@raindrop-ai/deep-agents 0.0.1 → 0.0.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Raindrop AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -97,7 +97,7 @@ The `createRaindropDeepAgents()` factory returns:
97
97
  - **Streaming**: Token-by-token streaming events are not captured individually; only the final aggregated response is tracked.
98
98
  - **Subagent isolation**: When using the `task` tool for subagent delegation, each subagent's callbacks fire independently.
99
99
  - **Concurrent invocations on a shared handler**: A single handler instance keeps one in-flight span map at a time. Running multiple `agent.invoke(...)` calls **concurrently with the same handler** (e.g. `Promise.all([agent.invoke(...), agent.invoke(...)])` with the same `raindrop.handler`) can scramble the linkage between events and traces. Instantiate one `createRaindropDeepAgents()` per concurrent request; sequential invocations on a shared handler are fully supported.
100
- - **Long chain inputs/outputs are truncated**: Chain-level `input` and `output` captured on the root event are truncated to ~8 KB to stay within the SDK's payload-size limit. Per-LLM child events still carry full prompts.
100
+ - **Long chain inputs/outputs are truncated**: Chain-level `input` and `output` captured on the root event are truncated to ~8 KB to stay within the SDK's payload-size limit. Per-LLM child events still carry full prompts. Tool payloads are pruned to their cap _before_ JSON serialization, so a multi-MB tool output costs the cap — not the payload — on your event loop (truncated values carry a `...[truncated by raindrop]` marker).
101
101
 
102
102
  ## Testing
103
103
 
package/dist/index.d.mts CHANGED
@@ -42,7 +42,6 @@ type SpanIds = {
42
42
  spanIdB64: string;
43
43
  parentSpanIdB64?: string;
44
44
  };
