@raindrop-ai/pi-agent 0.0.2 → 0.0.4

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.
@@ -79,6 +79,11 @@ type EventShipperOptions = {
79
79
  libraryName?: string;
80
80
  libraryVersion?: string;
81
81
  defaultEventName?: string;
82
+ /**
83
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
84
+ * Pass `null` to opt out of all mirroring (including auto-detect).
85
+ */
86
+ localDebuggerUrl?: string | null;
82
87
  };
83
88
  declare class EventShipper {
84
89
  private baseUrl;
@@ -94,6 +99,8 @@ declare class EventShipper {
94
99
  private sticky;
95
100
  private timers;
96
101
  private inFlight;
102
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
103
+ private localDebuggerUrl;
97
104
  constructor(opts: EventShipperOptions);
98
105
  isDebugEnabled(): boolean;
99
106
  private authHeaders;
@@ -110,6 +117,23 @@ declare class EventShipper {
110
117
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
111
118
  private flushOne;
112
119
  }
120
+ /**
121
+ * Hook fired per OTLP span right before the span is shipped (to the Raindrop
122
+ * API and to a local debugger). Lets callers inspect, rewrite, or drop the
123
+ * entire span — not just individual attributes — which is more flexible than
124
+ * an attribute-level hook (you can rename attributes, add new ones, drop the
125
+ * span outright, etc.).
126
+ *
127
+ * Return values:
128
+ * - `undefined` or the same span: ship the span unchanged.
129
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
130
+ * - `null`: drop the span entirely from every ship path.
131
+ *
132
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
133
+ * If the hook throws, the span is dropped (fail-closed) so a buggy hook can
134
+ * never accidentally ship raw, un-redacted spans.
135
+ */
136
+ type TransformSpanHook = (span: OtlpSpan) => OtlpSpan | null | undefined;
113
137
 
114
138
  type InternalSpan = {
115
139
  ids: SpanIds;
@@ -130,6 +154,45 @@ type TraceShipperOptions = {
130
154
  sdkName?: string;
131
155
  serviceName?: string;
132
156
  serviceVersion?: string;
157
+ /**
158
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
159
+ * Pass `null` to opt out of all mirroring (including auto-detect).
160
+ */
161
+ localDebuggerUrl?: string | null;
162
+ /**
163
+ * Per-span hook that fires for every OTLP span right before the span is
164
+ * shipped (both to the Raindrop API and to a local debugger). Lets callers
165
+ * inspect, rewrite, or drop entire spans — rename attributes, add new ones,
166
+ * scrub additional secret-shaped values inside `ai.prompt.messages` /
167
+ * `ai.toolCall.args`, etc.
168
+ *
169
+ * Return values:
170
+ * - `undefined` or the same span reference: ship the span unchanged.
171
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
172
+ * - `null`: drop the span entirely from every ship path.
173
+ *
174
+ * The hook runs BEFORE the default redactor (which is the always-on floor
175
+ * for documented BYOK secrets). The default redactor still runs on the
176
+ * post-transform span unless `disableDefaultRedaction` is set, so even if
177
+ * a custom transform overlooks a secret-shaped attribute, the floor catches
178
+ * it.
179
+ *
180
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
181
+ * If the hook itself throws, the span is dropped (fail-closed) so a buggy
182
+ * hook can never accidentally ship raw, un-redacted spans.
183
+ */
184
+ transformSpan?: TransformSpanHook;
185
+ /**
186
+ * Disable the built-in default span transformer (which scrubs documented
187
+ * secret-shaped properties — `apiKey`, `secretAccessKey`, `privateKey`,
188
+ * etc. — inside `ai.request.providerOptions` and
189
+ * `ai.response.providerMetadata`).
190
+ *
191
+ * Default: `false` (i.e. default redaction is on). Setting this to `true`
192
+ * disables the floor entirely; provide a custom `transformSpan` if you
193
+ * still want some redaction in that case.
194
+ */
195
+ disableDefaultRedaction?: boolean;
133
196
  };
134
197
  declare class TraceShipper {
135
198
  private baseUrl;
@@ -147,9 +210,26 @@ declare class TraceShipper {
147
210
  private queue;
148
211
  private timer;
149
212
  private inFlight;
150
- /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
213
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
151
214
  private localDebuggerUrl;
215
+ private transformSpanHook;
216
+ private disableDefaultRedaction;
152
217
  constructor(opts: TraceShipperOptions);
218
+ /**
219
+ * Apply the user `transformSpan` hook (if any) followed by the default
220
+ * redactor (unless disabled). Returns either the (possibly new) span to
221
+ * ship, or `null` to drop the span entirely.
222
+ *
223
+ * Ordering: user hook runs first so callers can rewrite the span freely
224
+ * (rename attrs, add new ones, scrub things the default doesn't know
225
+ * about). The default redactor then runs on whatever the user produced,
226
+ * acting as the always-on floor for documented BYOK secrets. If the user
227
+ * sets `disableDefaultRedaction: true`, the floor is skipped.
228
+ *
229
+ * Fail-closed: if the user hook throws, the span is dropped — a buggy
230
+ * hook can never accidentally ship raw, un-redacted spans.
231
+ */
232
+ private redactSpan;
153
233
  isDebugEnabled(): boolean;
154
234
  private authHeaders;
155
235
  startSpan(args: {
@@ -163,6 +243,7 @@ declare class TraceShipper {
163
243
  attributes?: Array<OtlpKeyValue | undefined>;
164
244
  startTimeUnixNano?: string;
165
245
  }): InternalSpan;
246
+ private mirrorToLocalDebugger;
166
247
  endSpan(span: InternalSpan, extra?: {
167
248
  attributes?: InternalSpan["attributes"];
168
249
  error?: unknown;
@@ -79,6 +79,11 @@ type EventShipperOptions = {
79
79
  libraryName?: string;
80
80
  libraryVersion?: string;
81
81
  defaultEventName?: string;
82
+ /**
83
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
84
+ * Pass `null` to opt out of all mirroring (including auto-detect).
85
+ */
86
+ localDebuggerUrl?: string | null;
82
87
  };
83
88
  declare class EventShipper {
84
89
  private baseUrl;
@@ -94,6 +99,8 @@ declare class EventShipper {
94
99
  private sticky;
95
100
  private timers;
96
101
  private inFlight;
102
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
103
+ private localDebuggerUrl;
97
104
  constructor(opts: EventShipperOptions);
98
105
  isDebugEnabled(): boolean;
99
106
  private authHeaders;
@@ -110,6 +117,23 @@ declare class EventShipper {
110
117
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
111
118
  private flushOne;
112
119
  }
120
+ /**
121
+ * Hook fired per OTLP span right before the span is shipped (to the Raindrop
122
+ * API and to a local debugger). Lets callers inspect, rewrite, or drop the
123
+ * entire span — not just individual attributes — which is more flexible than
124
+ * an attribute-level hook (you can rename attributes, add new ones, drop the
125
+ * span outright, etc.).
126
+ *
127
+ * Return values:
128
+ * - `undefined` or the same span: ship the span unchanged.
129
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
130
+ * - `null`: drop the span entirely from every ship path.
131
+ *
132
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
133
+ * If the hook throws, the span is dropped (fail-closed) so a buggy hook can
134
+ * never accidentally ship raw, un-redacted spans.
135
+ */
136
+ type TransformSpanHook = (span: OtlpSpan) => OtlpSpan | null | undefined;
113
137
 
114
138
  type InternalSpan = {
115
139
  ids: SpanIds;
@@ -130,6 +154,45 @@ type TraceShipperOptions = {
130
154
  sdkName?: string;
131
155
  serviceName?: string;
132
156
  serviceVersion?: string;
157
+ /**
158
+ * Explicit Workshop / local debugger URL. Wins over env vars + auto-detect.
159
+ * Pass `null` to opt out of all mirroring (including auto-detect).
160
+ */
161
+ localDebuggerUrl?: string | null;
162
+ /**
163
+ * Per-span hook that fires for every OTLP span right before the span is
164
+ * shipped (both to the Raindrop API and to a local debugger). Lets callers
165
+ * inspect, rewrite, or drop entire spans — rename attributes, add new ones,
166
+ * scrub additional secret-shaped values inside `ai.prompt.messages` /
167
+ * `ai.toolCall.args`, etc.
168
+ *
169
+ * Return values:
170
+ * - `undefined` or the same span reference: ship the span unchanged.
171
+ * - a new `OtlpSpan`: ship the returned span in place of the original.
172
+ * - `null`: drop the span entirely from every ship path.
173
+ *
174
+ * The hook runs BEFORE the default redactor (which is the always-on floor
175
+ * for documented BYOK secrets). The default redactor still runs on the
176
+ * post-transform span unless `disableDefaultRedaction` is set, so even if
177
+ * a custom transform overlooks a secret-shaped attribute, the floor catches
178
+ * it.
179
+ *
180
+ * The hook runs on the hot path — keep it synchronous and side-effect-free.
181
+ * If the hook itself throws, the span is dropped (fail-closed) so a buggy
182
+ * hook can never accidentally ship raw, un-redacted spans.
183
+ */
184
+ transformSpan?: TransformSpanHook;
185
+ /**
186
+ * Disable the built-in default span transformer (which scrubs documented
187
+ * secret-shaped properties — `apiKey`, `secretAccessKey`, `privateKey`,
188
+ * etc. — inside `ai.request.providerOptions` and
189
+ * `ai.response.providerMetadata`).
190
+ *
191
+ * Default: `false` (i.e. default redaction is on). Setting this to `true`
192
+ * disables the floor entirely; provide a custom `transformSpan` if you
193
+ * still want some redaction in that case.
194
+ */
195
+ disableDefaultRedaction?: boolean;
133
196
  };
134
197
  declare class TraceShipper {
135
198
  private baseUrl;
@@ -147,9 +210,26 @@ declare class TraceShipper {
147
210
  private queue;
148
211
  private timer;
149
212
  private inFlight;
150
- /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
213
+ /** URL of the local debugger / Workshop daemon, when one is reachable. */
151
214
  private localDebuggerUrl;
215
+ private transformSpanHook;
216
+ private disableDefaultRedaction;
152
217
  constructor(opts: TraceShipperOptions);
218
+ /**
219
+ * Apply the user `transformSpan` hook (if any) followed by the default
220
+ * redactor (unless disabled). Returns either the (possibly new) span to
221
+ * ship, or `null` to drop the span entirely.
222
+ *
223
+ * Ordering: user hook runs first so callers can rewrite the span freely
224
+ * (rename attrs, add new ones, scrub things the default doesn't know
225
+ * about). The default redactor then runs on whatever the user produced,
226
+ * acting as the always-on floor for documented BYOK secrets. If the user
227
+ * sets `disableDefaultRedaction: true`, the floor is skipped.
228
+ *
229
+ * Fail-closed: if the user hook throws, the span is dropped — a buggy
230
+ * hook can never accidentally ship raw, un-redacted spans.
231
+ */
232
+ private redactSpan;
153
233
  isDebugEnabled(): boolean;
154
234
  private authHeaders;
155
235
  startSpan(args: {
@@ -163,6 +243,7 @@ declare class TraceShipper {
163
243
  attributes?: Array<OtlpKeyValue | undefined>;
164
244
  startTimeUnixNano?: string;
165
245
  }): InternalSpan;
246
+ private mirrorToLocalDebugger;
166
247
  endSpan(span: InternalSpan, extra?: {
167
248
  attributes?: InternalSpan["attributes"];
168
249
  error?: unknown;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { Agent } from '@mariozechner/pi-agent-core';
2
- import { A as Attachment } from './index.d-npTVS9Mf.cjs';
1
+ import { Agent } from '@earendil-works/pi-agent-core';
2
+ import { A as Attachment } from './index.d-Cxs_NTx0.cjs';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
@@ -20,6 +20,14 @@ interface RaindropPiAgentOptions {
20
20
  eventName?: string;
21
21
  /** Default properties attached to every event */
22
22
  properties?: Record<string, unknown>;
23
+ /**
24
+ * Explicit Workshop / local debugger URL forwarded to both shippers as
25
+ * their `localDebuggerUrl`. `null` opts out (overrides
26
+ * `RAINDROP_LOCAL_DEBUGGER` / `RAINDROP_WORKSHOP` env vars and
27
+ * auto-detect). `undefined` falls through to the env / auto-detect
28
+ * resolution in `@raindrop-ai/core`.
29
+ */
30
+ localWorkshopUrl?: string | null;
23
31
  /** Trace shipping configuration */
24
32
  traces?: {
25
33
  /** Enable trace shipping (default: true) */
@@ -117,11 +125,11 @@ interface RaindropPiAgentClient {
117
125
  *
118
126
  * @example
119
127
  * ```typescript
120
- * import { Agent } from "@mariozechner/pi-agent-core";
128
+ * import { Agent } from "@earendil-works/pi-agent-core";
121
129
  * import { createRaindropPiAgent } from "@raindrop-ai/pi-agent";
122
130
  *
123
131
  * const raindrop = createRaindropPiAgent({
124
- * writeKey: "rk_...",
132
+ * writeKey: "your-write-key",
125
133
  * userId: "user-123",
126
134
  * convoId: "session-abc",
127
135
  * });
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Agent } from '@mariozechner/pi-agent-core';
2
- import { A as Attachment } from './index.d-npTVS9Mf.js';
1
+ import { Agent } from '@earendil-works/pi-agent-core';
2
+ import { A as Attachment } from './index.d-Cxs_NTx0.js';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
@@ -20,6 +20,14 @@ interface RaindropPiAgentOptions {
20
20
  eventName?: string;
21
21
  /** Default properties attached to every event */
22
22
  properties?: Record<string, unknown>;
23
+ /**
24
+ * Explicit Workshop / local debugger URL forwarded to both shippers as
25
+ * their `localDebuggerUrl`. `null` opts out (overrides
26
+ * `RAINDROP_LOCAL_DEBUGGER` / `RAINDROP_WORKSHOP` env vars and
27
+ * auto-detect). `undefined` falls through to the env / auto-detect
28
+ * resolution in `@raindrop-ai/core`.
29
+ */
30
+ localWorkshopUrl?: string | null;
23
31
  /** Trace shipping configuration */
24
32
  traces?: {
25
33
  /** Enable trace shipping (default: true) */
@@ -117,11 +125,11 @@ interface RaindropPiAgentClient {
117
125
  *
118
126
  * @example
119
127
  * ```typescript
120
- * import { Agent } from "@mariozechner/pi-agent-core";
128
+ * import { Agent } from "@earendil-works/pi-agent-core";
121
129
  * import { createRaindropPiAgent } from "@raindrop-ai/pi-agent";
122
130
  *
123
131
  * const raindrop = createRaindropPiAgent({
124
- * writeKey: "rk_...",
132
+ * writeKey: "your-write-key",
125
133
  * userId: "user-123",
126
134
  * convoId: "session-abc",
127
135
  * });
package/dist/index.js CHANGED
@@ -13,9 +13,10 @@ import {
13
13
  getUsername,
14
14
  libraryVersion,
15
15
  randomUUID,
16
+ resolveLocalDebuggerBaseUrl,
16
17
  safeStringify,
17
18
  truncate
18
- } from "./chunk-LZIGXU2D.js";
19
+ } from "./chunk-EWIO36KH.js";
19
20
 
20
21
  // src/internal/subscriber.ts
21
22
  function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, options, debug) {
@@ -376,23 +377,26 @@ function envDebugEnabled() {
376
377
  function createRaindropPiAgent(opts) {
377
378
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
378
379
  const hasWriteKey = typeof opts.writeKey === "string" && opts.writeKey.trim().length > 0;
380
+ const resolvedLocalUrl = resolveLocalDebuggerBaseUrl(opts.localWorkshopUrl);
381
+ const hasLocalDestination = resolvedLocalUrl !== null;
379
382
  const eventsEnabled = ((_a = opts.events) == null ? void 0 : _a.enabled) !== false;
380
383
  const tracesEnabled = ((_b = opts.traces) == null ? void 0 : _b.enabled) !== false;
381
- if (!hasWriteKey && !opts.endpoint) {
384
+ if (!hasWriteKey && !opts.endpoint && !hasLocalDestination) {
382
385
  console.warn(
383
386
  "[raindrop-ai/pi-agent] writeKey not provided; telemetry shipping is disabled"
384
387
  );
385
388
  }
386
389
  const envDebug = envDebugEnabled();
387
390
  const debug = ((_c = opts.events) == null ? void 0 : _c.debug) === true || ((_d = opts.traces) == null ? void 0 : _d.debug) === true || envDebug;
388
- const eventShipper = eventsEnabled && (hasWriteKey || opts.endpoint) ? new EventShipper({
391
+ const eventShipper = eventsEnabled && (hasWriteKey || opts.endpoint || hasLocalDestination) ? new EventShipper({
389
392
  writeKey: opts.writeKey,
390
393
  endpoint: opts.endpoint,
391
394
  enabled: true,
392
395
  debug: ((_e = opts.events) == null ? void 0 : _e.debug) === true || envDebug,
393
- partialFlushMs: (_f = opts.events) == null ? void 0 : _f.partialFlushMs
396
+ partialFlushMs: (_f = opts.events) == null ? void 0 : _f.partialFlushMs,
397
+ localDebuggerUrl: opts.localWorkshopUrl
394
398
  }) : null;
395
- const traceShipper = tracesEnabled && (hasWriteKey || opts.endpoint) ? new TraceShipper({
399
+ const traceShipper = tracesEnabled && (hasWriteKey || opts.endpoint || hasLocalDestination) ? new TraceShipper({
396
400
  writeKey: opts.writeKey,
397
401
  endpoint: opts.endpoint,
398
402
  enabled: true,
@@ -400,7 +404,8 @@ function createRaindropPiAgent(opts) {
400
404
  debugSpans: ((_h = opts.traces) == null ? void 0 : _h.debugSpans) === true || envDebug,
401
405
  flushIntervalMs: (_i = opts.traces) == null ? void 0 : _i.flushIntervalMs,
402
406
  maxBatchSize: (_j = opts.traces) == null ? void 0 : _j.maxBatchSize,
403
- maxQueueSize: (_k = opts.traces) == null ? void 0 : _k.maxQueueSize
407
+ maxQueueSize: (_k = opts.traces) == null ? void 0 : _k.maxQueueSize,
408
+ localDebuggerUrl: opts.localWorkshopUrl
404
409
  }) : null;
405
410
  const defaultOptions = {
406
411
  userId: opts.userId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/pi-agent",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
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",
@@ -42,31 +42,24 @@
42
42
  "dist/**",
43
43
  "README.md"
44
44
  ],
45
- "scripts": {
46
- "build": "tsup",
47
- "dev": "tsup --watch",
48
- "clean": "rm -rf dist",
49
- "test": "vitest run",
50
- "test:watch": "vitest"
51
- },
52
45
  "peerDependencies": {
53
- "@mariozechner/pi-agent-core": ">=0.60.0",
54
- "@mariozechner/pi-coding-agent": ">=0.65.2"
46
+ "@earendil-works/pi-agent-core": ">=0.74.0",
47
+ "@earendil-works/pi-coding-agent": ">=0.74.0"
55
48
  },
56
49
  "peerDependenciesMeta": {
57
- "@mariozechner/pi-coding-agent": {
50
+ "@earendil-works/pi-coding-agent": {
58
51
  "optional": true
59
52
  }
60
53
  },
61
54
  "devDependencies": {
62
- "@raindrop-ai/core": "workspace:*",
63
- "@mariozechner/pi-agent-core": "^0.66.0",
64
- "@mariozechner/pi-coding-agent": "^0.66.0",
55
+ "@earendil-works/pi-agent-core": "^0.78.0",
56
+ "@earendil-works/pi-coding-agent": "^0.78.0",
65
57
  "@types/node": "^20.11.17",
66
58
  "msw": "^2.12.7",
67
59
  "tsup": "^8.5.1",
68
60
  "typescript": "^5.7.3",
69
- "vitest": "^2.1.9"
61
+ "vitest": "^2.1.9",
62
+ "@raindrop-ai/core": "0.0.2"
70
63
  },
71
64
  "tsup": {
72
65
  "entry": [
@@ -87,5 +80,12 @@
87
80
  },
88
81
  "publishConfig": {
89
82
  "access": "public"
83
+ },
84
+ "scripts": {
85
+ "build": "tsup",
86
+ "dev": "tsup --watch",
87
+ "clean": "rm -rf dist",
88
+ "test": "vitest run",
89
+ "test:watch": "vitest"
90
90
  }
91
- }
91
+ }