@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.
- package/LICENSE +21 -0
- package/README.md +5 -5
- package/dist/{chunk-LZIGXU2D.js → chunk-EWIO36KH.js} +353 -150
- package/dist/extension.cjs +418 -197
- package/dist/extension.d.cts +12 -2
- package/dist/extension.d.ts +12 -2
- package/dist/extension.js +27 -7
- package/dist/index.cjs +269 -63
- package/dist/{index.d-npTVS9Mf.d.cts → index.d-Cxs_NTx0.d.cts} +82 -1
- package/dist/{index.d-npTVS9Mf.d.ts → index.d-Cxs_NTx0.d.ts} +82 -1
- package/dist/index.d.cts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +11 -6
- package/package.json +16 -16
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @raindrop-ai/pi-agent
|
|
2
2
|
|
|
3
|
-
Automatic observability for [Pi Agent](https://github.com/
|
|
3
|
+
Automatic observability for [Pi Agent](https://github.com/earendil-works/pi) with [Raindrop](https://raindrop.ai). Captures agent runs, LLM generations, tool calls, and token usage.
|
|
4
4
|
|
|
5
5
|
Two entry points:
|
|
6
6
|
|
|
@@ -10,12 +10,12 @@ Two entry points:
|
|
|
10
10
|
## Quick Start — Programmatic
|
|
11
11
|
|
|
12
12
|
```typescript
|
|
13
|
-
import { Agent } from "@
|
|
14
|
-
import { getModel } from "@
|
|
13
|
+
import { Agent } from "@earendil-works/pi-agent-core";
|
|
14
|
+
import { getModel } from "@earendil-works/pi-ai";
|
|
15
15
|
import { createRaindropPiAgent } from "@raindrop-ai/pi-agent";
|
|
16
16
|
|
|
17
17
|
const raindrop = createRaindropPiAgent({
|
|
18
|
-
writeKey: "
|
|
18
|
+
writeKey: "your-write-key",
|
|
19
19
|
userId: "user-123",
|
|
20
20
|
});
|
|
21
21
|
|
|
@@ -41,7 +41,7 @@ Set `RAINDROP_WRITE_KEY` in your environment. Traces appear automatically.
|
|
|
41
41
|
|
|
42
42
|
## Documentation
|
|
43
43
|
|
|
44
|
-
See the full [Pi Agent docs](https://
|
|
44
|
+
See the full [Pi Agent docs](https://www.raindrop.ai/docs/integrations/pi-agent/) for configuration, per-subscribe overrides, and extension settings.
|
|
45
45
|
|
|
46
46
|
## License
|
|
47
47
|
|
|
@@ -1,101 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
var package_default = {
|
|
3
|
-
name: "@raindrop-ai/pi-agent",
|
|
4
|
-
version: "0.0.2",
|
|
5
|
-
description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
|
|
6
|
-
type: "module",
|
|
7
|
-
license: "MIT",
|
|
8
|
-
repository: {
|
|
9
|
-
type: "git",
|
|
10
|
-
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
11
|
-
directory: "packages/pi-agent"
|
|
12
|
-
},
|
|
13
|
-
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/pi-agent#readme",
|
|
14
|
-
bugs: {
|
|
15
|
-
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
16
|
-
},
|
|
17
|
-
keywords: [
|
|
18
|
-
"pi-package",
|
|
19
|
-
"raindrop",
|
|
20
|
-
"pi-agent",
|
|
21
|
-
"observability",
|
|
22
|
-
"tracing"
|
|
23
|
-
],
|
|
24
|
-
exports: {
|
|
25
|
-
".": {
|
|
26
|
-
types: "./dist/index.d.ts",
|
|
27
|
-
import: "./dist/index.js",
|
|
28
|
-
require: "./dist/index.cjs"
|
|
29
|
-
},
|
|
30
|
-
"./extension": {
|
|
31
|
-
types: "./dist/extension.d.ts",
|
|
32
|
-
import: "./dist/extension.js",
|
|
33
|
-
require: "./dist/extension.cjs"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
pi: {
|
|
37
|
-
extensions: [
|
|
38
|
-
"./dist/extension.js"
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
sideEffects: false,
|
|
42
|
-
files: [
|
|
43
|
-
"dist/**",
|
|
44
|
-
"README.md"
|
|
45
|
-
],
|
|
46
|
-
scripts: {
|
|
47
|
-
build: "tsup",
|
|
48
|
-
dev: "tsup --watch",
|
|
49
|
-
clean: "rm -rf dist",
|
|
50
|
-
test: "vitest run",
|
|
51
|
-
"test:watch": "vitest"
|
|
52
|
-
},
|
|
53
|
-
peerDependencies: {
|
|
54
|
-
"@mariozechner/pi-agent-core": ">=0.60.0",
|
|
55
|
-
"@mariozechner/pi-coding-agent": ">=0.65.2"
|
|
56
|
-
},
|
|
57
|
-
peerDependenciesMeta: {
|
|
58
|
-
"@mariozechner/pi-coding-agent": {
|
|
59
|
-
optional: true
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
devDependencies: {
|
|
63
|
-
"@raindrop-ai/core": "workspace:*",
|
|
64
|
-
"@mariozechner/pi-agent-core": "^0.66.0",
|
|
65
|
-
"@mariozechner/pi-coding-agent": "^0.66.0",
|
|
66
|
-
"@types/node": "^20.11.17",
|
|
67
|
-
msw: "^2.12.7",
|
|
68
|
-
tsup: "^8.5.1",
|
|
69
|
-
typescript: "^5.7.3",
|
|
70
|
-
vitest: "^2.1.9"
|
|
71
|
-
},
|
|
72
|
-
tsup: {
|
|
73
|
-
entry: [
|
|
74
|
-
"src/index.ts",
|
|
75
|
-
"src/extension.ts"
|
|
76
|
-
],
|
|
77
|
-
format: [
|
|
78
|
-
"cjs",
|
|
79
|
-
"esm"
|
|
80
|
-
],
|
|
81
|
-
dts: {
|
|
82
|
-
resolve: true
|
|
83
|
-
},
|
|
84
|
-
clean: true,
|
|
85
|
-
noExternal: [
|
|
86
|
-
"@raindrop-ai/core"
|
|
87
|
-
]
|
|
88
|
-
},
|
|
89
|
-
publishConfig: {
|
|
90
|
-
access: "public"
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// src/version.ts
|
|
95
|
-
var libraryName = package_default.name;
|
|
96
|
-
var libraryVersion = package_default.version;
|
|
97
|
-
|
|
98
|
-
// ../core/dist/chunk-4UCYIEH4.js
|
|
1
|
+
// ../core/dist/chunk-VUNUOE2X.js
|
|
99
2
|
function getCrypto() {
|
|
100
3
|
const c = globalThis.crypto;
|
|
101
4
|
return c;
|
|
@@ -299,6 +202,91 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
|
|
|
299
202
|
]
|
|
300
203
|
};
|
|
301
204
|
}
|
|
205
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
206
|
+
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
207
|
+
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
208
|
+
function readEnvVar(name) {
|
|
209
|
+
var _a;
|
|
210
|
+
try {
|
|
211
|
+
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
212
|
+
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
213
|
+
return env[name];
|
|
214
|
+
}
|
|
215
|
+
} catch (e) {
|
|
216
|
+
}
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
function readWorkshopEnv() {
|
|
220
|
+
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
221
|
+
if (raw === void 0) return void 0;
|
|
222
|
+
const trimmed = raw.trim();
|
|
223
|
+
if (trimmed.length === 0) return void 0;
|
|
224
|
+
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
225
|
+
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
226
|
+
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
function isLocalDevHost(hostname2) {
|
|
230
|
+
if (!hostname2) return false;
|
|
231
|
+
if (hostname2 === "localhost" || hostname2 === "127.0.0.1" || hostname2 === "0.0.0.0" || hostname2 === "::1") {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
if (hostname2.endsWith(".localhost")) return true;
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
function readRuntimeHostname() {
|
|
238
|
+
try {
|
|
239
|
+
const loc = globalThis == null ? void 0 : globalThis.location;
|
|
240
|
+
if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
|
|
241
|
+
return loc.hostname;
|
|
242
|
+
}
|
|
243
|
+
} catch (e) {
|
|
244
|
+
}
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
function shouldAutoEnableLocalWorkshop() {
|
|
248
|
+
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
249
|
+
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
253
|
+
var _a, _b, _c;
|
|
254
|
+
if (baseUrl === null) return null;
|
|
255
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
256
|
+
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
257
|
+
}
|
|
258
|
+
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
259
|
+
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
260
|
+
const workshopEnv = readWorkshopEnv();
|
|
261
|
+
if (workshopEnv === "disable") return null;
|
|
262
|
+
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
263
|
+
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
264
|
+
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
268
|
+
var _a;
|
|
269
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
270
|
+
if (!baseUrl) return;
|
|
271
|
+
void postJson(`${baseUrl}traces`, body, {}, {
|
|
272
|
+
maxAttempts: 1,
|
|
273
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
274
|
+
sdkName: options.sdkName
|
|
275
|
+
}).catch(() => {
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
279
|
+
var _a;
|
|
280
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
281
|
+
if (!baseUrl) return;
|
|
282
|
+
const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
|
|
283
|
+
void postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
284
|
+
maxAttempts: 1,
|
|
285
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
286
|
+
sdkName: options.sdkName
|
|
287
|
+
}).catch(() => {
|
|
288
|
+
});
|
|
289
|
+
}
|
|
302
290
|
function mergePatches(target, source) {
|
|
303
291
|
var _a, _b, _c, _d;
|
|
304
292
|
const out = { ...target, ...source };
|
|
@@ -316,7 +304,7 @@ var EventShipper = class {
|
|
|
316
304
|
this.sticky = /* @__PURE__ */ new Map();
|
|
317
305
|
this.timers = /* @__PURE__ */ new Map();
|
|
318
306
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
319
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
307
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
320
308
|
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
321
309
|
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
322
310
|
this.enabled = opts.enabled !== false;
|
|
@@ -325,11 +313,15 @@ var EventShipper = class {
|
|
|
325
313
|
this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
|
|
326
314
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
327
315
|
this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
|
|
316
|
+
this.localDebuggerUrl = (_f = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _f : void 0;
|
|
317
|
+
if (this.debug && this.localDebuggerUrl) {
|
|
318
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
319
|
+
}
|
|
328
320
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
329
321
|
this.context = {
|
|
330
322
|
library: {
|
|
331
|
-
name: (
|
|
332
|
-
version: (
|
|
323
|
+
name: (_g = opts.libraryName) != null ? _g : "@raindrop-ai/core",
|
|
324
|
+
version: (_h = opts.libraryVersion) != null ? _h : "0.0.0"
|
|
333
325
|
},
|
|
334
326
|
metadata: {
|
|
335
327
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -415,6 +407,7 @@ var EventShipper = class {
|
|
|
415
407
|
}
|
|
416
408
|
}
|
|
417
409
|
];
|
|
410
|
+
if (!this.writeKey) return;
|
|
418
411
|
const url = `${this.baseUrl}signals/track`;
|
|
419
412
|
try {
|
|
420
413
|
await postJson(url, body, this.authHeaders(), {
|
|
@@ -445,6 +438,7 @@ var EventShipper = class {
|
|
|
445
438
|
traits: (_a = user.traits) != null ? _a : {}
|
|
446
439
|
};
|
|
447
440
|
});
|
|
441
|
+
if (!this.writeKey) return;
|
|
448
442
|
if (body.length === 0) return;
|
|
449
443
|
const url = `${this.baseUrl}users/identify`;
|
|
450
444
|
try {
|
|
@@ -521,6 +515,18 @@ var EventShipper = class {
|
|
|
521
515
|
endpoint: url
|
|
522
516
|
});
|
|
523
517
|
}
|
|
518
|
+
if (this.localDebuggerUrl) {
|
|
519
|
+
mirrorPartialEventToLocalDebugger(payload, {
|
|
520
|
+
baseUrl: this.localDebuggerUrl,
|
|
521
|
+
writeKey: this.writeKey,
|
|
522
|
+
debug: this.debug,
|
|
523
|
+
sdkName: this.sdkName
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
if (!this.writeKey) {
|
|
527
|
+
if (!isPending) this.sticky.delete(eventId);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
524
530
|
const p = postJson(url, payload, this.authHeaders(), {
|
|
525
531
|
maxAttempts: 3,
|
|
526
532
|
debug: this.debug,
|
|
@@ -545,28 +551,100 @@ var EventShipper = class {
|
|
|
545
551
|
}
|
|
546
552
|
}
|
|
547
553
|
};
|
|
548
|
-
var
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
554
|
+
var DEFAULT_SECRET_KEY_NAMES = [
|
|
555
|
+
"apikey",
|
|
556
|
+
"apisecret",
|
|
557
|
+
"apitoken",
|
|
558
|
+
"secretaccesskey",
|
|
559
|
+
"sessiontoken",
|
|
560
|
+
"privatekey",
|
|
561
|
+
"privatekeyid",
|
|
562
|
+
"clientsecret",
|
|
563
|
+
"accesstoken",
|
|
564
|
+
"refreshtoken",
|
|
565
|
+
"oauthtoken",
|
|
566
|
+
"bearertoken",
|
|
567
|
+
"authorization",
|
|
568
|
+
"password",
|
|
569
|
+
"passphrase"
|
|
570
|
+
];
|
|
571
|
+
var REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
572
|
+
function normalizeKeyName(name) {
|
|
573
|
+
return name.toLowerCase().replace(/[-_.]/g, "");
|
|
553
574
|
}
|
|
554
|
-
function
|
|
555
|
-
var _a;
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
575
|
+
function redactSecretsInObject(value, options) {
|
|
576
|
+
var _a, _b;
|
|
577
|
+
const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
|
|
578
|
+
const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
|
|
579
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
580
|
+
const walk = (node) => {
|
|
581
|
+
if (node === null || typeof node !== "object") return node;
|
|
582
|
+
if (seen.has(node)) return "[CIRCULAR]";
|
|
583
|
+
seen.add(node);
|
|
584
|
+
if (Array.isArray(node)) {
|
|
585
|
+
return node.map((item) => walk(item));
|
|
586
|
+
}
|
|
587
|
+
const out = {};
|
|
588
|
+
for (const [k, v] of Object.entries(node)) {
|
|
589
|
+
if (normalizedSecretSet.has(normalizeKeyName(k))) {
|
|
590
|
+
out[k] = placeholder;
|
|
591
|
+
} else {
|
|
592
|
+
out[k] = walk(v);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return out;
|
|
596
|
+
};
|
|
597
|
+
return walk(value);
|
|
598
|
+
}
|
|
599
|
+
function buildSecretSet(names) {
|
|
600
|
+
const set = /* @__PURE__ */ new Set();
|
|
601
|
+
for (const name of names) set.add(normalizeKeyName(name));
|
|
602
|
+
return set;
|
|
603
|
+
}
|
|
604
|
+
var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
605
|
+
"ai.request.providerOptions",
|
|
606
|
+
"ai.response.providerMetadata"
|
|
607
|
+
];
|
|
608
|
+
function defaultTransformSpan(span) {
|
|
609
|
+
const attrs = span.attributes;
|
|
610
|
+
if (!attrs || attrs.length === 0) return span;
|
|
611
|
+
let nextAttrs;
|
|
612
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
613
|
+
const attr = attrs[i];
|
|
614
|
+
const redacted = redactJsonAttributeValue(attr.key, attr.value);
|
|
615
|
+
if (redacted === void 0) continue;
|
|
616
|
+
if (!nextAttrs) nextAttrs = attrs.slice();
|
|
617
|
+
nextAttrs[i] = { key: attr.key, value: redacted };
|
|
618
|
+
}
|
|
619
|
+
if (!nextAttrs) return span;
|
|
620
|
+
return { ...span, attributes: nextAttrs };
|
|
621
|
+
}
|
|
622
|
+
var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
623
|
+
function redactJsonAttributeValue(key, value) {
|
|
624
|
+
if (!REDACT_JSON_ATTRIBUTE_KEYS.has(key)) return void 0;
|
|
625
|
+
const json = value.stringValue;
|
|
626
|
+
if (typeof json !== "string" || json.length === 0) return void 0;
|
|
627
|
+
let parsed;
|
|
628
|
+
try {
|
|
629
|
+
parsed = JSON.parse(json);
|
|
630
|
+
} catch (e) {
|
|
631
|
+
return void 0;
|
|
632
|
+
}
|
|
633
|
+
const scrubbed = redactSecretsInObject(parsed);
|
|
634
|
+
let scrubbedJson;
|
|
635
|
+
try {
|
|
636
|
+
scrubbedJson = JSON.stringify(scrubbed);
|
|
637
|
+
} catch (e) {
|
|
638
|
+
return void 0;
|
|
639
|
+
}
|
|
640
|
+
if (scrubbedJson === json) return void 0;
|
|
641
|
+
return { stringValue: scrubbedJson };
|
|
564
642
|
}
|
|
565
643
|
var TraceShipper = class {
|
|
566
644
|
constructor(opts) {
|
|
567
645
|
this.queue = [];
|
|
568
646
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
569
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
647
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
570
648
|
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
571
649
|
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
572
650
|
this.enabled = opts.enabled !== false;
|
|
@@ -579,13 +657,46 @@ var TraceShipper = class {
|
|
|
579
657
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
580
658
|
this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
|
|
581
659
|
this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
|
|
582
|
-
|
|
583
|
-
if (
|
|
584
|
-
this.
|
|
585
|
-
|
|
586
|
-
|
|
660
|
+
this.localDebuggerUrl = (_i = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _i : void 0;
|
|
661
|
+
if (this.debug && this.localDebuggerUrl) {
|
|
662
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
663
|
+
}
|
|
664
|
+
this.transformSpanHook = opts.transformSpan;
|
|
665
|
+
this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Apply the user `transformSpan` hook (if any) followed by the default
|
|
669
|
+
* redactor (unless disabled). Returns either the (possibly new) span to
|
|
670
|
+
* ship, or `null` to drop the span entirely.
|
|
671
|
+
*
|
|
672
|
+
* Ordering: user hook runs first so callers can rewrite the span freely
|
|
673
|
+
* (rename attrs, add new ones, scrub things the default doesn't know
|
|
674
|
+
* about). The default redactor then runs on whatever the user produced,
|
|
675
|
+
* acting as the always-on floor for documented BYOK secrets. If the user
|
|
676
|
+
* sets `disableDefaultRedaction: true`, the floor is skipped.
|
|
677
|
+
*
|
|
678
|
+
* Fail-closed: if the user hook throws, the span is dropped — a buggy
|
|
679
|
+
* hook can never accidentally ship raw, un-redacted spans.
|
|
680
|
+
*/
|
|
681
|
+
redactSpan(span) {
|
|
682
|
+
let current = span;
|
|
683
|
+
if (this.transformSpanHook) {
|
|
684
|
+
try {
|
|
685
|
+
const result = this.transformSpanHook(current);
|
|
686
|
+
if (result === null) return null;
|
|
687
|
+
if (result !== void 0) current = result;
|
|
688
|
+
} catch (err) {
|
|
689
|
+
if (this.debug) {
|
|
690
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
691
|
+
console.warn(`${this.prefix} transformSpan hook threw: ${msg}`);
|
|
692
|
+
}
|
|
693
|
+
return null;
|
|
587
694
|
}
|
|
588
695
|
}
|
|
696
|
+
if (!this.disableDefaultRedaction) {
|
|
697
|
+
current = defaultTransformSpan(current);
|
|
698
|
+
}
|
|
699
|
+
return current;
|
|
589
700
|
}
|
|
590
701
|
isDebugEnabled() {
|
|
591
702
|
return this.debug;
|
|
@@ -603,8 +714,8 @@ var TraceShipper = class {
|
|
|
603
714
|
];
|
|
604
715
|
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
605
716
|
const span = { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
|
|
606
|
-
|
|
607
|
-
|
|
717
|
+
this.mirrorToLocalDebugger(
|
|
718
|
+
buildOtlpSpan({
|
|
608
719
|
ids: span.ids,
|
|
609
720
|
name: span.name,
|
|
610
721
|
startTimeUnixNano: span.startTimeUnixNano,
|
|
@@ -612,16 +723,21 @@ var TraceShipper = class {
|
|
|
612
723
|
// placeholder — will be updated on endSpan
|
|
613
724
|
attributes: span.attributes,
|
|
614
725
|
status: { code: SpanStatusCode.UNSET }
|
|
615
|
-
})
|
|
616
|
-
|
|
617
|
-
mirrorTraceExportToLocalDebugger(body, {
|
|
618
|
-
baseUrl: this.localDebuggerUrl,
|
|
619
|
-
debug: false,
|
|
620
|
-
sdkName: this.sdkName
|
|
621
|
-
});
|
|
622
|
-
}
|
|
726
|
+
})
|
|
727
|
+
);
|
|
623
728
|
return span;
|
|
624
729
|
}
|
|
730
|
+
mirrorToLocalDebugger(span) {
|
|
731
|
+
if (!this.localDebuggerUrl) return;
|
|
732
|
+
const redacted = this.redactSpan(span);
|
|
733
|
+
if (redacted === null) return;
|
|
734
|
+
const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
|
|
735
|
+
mirrorTraceExportToLocalDebugger(body, {
|
|
736
|
+
baseUrl: this.localDebuggerUrl,
|
|
737
|
+
debug: false,
|
|
738
|
+
sdkName: this.sdkName
|
|
739
|
+
});
|
|
740
|
+
}
|
|
625
741
|
endSpan(span, extra) {
|
|
626
742
|
var _a, _b;
|
|
627
743
|
if (span.endTimeUnixNano) return;
|
|
@@ -643,14 +759,7 @@ var TraceShipper = class {
|
|
|
643
759
|
status
|
|
644
760
|
});
|
|
645
761
|
this.enqueue(otlp);
|
|
646
|
-
|
|
647
|
-
const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
|
|
648
|
-
mirrorTraceExportToLocalDebugger(body, {
|
|
649
|
-
baseUrl: this.localDebuggerUrl,
|
|
650
|
-
debug: false,
|
|
651
|
-
sdkName: this.sdkName
|
|
652
|
-
});
|
|
653
|
-
}
|
|
762
|
+
this.mirrorToLocalDebugger(otlp);
|
|
654
763
|
}
|
|
655
764
|
createSpan(args) {
|
|
656
765
|
var _a;
|
|
@@ -668,14 +777,7 @@ var TraceShipper = class {
|
|
|
668
777
|
status: args.status
|
|
669
778
|
});
|
|
670
779
|
this.enqueue(otlp);
|
|
671
|
-
|
|
672
|
-
const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
|
|
673
|
-
mirrorTraceExportToLocalDebugger(body, {
|
|
674
|
-
baseUrl: this.localDebuggerUrl,
|
|
675
|
-
debug: false,
|
|
676
|
-
sdkName: this.sdkName
|
|
677
|
-
});
|
|
678
|
-
}
|
|
780
|
+
this.mirrorToLocalDebugger(otlp);
|
|
679
781
|
}
|
|
680
782
|
enqueue(span) {
|
|
681
783
|
if (!this.enabled) return;
|
|
@@ -687,10 +789,12 @@ var TraceShipper = class {
|
|
|
687
789
|
)}`
|
|
688
790
|
);
|
|
689
791
|
}
|
|
792
|
+
const redacted = this.redactSpan(span);
|
|
793
|
+
if (redacted === null) return;
|
|
690
794
|
if (this.queue.length >= this.maxQueueSize) {
|
|
691
795
|
this.queue.shift();
|
|
692
796
|
}
|
|
693
|
-
this.queue.push(
|
|
797
|
+
this.queue.push(redacted);
|
|
694
798
|
if (this.queue.length >= this.maxBatchSize) {
|
|
695
799
|
void this.flush().catch(() => {
|
|
696
800
|
});
|
|
@@ -712,6 +816,7 @@ var TraceShipper = class {
|
|
|
712
816
|
}
|
|
713
817
|
while (this.queue.length > 0) {
|
|
714
818
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
819
|
+
if (!this.writeKey) continue;
|
|
715
820
|
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
716
821
|
const url = `${this.baseUrl}traces`;
|
|
717
822
|
if (this.debug) {
|
|
@@ -754,6 +859,103 @@ var TraceShipper = class {
|
|
|
754
859
|
import { AsyncLocalStorage } from "async_hooks";
|
|
755
860
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
|
|
756
861
|
|
|
862
|
+
// package.json
|
|
863
|
+
var package_default = {
|
|
864
|
+
name: "@raindrop-ai/pi-agent",
|
|
865
|
+
version: "0.0.4",
|
|
866
|
+
description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
|
|
867
|
+
type: "module",
|
|
868
|
+
license: "MIT",
|
|
869
|
+
repository: {
|
|
870
|
+
type: "git",
|
|
871
|
+
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
872
|
+
directory: "packages/pi-agent"
|
|
873
|
+
},
|
|
874
|
+
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/pi-agent#readme",
|
|
875
|
+
bugs: {
|
|
876
|
+
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
877
|
+
},
|
|
878
|
+
keywords: [
|
|
879
|
+
"pi-package",
|
|
880
|
+
"raindrop",
|
|
881
|
+
"pi-agent",
|
|
882
|
+
"observability",
|
|
883
|
+
"tracing"
|
|
884
|
+
],
|
|
885
|
+
exports: {
|
|
886
|
+
".": {
|
|
887
|
+
types: "./dist/index.d.ts",
|
|
888
|
+
import: "./dist/index.js",
|
|
889
|
+
require: "./dist/index.cjs"
|
|
890
|
+
},
|
|
891
|
+
"./extension": {
|
|
892
|
+
types: "./dist/extension.d.ts",
|
|
893
|
+
import: "./dist/extension.js",
|
|
894
|
+
require: "./dist/extension.cjs"
|
|
895
|
+
}
|
|
896
|
+
},
|
|
897
|
+
pi: {
|
|
898
|
+
extensions: [
|
|
899
|
+
"./dist/extension.js"
|
|
900
|
+
]
|
|
901
|
+
},
|
|
902
|
+
sideEffects: false,
|
|
903
|
+
files: [
|
|
904
|
+
"dist/**",
|
|
905
|
+
"README.md"
|
|
906
|
+
],
|
|
907
|
+
scripts: {
|
|
908
|
+
build: "tsup",
|
|
909
|
+
dev: "tsup --watch",
|
|
910
|
+
clean: "rm -rf dist",
|
|
911
|
+
test: "vitest run",
|
|
912
|
+
"test:watch": "vitest"
|
|
913
|
+
},
|
|
914
|
+
peerDependencies: {
|
|
915
|
+
"@earendil-works/pi-agent-core": ">=0.74.0",
|
|
916
|
+
"@earendil-works/pi-coding-agent": ">=0.74.0"
|
|
917
|
+
},
|
|
918
|
+
peerDependenciesMeta: {
|
|
919
|
+
"@earendil-works/pi-coding-agent": {
|
|
920
|
+
optional: true
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
devDependencies: {
|
|
924
|
+
"@raindrop-ai/core": "workspace:*",
|
|
925
|
+
"@earendil-works/pi-agent-core": "^0.78.0",
|
|
926
|
+
"@earendil-works/pi-coding-agent": "^0.78.0",
|
|
927
|
+
"@types/node": "^20.11.17",
|
|
928
|
+
msw: "^2.12.7",
|
|
929
|
+
tsup: "^8.5.1",
|
|
930
|
+
typescript: "^5.7.3",
|
|
931
|
+
vitest: "^2.1.9"
|
|
932
|
+
},
|
|
933
|
+
tsup: {
|
|
934
|
+
entry: [
|
|
935
|
+
"src/index.ts",
|
|
936
|
+
"src/extension.ts"
|
|
937
|
+
],
|
|
938
|
+
format: [
|
|
939
|
+
"cjs",
|
|
940
|
+
"esm"
|
|
941
|
+
],
|
|
942
|
+
dts: {
|
|
943
|
+
resolve: true
|
|
944
|
+
},
|
|
945
|
+
clean: true,
|
|
946
|
+
noExternal: [
|
|
947
|
+
"@raindrop-ai/core"
|
|
948
|
+
]
|
|
949
|
+
},
|
|
950
|
+
publishConfig: {
|
|
951
|
+
access: "public"
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
// src/version.ts
|
|
956
|
+
var libraryName = package_default.name;
|
|
957
|
+
var libraryVersion = package_default.version;
|
|
958
|
+
|
|
757
959
|
// src/internal/shipper.ts
|
|
758
960
|
var EventShipper2 = class extends EventShipper {
|
|
759
961
|
constructor(opts) {
|
|
@@ -901,12 +1103,13 @@ function getUsername() {
|
|
|
901
1103
|
}
|
|
902
1104
|
|
|
903
1105
|
export {
|
|
904
|
-
libraryVersion,
|
|
905
1106
|
randomUUID,
|
|
906
1107
|
generateId,
|
|
907
1108
|
nowUnixNanoString,
|
|
908
1109
|
attrString,
|
|
909
1110
|
attrInt,
|
|
1111
|
+
resolveLocalDebuggerBaseUrl,
|
|
1112
|
+
libraryVersion,
|
|
910
1113
|
EventShipper2 as EventShipper,
|
|
911
1114
|
TraceShipper2 as TraceShipper,
|
|
912
1115
|
extractUserText,
|