45
-
46
45
  type Attachment = {
47
46
  type: string;
48
47
  role: string;
@@ -86,6 +85,26 @@ type EventShipperOptions = {
86
85
  libraryName?: string;
87
86
  libraryVersion?: string;
88
87
  defaultEventName?: string;
88
+ /**
89
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
90
+ * Pass `null` to opt out of all mirroring (including auto-detect).
91
+ */
92
+ localDebuggerUrl?: string | null;
93
+ /**
94
+ * Optional project slug. When set, every outbound cloud request includes an
95
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
96
+ * values are ignored. Slug format is validated on construction but never
97
+ * throws — the backend returns 400 on invalid values.
98
+ */
99
+ projectId?: string;
100
+ /**
101
+ * Per-field character cap applied to event input/output BEFORE buffering
102
+ * or serialization, so oversized payloads cost the cap — not the payload —
103
+ * on the calling code path. Truncated fields end with
104
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
105
+ * Defaults to 1,000,000 (matching the Python SDK).
106
+ */
107
+ maxTextFieldChars?: number;
89
108
  };
90
109
  declare class EventShipper {
91
110
  private baseUrl;
@@ -96,14 +115,46 @@ declare class EventShipper {
96
115
  private sdkName;
97
116
  private prefix;
98
117
  private defaultEventName;
118
+ private projectId;
99
119
  private context;
100
120
  private buffers;
101
121
  private sticky;
102
122
  private timers;
103
123
  private inFlight;
124
+ private maxTextFieldCharsOpt;
125
+ /**
126
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
127
+ * Checked before every POST issued during the final flush.
128
+ */
129
+ private shutdownDeadlineAt;
130
+ /**
131
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
132
+ * drain window (stragglers, or flush work the deadline abandoned
133
+ * mid-drain) run as a single short attempt instead of regaining the full
134
+ * retry schedule.
135
+ */
136
+ private hasShutdown;
137
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
138
+ private localDebuggerUrl;
104
139
  constructor(opts: EventShipperOptions);
105
140
  isDebugEnabled(): boolean;
106
141
  private authHeaders;
142
+ private requestHeaders;
143
+ /**
144
+ * Build the retry/timeout options for one POST, honoring the shutdown
145
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
146
+ * the caller must drop the payload (with a rate-limited warning) instead
147
+ * of issuing a request that could outlive process exit.
148
+ *
149
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
150
+ * path is mid-drain takes effect immediately: no further retries, and the
151
+ * per-attempt timeout is clamped to the remaining window. After
152
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
153
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
154
+ * run as a single short attempt rather than regaining the full retry
155
+ * schedule.
156
+ */
157
+ private requestOpts;
107
158
  patch(eventId: string, patch: Patch): Promise<void>;
108
159
  finish(eventId: string, patch: {
109
160
  output?: string;
@@ -115,8 +166,26 @@ declare class EventShipper {
115
166
  shutdown(): Promise<void>;
116
167
  trackSignal(signal: SignalInput): Promise<void>;
117
168
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
169
+ private warnShutdownDrop;
118
170
  private flushOne;
119
171
  }
172
+ /**
173
+ * Hook fired per OTLP span right before the span is shipped (to the Raindrop
174
+ * API and to a local debugger). Lets callers inspect, rewrite, or drop the
175
+ * entire span — not just individual attributes — which is more flexible than
176
+ * an attribute-level hook (you can rename attributes, add new ones, drop the
177
+ * span outright, etc.).
178
+ *
179
+ * Return values:
180
+ * - `undefined` or the same span: ship the span unchanged.
181
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
182
+ * - `null`: drop the span entirely from every ship path.
183
+ *
184
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
185
+ * If the hook throws, the span is dropped (fail-closed) so a buggy hook can
186
+ * never accidentally ship raw, un-redacted spans.
187
+ */
188
+ type TransformSpanHook = (span: OtlpSpan) => OtlpSpan | null | undefined;
120
189
 
121
190
  type InternalSpan = {
122
191
  ids: SpanIds;
@@ -137,6 +206,61 @@ type TraceShipperOptions = {
137
206
  sdkName?: string;
138
207
  serviceName?: string;
139
208
  serviceVersion?: string;
209
+ /**
210
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
211
+ * Pass `null` to opt out of all mirroring (including auto-detect).
212
+ */
213
+ localDebuggerUrl?: string | null;
214
+ /**
215
+ * Optional project slug. When set, every OTLP trace export includes an
216
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
217
+ * values are ignored. Slug format is validated on construction but never
218
+ * throws — the backend returns 400 on invalid values.
219
+ */
220
+ projectId?: string;
221
+ /**
222
+ * Per-span hook that fires for every OTLP span right before the span is
223
+ * shipped (both to the Raindrop API and to a local debugger). Lets callers
224
+ * inspect, rewrite, or drop entire spans — rename attributes, add new ones,
225
+ * scrub additional secret-shaped values inside `ai.prompt.messages` /
226
+ * `ai.toolCall.args`, etc.
227
+ *
228
+ * Return values:
229
+ * - `undefined` or the same span reference: ship the span unchanged.
230
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
231
+ * - `null`: drop the span entirely from every ship path.
232
+ *
233
+ * The hook runs BEFORE the default redactor (which is the always-on floor
234
+ * for documented BYOK secrets). The default redactor still runs on the
235
+ * post-transform span unless `disableDefaultRedaction` is set, so even if
236
+ * a custom transform overlooks a secret-shaped attribute, the floor catches
237
+ * it.
238
+ *
239
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
240
+ * If the hook itself throws, the span is dropped (fail-closed) so a buggy
241
+ * hook can never accidentally ship raw, un-redacted spans.
242
+ */
243
+ transformSpan?: TransformSpanHook;
244
+ /**
245
+ * Disable the built-in default span transformer (which scrubs documented
246
+ * secret-shaped properties — `apiKey`, `secretAccessKey`, `privateKey`,
247
+ * etc. — inside `ai.request.providerOptions` and
248
+ * `ai.response.providerMetadata`).
249
+ *
250
+ * Default: `false` (i.e. default redaction is on). Setting this to `true`
251
+ * disables the floor entirely; provide a custom `transformSpan` if you
252
+ * still want some redaction in that case.
253
+ */
254
+ disableDefaultRedaction?: boolean;
255
+ /**
256
+ * Per-attribute character cap applied to every span attribute string value
257
+ * right before the span enters a ship path, so a multi-MB prompt/tool
258
+ * payload can never make the batch `JSON.stringify` (which runs on the
259
+ * event loop) cost seconds. Truncated values end with
260
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
261
+ * Defaults to 1,000,000 (matching the Python SDK).
262
+ */
263
+ maxTextFieldChars?: number;
140
264
  };
141
265
  declare class TraceShipper {
142
266
  private baseUrl;
@@ -151,14 +275,58 @@ declare class TraceShipper {
151
275
  private flushIntervalMs;
152
276
  private maxBatchSize;
153
277
  private maxQueueSize;
278
+ private projectId;
154
279
  private queue;
155
280
  private timer;
156
281
  private inFlight;
157
- /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
282
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
158
283
  private localDebuggerUrl;
284
+ private transformSpanHook;
285
+ private disableDefaultRedaction;
286
+ private maxTextFieldCharsOpt;
287
+ /**
288
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
289
+ * Checked before every batch POST issued during the final flush.
290
+ */
291
+ private shutdownDeadlineAt;
292
+ /**
293
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
294
+ * drain window (stragglers, or flush work the deadline abandoned
295
+ * mid-drain) run as a single short attempt instead of regaining the full
296
+ * retry schedule.
297
+ */
298
+ private hasShutdown;
159
299
  constructor(opts: TraceShipperOptions);
300
+ /**
301
+ * Cap every string attribute value on the span. O(#attributes) length
302
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
303
+ * pipeline so the default secret-scrub still sees parseable JSON in
304
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
305
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
306
+ * in the surviving prefix).
307
+ *
308
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
309
+ * for span content, matching the Python SDK and the OTel SDK convention.
310
+ */
311
+ private capSpanAttributes;
312
+ /**
313
+ * Apply the user `transformSpan` hook (if any) followed by the default
314
+ * redactor (unless disabled). Returns either the (possibly new) span to
315
+ * ship, or `null` to drop the span entirely.
316
+ *
317
+ * Ordering: user hook runs first so callers can rewrite the span freely
318
+ * (rename attrs, add new ones, scrub things the default doesn't know
319
+ * about). The default redactor then runs on whatever the user produced,
320
+ * acting as the always-on floor for documented BYOK secrets. If the user
321
+ * sets `disableDefaultRedaction: true`, the floor is skipped.
322
+ *
323
+ * Fail-closed: if the user hook throws, the span is dropped — a buggy
324
+ * hook can never accidentally ship raw, un-redacted spans.
325
+ */
326
+ private redactSpan;
160
327
  isDebugEnabled(): boolean;
161
328
  private authHeaders;
329
+ private requestHeaders;
162
330
  startSpan(args: {
163
331
  name: string;
164
332
  parent?: {
@@ -170,6 +338,7 @@ declare class TraceShipper {
170
338
  attributes?: Array<OtlpKeyValue | undefined>;
171
339
  startTimeUnixNano?: string;
172
340
  }): InternalSpan;
341
+ private mirrorToLocalDebugger;
173
342
  endSpan(span: InternalSpan, extra?: {
174
343
  attributes?: InternalSpan["attributes"];
175
344
  error?: unknown;
@@ -190,6 +359,8 @@ declare class TraceShipper {
190
359
  }): void;
191
360
  enqueue(span: OtlpSpan): void;
192
361
  flush(): Promise<void>;
362
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
363
+ private requestOpts;
193
364
  shutdown(): Promise<void>;
194
365
  }
195
366
 
@@ -274,6 +445,12 @@ interface DeepAgentsOptions {
274
445
  debug?: boolean;
275
446
  userId?: string;
276
447
  convoId?: string;
448
+ /**
449
+ * Optional Raindrop project slug. When set, every outbound cloud request
450
+ * carries an `X-Raindrop-Project-Id` header. Unset → no header (the project
451
+ * resolves to `default` server-side; byte-identical to prior behavior).
452
+ */
453
+ projectId?: string;
277
454
  traceChains?: boolean;
278
455
  }
279
456
  type RaindropDeepAgentsClient = {
package/dist/index.d.ts CHANGED
@@ -42,7 +42,6 @@ type SpanIds = {
42
42
  spanIdB64: string;
43
43
  parentSpanIdB64?: string;
44
44
  };
45
-
46
45
  type Attachment = {
47
46
  type: string;
48
47
  role: string;
@@ -86,6 +85,26 @@ type EventShipperOptions = {
86
85
  libraryName?: string;
87
86
  libraryVersion?: string;
88
87
  defaultEventName?: string;
88
+ /**
89
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
90
+ * Pass `null` to opt out of all mirroring (including auto-detect).
91
+ */
92
+ localDebuggerUrl?: string | null;
93
+ /**
94
+ * Optional project slug. When set, every outbound cloud request includes an
95
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
96
+ * values are ignored. Slug format is validated on construction but never
97
+ * throws — the backend returns 400 on invalid values.
98
+ */
99
+ projectId?: string;
100
+ /**
101
+ * Per-field character cap applied to event input/output BEFORE buffering
102
+ * or serialization, so oversized payloads cost the cap — not the payload —
103
+ * on the calling code path. Truncated fields end with
104
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
105
+ * Defaults to 1,000,000 (matching the Python SDK).
106
+ */
107
+ maxTextFieldChars?: number;
89
108
  };
90
109
  declare class EventShipper {
91
110
  private baseUrl;
@@ -96,14 +115,46 @@ declare class EventShipper {
96
115
  private sdkName;
97
116
  private prefix;
98
117
  private defaultEventName;
118
+ private projectId;
99
119
  private context;
100
120
  private buffers;
101
121
  private sticky;
102
122
  private timers;
103
123
  private inFlight;
124
+ private maxTextFieldCharsOpt;
125
+ /**
126
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
127
+ * Checked before every POST issued during the final flush.
128
+ */
129
+ private shutdownDeadlineAt;
130
+ /**
131
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
132
+ * drain window (stragglers, or flush work the deadline abandoned
133
+ * mid-drain) run as a single short attempt instead of regaining the full
134
+ * retry schedule.
135
+ */
136
+ private hasShutdown;
137
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
138
+ private localDebuggerUrl;
104
139
  constructor(opts: EventShipperOptions);
105
140
  isDebugEnabled(): boolean;
106
141
  private authHeaders;
142
+ private requestHeaders;
143
+ /**
144
+ * Build the retry/timeout options for one POST, honoring the shutdown
145
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
146
+ * the caller must drop the payload (with a rate-limited warning) instead
147
+ * of issuing a request that could outlive process exit.
148
+ *
149
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
150
+ * path is mid-drain takes effect immediately: no further retries, and the
151
+ * per-attempt timeout is clamped to the remaining window. After
152
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
153
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
154
+ * run as a single short attempt rather than regaining the full retry
155
+ * schedule.
156
+ */
157
+ private requestOpts;
107
158
  patch(eventId: string, patch: Patch): Promise<void>;
108
159
  finish(eventId: string, patch: {
109
160
  output?: string;
@@ -115,8 +166,26 @@ declare class EventShipper {
115
166
  shutdown(): Promise<void>;
116
167
  trackSignal(signal: SignalInput): Promise<void>;
117
168
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
169
+ private warnShutdownDrop;
118
170
  private flushOne;
119
171
  }
172
+ /**
173
+ * Hook fired per OTLP span right before the span is shipped (to the Raindrop
174
+ * API and to a local debugger). Lets callers inspect, rewrite, or drop the
175
+ * entire span — not just individual attributes — which is more flexible than
176
+ * an attribute-level hook (you can rename attributes, add new ones, drop the
177
+ * span outright, etc.).
178
+ *
179
+ * Return values:
180
+ * - `undefined` or the same span: ship the span unchanged.
181
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
182
+ * - `null`: drop the span entirely from every ship path.
183
+ *
184
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
185
+ * If the hook throws, the span is dropped (fail-closed) so a buggy hook can
186
+ * never accidentally ship raw, un-redacted spans.
187
+ */
188
+ type TransformSpanHook = (span: OtlpSpan) => OtlpSpan | null | undefined;
120
189
 
121
190
  type InternalSpan = {
122
191
  ids: SpanIds;
@@ -137,6 +206,61 @@ type TraceShipperOptions = {
137
206
  sdkName?: string;
138
207
  serviceName?: string;
139
208
  serviceVersion?: string;
209
+ /**
210
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
211
+ * Pass `null` to opt out of all mirroring (including auto-detect).
212
+ */
213
+ localDebuggerUrl?: string | null;
214
+ /**
215
+ * Optional project slug. When set, every OTLP trace export includes an
216
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
217
+ * values are ignored. Slug format is validated on construction but never
218
+ * throws — the backend returns 400 on invalid values.
219
+ */
220
+ projectId?: string;
221
+ /**
222
+ * Per-span hook that fires for every OTLP span right before the span is
223
+ * shipped (both to the Raindrop API and to a local debugger). Lets callers
224
+ * inspect, rewrite, or drop entire spans — rename attributes, add new ones,
225
+ * scrub additional secret-shaped values inside `ai.prompt.messages` /
226
+ * `ai.toolCall.args`, etc.
227
+ *
228
+ * Return values:
229
+ * - `undefined` or the same span reference: ship the span unchanged.
230
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
231
+ * - `null`: drop the span entirely from every ship path.
232
+ *
233
+ * The hook runs BEFORE the default redactor (which is the always-on floor
234
+ * for documented BYOK secrets). The default redactor still runs on the
235
+ * post-transform span unless `disableDefaultRedaction` is set, so even if
236
+ * a custom transform overlooks a secret-shaped attribute, the floor catches
237
+ * it.
238
+ *
239
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
240
+ * If the hook itself throws, the span is dropped (fail-closed) so a buggy
241
+ * hook can never accidentally ship raw, un-redacted spans.
242
+ */
243
+ transformSpan?: TransformSpanHook;
244
+ /**
245
+ * Disable the built-in default span transformer (which scrubs documented
246
+ * secret-shaped properties — `apiKey`, `secretAccessKey`, `privateKey`,
247
+ * etc. — inside `ai.request.providerOptions` and
248
+ * `ai.response.providerMetadata`).
249
+ *
250
+ * Default: `false` (i.e. default redaction is on). Setting this to `true`
251
+ * disables the floor entirely; provide a custom `transformSpan` if you
252
+ * still want some redaction in that case.
253
+ */
254
+ disableDefaultRedaction?: boolean;
255
+ /**
256
+ * Per-attribute character cap applied to every span attribute string value
257
+ * right before the span enters a ship path, so a multi-MB prompt/tool
258
+ * payload can never make the batch `JSON.stringify` (which runs on the
259
+ * event loop) cost seconds. Truncated values end with
260
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
261
+ * Defaults to 1,000,000 (matching the Python SDK).
262
+ */
263
+ maxTextFieldChars?: number;
140
264
  };
141
265
  declare class TraceShipper {
142
266
  private baseUrl;
@@ -151,14 +275,58 @@ declare class TraceShipper {
151
275
  private flushIntervalMs;
152
276
  private maxBatchSize;
153
277
  private maxQueueSize;
278
+ private projectId;
154
279
  private queue;
155
280
  private timer;
156
281
  private inFlight;
157
- /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
282
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
158
283
  private localDebuggerUrl;
284
+ private transformSpanHook;
285
+ private disableDefaultRedaction;
286
+ private maxTextFieldCharsOpt;
287
+ /**
288
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
289
+ * Checked before every batch POST issued during the final flush.
290
+ */
291
+ private shutdownDeadlineAt;
292
+ /**
293
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
294
+ * drain window (stragglers, or flush work the deadline abandoned
295
+ * mid-drain) run as a single short attempt instead of regaining the full
296
+ * retry schedule.
297
+ */
298
+ private hasShutdown;
159
299
  constructor(opts: TraceShipperOptions);
300
+ /**
301
+ * Cap every string attribute value on the span. O(#attributes) length
302
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
303
+ * pipeline so the default secret-scrub still sees parseable JSON in
304
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
305
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
306
+ * in the surviving prefix).
307
+ *
308
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
309
+ * for span content, matching the Python SDK and the OTel SDK convention.
310
+ */
311
+ private capSpanAttributes;
312
+ /**
313
+ * Apply the user `transformSpan` hook (if any) followed by the default
314
+ * redactor (unless disabled). Returns either the (possibly new) span to
315
+ * ship, or `null` to drop the span entirely.
316
+ *
317
+ * Ordering: user hook runs first so callers can rewrite the span freely
318
+ * (rename attrs, add new ones, scrub things the default doesn't know
319
+ * about). The default redactor then runs on whatever the user produced,
320
+ * acting as the always-on floor for documented BYOK secrets. If the user
321
+ * sets `disableDefaultRedaction: true`, the floor is skipped.
322
+ *
323
+ * Fail-closed: if the user hook throws, the span is dropped — a buggy
324
+ * hook can never accidentally ship raw, un-redacted spans.
325
+ */
326
+ private redactSpan;
160
327
  isDebugEnabled(): boolean;
161
328
  private authHeaders;
329
+ private requestHeaders;
162
330
  startSpan(args: {
163
331
  name: string;
164
332
  parent?: {
@@ -170,6 +338,7 @@ declare class TraceShipper {
170
338
  attributes?: Array<OtlpKeyValue | undefined>;
171
339
  startTimeUnixNano?: string;
172
340
  }): InternalSpan;
341
+ private mirrorToLocalDebugger;
173
342
  endSpan(span: InternalSpan, extra?: {
174
343
  attributes?: InternalSpan["attributes"];
175
344
  error?: unknown;
@@ -190,6 +359,8 @@ declare class TraceShipper {
190
359
  }): void;
191
360
  enqueue(span: OtlpSpan): void;
192
361
  flush(): Promise<void>;
362
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
363
+ private requestOpts;
193
364
  shutdown(): Promise<void>;
194
365
  }
195
366
 
@@ -274,6 +445,12 @@ interface DeepAgentsOptions {
274
445
  debug?: boolean;
275
446
  userId?: string;
276
447
  convoId?: string;
448
+ /**
449
+ * Optional Raindrop project slug. When set, every outbound cloud request
450
+ * carries an `X-Raindrop-Project-Id` header. Unset → no header (the project
451
+ * resolves to `default` server-side; byte-identical to prior behavior).
452
+ */
453
+ projectId?: string;
277
454
  traceChains?: boolean;
278
455
  }
279
456
  type RaindropDeepAgentsClient = {