@raindrop-ai/pi-agent 0.0.2
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/README.md +48 -0
- package/dist/chunk-LZIGXU2D.js +922 -0
- package/dist/extension.cjs +1311 -0
- package/dist/extension.d.cts +60 -0
- package/dist/extension.d.ts +60 -0
- package/dist/extension.js +452 -0
- package/dist/index.cjs +1405 -0
- package/dist/index.d-npTVS9Mf.d.cts +216 -0
- package/dist/index.d-npTVS9Mf.d.ts +216 -0
- package/dist/index.d.cts +138 -0
- package/dist/index.d.ts +138 -0
- package/dist/index.js +498 -0
- package/package.json +91 -0
|
@@ -0,0 +1,1311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/extension.ts
|
|
21
|
+
var extension_exports = {};
|
|
22
|
+
__export(extension_exports, {
|
|
23
|
+
default: () => extension,
|
|
24
|
+
registerTracing: () => registerTracing
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(extension_exports);
|
|
27
|
+
|
|
28
|
+
// src/internal/config.ts
|
|
29
|
+
var import_node_fs = require("fs");
|
|
30
|
+
var import_node_os = require("os");
|
|
31
|
+
var import_node_path = require("path");
|
|
32
|
+
function getPiAgentDirectory() {
|
|
33
|
+
var _a;
|
|
34
|
+
return (_a = process.env["PI_CODING_AGENT_DIR"]) != null ? _a : (0, import_node_path.join)((0, import_node_os.homedir)(), ".pi", "agent");
|
|
35
|
+
}
|
|
36
|
+
function loadConfig(projectDirectory) {
|
|
37
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
38
|
+
let merged = {};
|
|
39
|
+
const configPaths = [
|
|
40
|
+
(0, import_node_path.join)(getPiAgentDirectory(), "raindrop.json"),
|
|
41
|
+
(0, import_node_path.join)(projectDirectory, ".pi", "raindrop.json")
|
|
42
|
+
];
|
|
43
|
+
for (const configPath of configPaths) {
|
|
44
|
+
try {
|
|
45
|
+
if ((0, import_node_fs.existsSync)(configPath)) {
|
|
46
|
+
const content = (0, import_node_fs.readFileSync)(configPath, "utf-8");
|
|
47
|
+
const parsed = JSON.parse(content);
|
|
48
|
+
merged = { ...merged, ...parsed };
|
|
49
|
+
}
|
|
50
|
+
} catch (e) {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
let eventMetadata;
|
|
54
|
+
const envMeta = process.env["RAINDROP_EVENT_METADATA"];
|
|
55
|
+
if (envMeta) {
|
|
56
|
+
try {
|
|
57
|
+
eventMetadata = JSON.parse(envMeta);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
63
|
+
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
64
|
+
eventName: (_e = merged.event_name) != null ? _e : "pi_session",
|
|
65
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
66
|
+
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
|
|
67
|
+
eventMetadata
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// package.json
|
|
72
|
+
var package_default = {
|
|
73
|
+
name: "@raindrop-ai/pi-agent",
|
|
74
|
+
version: "0.0.2",
|
|
75
|
+
description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
|
|
76
|
+
type: "module",
|
|
77
|
+
license: "MIT",
|
|
78
|
+
repository: {
|
|
79
|
+
type: "git",
|
|
80
|
+
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
81
|
+
directory: "packages/pi-agent"
|
|
82
|
+
},
|
|
83
|
+
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/pi-agent#readme",
|
|
84
|
+
bugs: {
|
|
85
|
+
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
86
|
+
},
|
|
87
|
+
keywords: [
|
|
88
|
+
"pi-package",
|
|
89
|
+
"raindrop",
|
|
90
|
+
"pi-agent",
|
|
91
|
+
"observability",
|
|
92
|
+
"tracing"
|
|
93
|
+
],
|
|
94
|
+
exports: {
|
|
95
|
+
".": {
|
|
96
|
+
types: "./dist/index.d.ts",
|
|
97
|
+
import: "./dist/index.js",
|
|
98
|
+
require: "./dist/index.cjs"
|
|
99
|
+
},
|
|
100
|
+
"./extension": {
|
|
101
|
+
types: "./dist/extension.d.ts",
|
|
102
|
+
import: "./dist/extension.js",
|
|
103
|
+
require: "./dist/extension.cjs"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
pi: {
|
|
107
|
+
extensions: [
|
|
108
|
+
"./dist/extension.js"
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
sideEffects: false,
|
|
112
|
+
files: [
|
|
113
|
+
"dist/**",
|
|
114
|
+
"README.md"
|
|
115
|
+
],
|
|
116
|
+
scripts: {
|
|
117
|
+
build: "tsup",
|
|
118
|
+
dev: "tsup --watch",
|
|
119
|
+
clean: "rm -rf dist",
|
|
120
|
+
test: "vitest run",
|
|
121
|
+
"test:watch": "vitest"
|
|
122
|
+
},
|
|
123
|
+
peerDependencies: {
|
|
124
|
+
"@mariozechner/pi-agent-core": ">=0.60.0",
|
|
125
|
+
"@mariozechner/pi-coding-agent": ">=0.65.2"
|
|
126
|
+
},
|
|
127
|
+
peerDependenciesMeta: {
|
|
128
|
+
"@mariozechner/pi-coding-agent": {
|
|
129
|
+
optional: true
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
devDependencies: {
|
|
133
|
+
"@raindrop-ai/core": "workspace:*",
|
|
134
|
+
"@mariozechner/pi-agent-core": "^0.66.0",
|
|
135
|
+
"@mariozechner/pi-coding-agent": "^0.66.0",
|
|
136
|
+
"@types/node": "^20.11.17",
|
|
137
|
+
msw: "^2.12.7",
|
|
138
|
+
tsup: "^8.5.1",
|
|
139
|
+
typescript: "^5.7.3",
|
|
140
|
+
vitest: "^2.1.9"
|
|
141
|
+
},
|
|
142
|
+
tsup: {
|
|
143
|
+
entry: [
|
|
144
|
+
"src/index.ts",
|
|
145
|
+
"src/extension.ts"
|
|
146
|
+
],
|
|
147
|
+
format: [
|
|
148
|
+
"cjs",
|
|
149
|
+
"esm"
|
|
150
|
+
],
|
|
151
|
+
dts: {
|
|
152
|
+
resolve: true
|
|
153
|
+
},
|
|
154
|
+
clean: true,
|
|
155
|
+
noExternal: [
|
|
156
|
+
"@raindrop-ai/core"
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
publishConfig: {
|
|
160
|
+
access: "public"
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/version.ts
|
|
165
|
+
var libraryName = package_default.name;
|
|
166
|
+
var libraryVersion = package_default.version;
|
|
167
|
+
|
|
168
|
+
// ../core/dist/chunk-4UCYIEH4.js
|
|
169
|
+
function getCrypto() {
|
|
170
|
+
const c = globalThis.crypto;
|
|
171
|
+
return c;
|
|
172
|
+
}
|
|
173
|
+
function randomBytes(length) {
|
|
174
|
+
const cryptoObj = getCrypto();
|
|
175
|
+
const out = new Uint8Array(length);
|
|
176
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
177
|
+
cryptoObj.getRandomValues(out);
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
181
|
+
return out;
|
|
182
|
+
}
|
|
183
|
+
function base64Encode(bytes) {
|
|
184
|
+
const maybeBuffer = globalThis.Buffer;
|
|
185
|
+
if (maybeBuffer) {
|
|
186
|
+
return maybeBuffer.from(bytes).toString("base64");
|
|
187
|
+
}
|
|
188
|
+
let binary = "";
|
|
189
|
+
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
190
|
+
binary += String.fromCharCode(bytes[i2]);
|
|
191
|
+
}
|
|
192
|
+
const btoaFn = globalThis.btoa;
|
|
193
|
+
if (typeof btoaFn === "function") return btoaFn(binary);
|
|
194
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
195
|
+
let out = "";
|
|
196
|
+
let i = 0;
|
|
197
|
+
while (i < binary.length) {
|
|
198
|
+
const c1 = binary.charCodeAt(i++) & 255;
|
|
199
|
+
const c2 = i < binary.length ? binary.charCodeAt(i++) & 255 : NaN;
|
|
200
|
+
const c3 = i < binary.length ? binary.charCodeAt(i++) & 255 : NaN;
|
|
201
|
+
const e1 = c1 >> 2;
|
|
202
|
+
const e2 = (c1 & 3) << 4 | (Number.isNaN(c2) ? 0 : c2 >> 4);
|
|
203
|
+
const e3 = Number.isNaN(c2) ? 64 : (c2 & 15) << 2 | (Number.isNaN(c3) ? 0 : c3 >> 6);
|
|
204
|
+
const e4 = Number.isNaN(c3) ? 64 : c3 & 63;
|
|
205
|
+
out += alphabet.charAt(e1);
|
|
206
|
+
out += alphabet.charAt(e2);
|
|
207
|
+
out += e3 === 64 ? "=" : alphabet.charAt(e3);
|
|
208
|
+
out += e4 === 64 ? "=" : alphabet.charAt(e4);
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
function generateId() {
|
|
213
|
+
return base64Encode(randomBytes(12)).replace(/[+/=]/g, "").slice(0, 16);
|
|
214
|
+
}
|
|
215
|
+
function wait(ms) {
|
|
216
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
217
|
+
}
|
|
218
|
+
function formatEndpoint(endpoint) {
|
|
219
|
+
if (!endpoint) return void 0;
|
|
220
|
+
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
221
|
+
}
|
|
222
|
+
function parseRetryAfter(headers) {
|
|
223
|
+
var _a;
|
|
224
|
+
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
225
|
+
if (!value) return void 0;
|
|
226
|
+
const asNumber = Number(value);
|
|
227
|
+
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
228
|
+
const asDate = new Date(value).getTime();
|
|
229
|
+
if (!Number.isNaN(asDate)) {
|
|
230
|
+
const delta = asDate - Date.now();
|
|
231
|
+
return delta > 0 ? delta : 0;
|
|
232
|
+
}
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
235
|
+
function getRetryDelayMs(attemptNumber, previousError) {
|
|
236
|
+
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
237
|
+
const v = previousError.retryAfterMs;
|
|
238
|
+
if (typeof v === "number") return Math.max(0, v);
|
|
239
|
+
}
|
|
240
|
+
if (attemptNumber <= 1) return 0;
|
|
241
|
+
const base = 500;
|
|
242
|
+
const factor = Math.pow(2, attemptNumber - 2);
|
|
243
|
+
return base * factor;
|
|
244
|
+
}
|
|
245
|
+
async function withRetry(operation, opName, opts) {
|
|
246
|
+
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
247
|
+
let lastError = void 0;
|
|
248
|
+
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
249
|
+
if (attemptNumber > 1) {
|
|
250
|
+
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
251
|
+
if (opts.debug) {
|
|
252
|
+
console.warn(
|
|
253
|
+
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
if (delay > 0) await wait(delay);
|
|
257
|
+
} else if (opts.debug) {
|
|
258
|
+
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
return await operation();
|
|
262
|
+
} catch (err) {
|
|
263
|
+
lastError = err;
|
|
264
|
+
if (opts.debug) {
|
|
265
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
266
|
+
console.warn(
|
|
267
|
+
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
271
|
+
break;
|
|
272
|
+
if (attemptNumber === opts.maxAttempts) break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
276
|
+
}
|
|
277
|
+
async function postJson(url, body, headers, opts) {
|
|
278
|
+
const opName = `POST ${url}`;
|
|
279
|
+
await withRetry(
|
|
280
|
+
async () => {
|
|
281
|
+
const resp = await fetch(url, {
|
|
282
|
+
method: "POST",
|
|
283
|
+
headers: {
|
|
284
|
+
"Content-Type": "application/json",
|
|
285
|
+
...headers
|
|
286
|
+
},
|
|
287
|
+
body: JSON.stringify(body)
|
|
288
|
+
});
|
|
289
|
+
if (!resp.ok) {
|
|
290
|
+
const text = await resp.text().catch(() => "");
|
|
291
|
+
const err = new Error(
|
|
292
|
+
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
293
|
+
);
|
|
294
|
+
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
295
|
+
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
296
|
+
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
297
|
+
throw err;
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
opName,
|
|
301
|
+
opts
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
var SpanStatusCode = {
|
|
305
|
+
UNSET: 0,
|
|
306
|
+
OK: 1,
|
|
307
|
+
ERROR: 2
|
|
308
|
+
};
|
|
309
|
+
function createSpanIds(parent) {
|
|
310
|
+
const traceId = parent ? parent.traceIdB64 : base64Encode(randomBytes(16));
|
|
311
|
+
const spanId = base64Encode(randomBytes(8));
|
|
312
|
+
return {
|
|
313
|
+
traceIdB64: traceId,
|
|
314
|
+
spanIdB64: spanId,
|
|
315
|
+
parentSpanIdB64: parent ? parent.spanIdB64 : void 0
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function nowUnixNanoString() {
|
|
319
|
+
return Date.now().toString() + "000000";
|
|
320
|
+
}
|
|
321
|
+
function attrString(key, value) {
|
|
322
|
+
if (value === void 0) return void 0;
|
|
323
|
+
return { key, value: { stringValue: value } };
|
|
324
|
+
}
|
|
325
|
+
function attrInt(key, value) {
|
|
326
|
+
if (value === void 0) return void 0;
|
|
327
|
+
if (!Number.isFinite(value)) return void 0;
|
|
328
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
329
|
+
}
|
|
330
|
+
function buildOtlpSpan(args) {
|
|
331
|
+
const attrs = args.attributes.filter((x) => x !== void 0);
|
|
332
|
+
const span = {
|
|
333
|
+
traceId: args.ids.traceIdB64,
|
|
334
|
+
spanId: args.ids.spanIdB64,
|
|
335
|
+
name: args.name,
|
|
336
|
+
startTimeUnixNano: args.startTimeUnixNano,
|
|
337
|
+
endTimeUnixNano: args.endTimeUnixNano
|
|
338
|
+
};
|
|
339
|
+
if (args.ids.parentSpanIdB64) span.parentSpanId = args.ids.parentSpanIdB64;
|
|
340
|
+
if (attrs.length) span.attributes = attrs;
|
|
341
|
+
if (args.status) span.status = args.status;
|
|
342
|
+
return span;
|
|
343
|
+
}
|
|
344
|
+
function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", serviceVersion = "0.0.0") {
|
|
345
|
+
return {
|
|
346
|
+
resourceSpans: [
|
|
347
|
+
{
|
|
348
|
+
resource: {
|
|
349
|
+
attributes: [{ key: "service.name", value: { stringValue: serviceName } }]
|
|
350
|
+
},
|
|
351
|
+
scopeSpans: [
|
|
352
|
+
{
|
|
353
|
+
scope: { name: serviceName, version: serviceVersion },
|
|
354
|
+
spans
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
]
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function mergePatches(target, source) {
|
|
362
|
+
var _a, _b, _c, _d;
|
|
363
|
+
const out = { ...target, ...source };
|
|
364
|
+
if (target.properties || source.properties) {
|
|
365
|
+
out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
|
|
366
|
+
}
|
|
367
|
+
if (target.attachments || source.attachments) {
|
|
368
|
+
out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
|
|
369
|
+
}
|
|
370
|
+
return out;
|
|
371
|
+
}
|
|
372
|
+
var EventShipper = class {
|
|
373
|
+
constructor(opts) {
|
|
374
|
+
this.buffers = /* @__PURE__ */ new Map();
|
|
375
|
+
this.sticky = /* @__PURE__ */ new Map();
|
|
376
|
+
this.timers = /* @__PURE__ */ new Map();
|
|
377
|
+
this.inFlight = /* @__PURE__ */ new Set();
|
|
378
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
379
|
+
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
380
|
+
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
381
|
+
this.enabled = opts.enabled !== false;
|
|
382
|
+
this.debug = opts.debug;
|
|
383
|
+
this.partialFlushMs = (_c = opts.partialFlushMs) != null ? _c : 1e3;
|
|
384
|
+
this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
|
|
385
|
+
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
386
|
+
this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
|
|
387
|
+
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
388
|
+
this.context = {
|
|
389
|
+
library: {
|
|
390
|
+
name: (_f = opts.libraryName) != null ? _f : "@raindrop-ai/core",
|
|
391
|
+
version: (_g = opts.libraryVersion) != null ? _g : "0.0.0"
|
|
392
|
+
},
|
|
393
|
+
metadata: {
|
|
394
|
+
jsRuntime: isNode ? "node" : "web",
|
|
395
|
+
...isNode ? { nodeVersion: process.version } : {}
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
isDebugEnabled() {
|
|
400
|
+
return this.debug;
|
|
401
|
+
}
|
|
402
|
+
authHeaders() {
|
|
403
|
+
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
404
|
+
}
|
|
405
|
+
async patch(eventId, patch) {
|
|
406
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
407
|
+
if (!this.enabled) return;
|
|
408
|
+
if (!eventId || !eventId.trim()) return;
|
|
409
|
+
if (this.debug) {
|
|
410
|
+
console.log(`${this.prefix} queue patch`, {
|
|
411
|
+
eventId,
|
|
412
|
+
userId: patch.userId,
|
|
413
|
+
convoId: patch.convoId,
|
|
414
|
+
eventName: patch.eventName,
|
|
415
|
+
hasInput: typeof patch.input === "string" && patch.input.length > 0,
|
|
416
|
+
hasOutput: typeof patch.output === "string" && patch.output.length > 0,
|
|
417
|
+
attachments: (_b = (_a = patch.attachments) == null ? void 0 : _a.length) != null ? _b : 0,
|
|
418
|
+
isPending: patch.isPending
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
422
|
+
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
423
|
+
const merged = mergePatches(existing, patch);
|
|
424
|
+
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
425
|
+
this.buffers.set(eventId, merged);
|
|
426
|
+
this.sticky.set(eventId, {
|
|
427
|
+
userId: (_h = merged.userId) != null ? _h : sticky.userId,
|
|
428
|
+
convoId: (_i = merged.convoId) != null ? _i : sticky.convoId,
|
|
429
|
+
eventName: (_j = merged.eventName) != null ? _j : sticky.eventName,
|
|
430
|
+
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending
|
|
431
|
+
});
|
|
432
|
+
const t = this.timers.get(eventId);
|
|
433
|
+
if (t) clearTimeout(t);
|
|
434
|
+
if (merged.isPending === false) {
|
|
435
|
+
await this.flushOne(eventId);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const timeout = setTimeout(() => {
|
|
439
|
+
void this.flushOne(eventId).catch(() => {
|
|
440
|
+
});
|
|
441
|
+
}, this.partialFlushMs);
|
|
442
|
+
this.timers.set(eventId, timeout);
|
|
443
|
+
}
|
|
444
|
+
async finish(eventId, patch) {
|
|
445
|
+
await this.patch(eventId, { ...patch, isPending: false });
|
|
446
|
+
}
|
|
447
|
+
async flush() {
|
|
448
|
+
if (!this.enabled) return;
|
|
449
|
+
const ids = [...this.buffers.keys()];
|
|
450
|
+
await Promise.all(ids.map((id) => this.flushOne(id)));
|
|
451
|
+
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
452
|
+
})));
|
|
453
|
+
}
|
|
454
|
+
async shutdown() {
|
|
455
|
+
for (const t of this.timers.values()) clearTimeout(t);
|
|
456
|
+
this.timers.clear();
|
|
457
|
+
await this.flush();
|
|
458
|
+
}
|
|
459
|
+
async trackSignal(signal) {
|
|
460
|
+
var _a, _b;
|
|
461
|
+
if (!this.enabled) return;
|
|
462
|
+
const body = [
|
|
463
|
+
{
|
|
464
|
+
event_id: signal.eventId,
|
|
465
|
+
signal_name: signal.name,
|
|
466
|
+
signal_type: (_a = signal.type) != null ? _a : "default",
|
|
467
|
+
timestamp: signal.timestamp,
|
|
468
|
+
sentiment: signal.sentiment,
|
|
469
|
+
attachment_id: signal.attachmentId,
|
|
470
|
+
properties: {
|
|
471
|
+
...(_b = signal.properties) != null ? _b : {},
|
|
472
|
+
...signal.comment ? { comment: signal.comment } : {},
|
|
473
|
+
...signal.after ? { after: signal.after } : {}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
];
|
|
477
|
+
const url = `${this.baseUrl}signals/track`;
|
|
478
|
+
try {
|
|
479
|
+
await postJson(url, body, this.authHeaders(), {
|
|
480
|
+
maxAttempts: 3,
|
|
481
|
+
debug: this.debug,
|
|
482
|
+
sdkName: this.sdkName
|
|
483
|
+
});
|
|
484
|
+
} catch (err) {
|
|
485
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
486
|
+
console.warn(`${this.prefix} failed to send signal (dropping): ${msg}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
async identify(users) {
|
|
490
|
+
if (!this.enabled) return;
|
|
491
|
+
const list = Array.isArray(users) ? users : [users];
|
|
492
|
+
const body = list.filter((user) => {
|
|
493
|
+
if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
|
|
494
|
+
if (this.debug) {
|
|
495
|
+
console.warn(`${this.prefix} skipping identify: missing userId`);
|
|
496
|
+
}
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
return true;
|
|
500
|
+
}).map((user) => {
|
|
501
|
+
var _a;
|
|
502
|
+
return {
|
|
503
|
+
user_id: user.userId,
|
|
504
|
+
traits: (_a = user.traits) != null ? _a : {}
|
|
505
|
+
};
|
|
506
|
+
});
|
|
507
|
+
if (body.length === 0) return;
|
|
508
|
+
const url = `${this.baseUrl}users/identify`;
|
|
509
|
+
try {
|
|
510
|
+
await postJson(url, body, this.authHeaders(), {
|
|
511
|
+
maxAttempts: 3,
|
|
512
|
+
debug: this.debug,
|
|
513
|
+
sdkName: this.sdkName
|
|
514
|
+
});
|
|
515
|
+
} catch (err) {
|
|
516
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
517
|
+
console.warn(`${this.prefix} failed to send identify (dropping): ${msg}`);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
async flushOne(eventId) {
|
|
521
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
522
|
+
if (!this.enabled) return;
|
|
523
|
+
const timer = this.timers.get(eventId);
|
|
524
|
+
if (timer) {
|
|
525
|
+
clearTimeout(timer);
|
|
526
|
+
this.timers.delete(eventId);
|
|
527
|
+
}
|
|
528
|
+
const accumulated = this.buffers.get(eventId);
|
|
529
|
+
this.buffers.delete(eventId);
|
|
530
|
+
if (!accumulated) return;
|
|
531
|
+
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
532
|
+
const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c : this.defaultEventName;
|
|
533
|
+
const userId = (_d = accumulated.userId) != null ? _d : sticky.userId;
|
|
534
|
+
if (!userId) {
|
|
535
|
+
if (this.debug) {
|
|
536
|
+
console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
|
|
537
|
+
}
|
|
538
|
+
this.sticky.delete(eventId);
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
|
|
542
|
+
const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
|
|
543
|
+
const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
|
|
544
|
+
const payload = {
|
|
545
|
+
event_id: eventId,
|
|
546
|
+
user_id: userId,
|
|
547
|
+
event: eventName,
|
|
548
|
+
timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
|
|
549
|
+
ai_data: {
|
|
550
|
+
input: accumulated.input,
|
|
551
|
+
output: accumulated.output,
|
|
552
|
+
model: accumulated.model,
|
|
553
|
+
convo_id: convoId
|
|
554
|
+
},
|
|
555
|
+
properties: {
|
|
556
|
+
...restProperties,
|
|
557
|
+
...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
|
|
558
|
+
$context: this.context
|
|
559
|
+
},
|
|
560
|
+
attachments: accumulated.attachments,
|
|
561
|
+
is_pending: isPending
|
|
562
|
+
};
|
|
563
|
+
const url = `${this.baseUrl}events/track_partial`;
|
|
564
|
+
if (this.debug) {
|
|
565
|
+
console.log(`${this.prefix} sending track_partial`, {
|
|
566
|
+
eventId,
|
|
567
|
+
eventName,
|
|
568
|
+
userId,
|
|
569
|
+
convoId,
|
|
570
|
+
isPending,
|
|
571
|
+
inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
|
|
572
|
+
outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
|
|
573
|
+
attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
|
|
574
|
+
attachmentKinds: (_m = (_l = accumulated.attachments) == null ? void 0 : _l.map((a) => ({
|
|
575
|
+
type: a.type,
|
|
576
|
+
role: a.role,
|
|
577
|
+
name: a.name,
|
|
578
|
+
valuePreview: a.value.slice(0, 60)
|
|
579
|
+
}))) != null ? _m : [],
|
|
580
|
+
endpoint: url
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
const p = postJson(url, payload, this.authHeaders(), {
|
|
584
|
+
maxAttempts: 3,
|
|
585
|
+
debug: this.debug,
|
|
586
|
+
sdkName: this.sdkName
|
|
587
|
+
});
|
|
588
|
+
this.inFlight.add(p);
|
|
589
|
+
try {
|
|
590
|
+
try {
|
|
591
|
+
await p;
|
|
592
|
+
if (this.debug) {
|
|
593
|
+
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
594
|
+
}
|
|
595
|
+
} catch (err) {
|
|
596
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
597
|
+
console.warn(`${this.prefix} failed to send track_partial (dropping): ${msg}`);
|
|
598
|
+
}
|
|
599
|
+
} finally {
|
|
600
|
+
this.inFlight.delete(p);
|
|
601
|
+
}
|
|
602
|
+
if (!isPending) {
|
|
603
|
+
this.sticky.delete(eventId);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
608
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
609
|
+
var _a, _b, _c;
|
|
610
|
+
const resolved = (_b = baseUrl != null ? baseUrl : typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a[LOCAL_DEBUGGER_ENV_VAR] : void 0) != null ? _b : null;
|
|
611
|
+
return resolved ? (_c = formatEndpoint(resolved)) != null ? _c : null : null;
|
|
612
|
+
}
|
|
613
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
614
|
+
var _a;
|
|
615
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
616
|
+
if (!baseUrl) return;
|
|
617
|
+
void postJson(`${baseUrl}traces`, body, {}, {
|
|
618
|
+
maxAttempts: 1,
|
|
619
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
620
|
+
sdkName: options.sdkName
|
|
621
|
+
}).catch(() => {
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
var TraceShipper = class {
|
|
625
|
+
constructor(opts) {
|
|
626
|
+
this.queue = [];
|
|
627
|
+
this.inFlight = /* @__PURE__ */ new Set();
|
|
628
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
629
|
+
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
630
|
+
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
631
|
+
this.enabled = opts.enabled !== false;
|
|
632
|
+
this.debug = opts.debug;
|
|
633
|
+
this.debugSpans = opts.debugSpans === true;
|
|
634
|
+
this.flushIntervalMs = (_c = opts.flushIntervalMs) != null ? _c : 1e3;
|
|
635
|
+
this.maxBatchSize = (_d = opts.maxBatchSize) != null ? _d : 50;
|
|
636
|
+
this.maxQueueSize = (_e = opts.maxQueueSize) != null ? _e : 5e3;
|
|
637
|
+
this.sdkName = (_f = opts.sdkName) != null ? _f : "core";
|
|
638
|
+
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
639
|
+
this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
|
|
640
|
+
this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
|
|
641
|
+
const localDebugger = typeof process !== "undefined" ? (_i = process.env) == null ? void 0 : _i.RAINDROP_LOCAL_DEBUGGER : void 0;
|
|
642
|
+
if (localDebugger) {
|
|
643
|
+
this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(localDebugger)) != null ? _j : void 0;
|
|
644
|
+
if (this.debug) {
|
|
645
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
isDebugEnabled() {
|
|
650
|
+
return this.debug;
|
|
651
|
+
}
|
|
652
|
+
authHeaders() {
|
|
653
|
+
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
654
|
+
}
|
|
655
|
+
startSpan(args) {
|
|
656
|
+
var _a, _b;
|
|
657
|
+
const ids = createSpanIds(args.parent);
|
|
658
|
+
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
659
|
+
const attrs = [
|
|
660
|
+
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
661
|
+
attrString("ai.operationId", args.operationId)
|
|
662
|
+
];
|
|
663
|
+
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
664
|
+
const span = { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
|
|
665
|
+
if (this.localDebuggerUrl) {
|
|
666
|
+
const openSpan = buildOtlpSpan({
|
|
667
|
+
ids: span.ids,
|
|
668
|
+
name: span.name,
|
|
669
|
+
startTimeUnixNano: span.startTimeUnixNano,
|
|
670
|
+
endTimeUnixNano: span.startTimeUnixNano,
|
|
671
|
+
// placeholder — will be updated on endSpan
|
|
672
|
+
attributes: span.attributes,
|
|
673
|
+
status: { code: SpanStatusCode.UNSET }
|
|
674
|
+
});
|
|
675
|
+
const body = buildExportTraceServiceRequest([openSpan], this.serviceName, this.serviceVersion);
|
|
676
|
+
mirrorTraceExportToLocalDebugger(body, {
|
|
677
|
+
baseUrl: this.localDebuggerUrl,
|
|
678
|
+
debug: false,
|
|
679
|
+
sdkName: this.sdkName
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
return span;
|
|
683
|
+
}
|
|
684
|
+
endSpan(span, extra) {
|
|
685
|
+
var _a, _b;
|
|
686
|
+
if (span.endTimeUnixNano) return;
|
|
687
|
+
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
688
|
+
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
689
|
+
span.attributes.push(...extra.attributes);
|
|
690
|
+
}
|
|
691
|
+
let status = extra == null ? void 0 : extra.status;
|
|
692
|
+
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
693
|
+
const message = extra.error instanceof Error ? extra.error.message : String(extra.error);
|
|
694
|
+
status = { code: SpanStatusCode.ERROR, message };
|
|
695
|
+
}
|
|
696
|
+
const otlp = buildOtlpSpan({
|
|
697
|
+
ids: span.ids,
|
|
698
|
+
name: span.name,
|
|
699
|
+
startTimeUnixNano: span.startTimeUnixNano,
|
|
700
|
+
endTimeUnixNano: span.endTimeUnixNano,
|
|
701
|
+
attributes: span.attributes,
|
|
702
|
+
status
|
|
703
|
+
});
|
|
704
|
+
this.enqueue(otlp);
|
|
705
|
+
if (this.localDebuggerUrl) {
|
|
706
|
+
const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
|
|
707
|
+
mirrorTraceExportToLocalDebugger(body, {
|
|
708
|
+
baseUrl: this.localDebuggerUrl,
|
|
709
|
+
debug: false,
|
|
710
|
+
sdkName: this.sdkName
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
createSpan(args) {
|
|
715
|
+
var _a;
|
|
716
|
+
const ids = createSpanIds(args.parent);
|
|
717
|
+
const attrs = [
|
|
718
|
+
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
|
|
719
|
+
];
|
|
720
|
+
if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
|
|
721
|
+
const otlp = buildOtlpSpan({
|
|
722
|
+
ids,
|
|
723
|
+
name: args.name,
|
|
724
|
+
startTimeUnixNano: args.startTimeUnixNano,
|
|
725
|
+
endTimeUnixNano: args.endTimeUnixNano,
|
|
726
|
+
attributes: attrs,
|
|
727
|
+
status: args.status
|
|
728
|
+
});
|
|
729
|
+
this.enqueue(otlp);
|
|
730
|
+
if (this.localDebuggerUrl) {
|
|
731
|
+
const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
|
|
732
|
+
mirrorTraceExportToLocalDebugger(body, {
|
|
733
|
+
baseUrl: this.localDebuggerUrl,
|
|
734
|
+
debug: false,
|
|
735
|
+
sdkName: this.sdkName
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
enqueue(span) {
|
|
740
|
+
if (!this.enabled) return;
|
|
741
|
+
if (this.debugSpans) {
|
|
742
|
+
const short = (s) => s ? s.slice(-8) : "none";
|
|
743
|
+
console.log(
|
|
744
|
+
`${this.prefix}[span] name=${span.name} trace=${short(span.traceId)} span=${short(span.spanId)} parent=${short(
|
|
745
|
+
span.parentSpanId
|
|
746
|
+
)}`
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
750
|
+
this.queue.shift();
|
|
751
|
+
}
|
|
752
|
+
this.queue.push(span);
|
|
753
|
+
if (this.queue.length >= this.maxBatchSize) {
|
|
754
|
+
void this.flush().catch(() => {
|
|
755
|
+
});
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (!this.timer) {
|
|
759
|
+
this.timer = setTimeout(() => {
|
|
760
|
+
this.timer = void 0;
|
|
761
|
+
void this.flush().catch(() => {
|
|
762
|
+
});
|
|
763
|
+
}, this.flushIntervalMs);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
async flush() {
|
|
767
|
+
if (!this.enabled) return;
|
|
768
|
+
if (this.timer) {
|
|
769
|
+
clearTimeout(this.timer);
|
|
770
|
+
this.timer = void 0;
|
|
771
|
+
}
|
|
772
|
+
while (this.queue.length > 0) {
|
|
773
|
+
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
774
|
+
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
775
|
+
const url = `${this.baseUrl}traces`;
|
|
776
|
+
if (this.debug) {
|
|
777
|
+
console.log(`${this.prefix} sending traces batch`, {
|
|
778
|
+
spans: batch.length,
|
|
779
|
+
endpoint: url
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
const p = postJson(url, body, this.authHeaders(), {
|
|
783
|
+
maxAttempts: 3,
|
|
784
|
+
debug: this.debug,
|
|
785
|
+
sdkName: this.sdkName
|
|
786
|
+
});
|
|
787
|
+
this.inFlight.add(p);
|
|
788
|
+
try {
|
|
789
|
+
try {
|
|
790
|
+
await p;
|
|
791
|
+
if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
|
|
792
|
+
} catch (err) {
|
|
793
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
794
|
+
console.warn(`${this.prefix} failed to send ${batch.length} spans: ${msg}`);
|
|
795
|
+
}
|
|
796
|
+
} finally {
|
|
797
|
+
this.inFlight.delete(p);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
async shutdown() {
|
|
802
|
+
if (this.timer) {
|
|
803
|
+
clearTimeout(this.timer);
|
|
804
|
+
this.timer = void 0;
|
|
805
|
+
}
|
|
806
|
+
await this.flush();
|
|
807
|
+
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
808
|
+
})));
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
// ../core/dist/index.node.js
|
|
813
|
+
var import_async_hooks = require("async_hooks");
|
|
814
|
+
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
|
|
815
|
+
|
|
816
|
+
// src/internal/shipper.ts
|
|
817
|
+
var EventShipper2 = class extends EventShipper {
|
|
818
|
+
constructor(opts) {
|
|
819
|
+
var _a, _b, _c, _d;
|
|
820
|
+
super({
|
|
821
|
+
...opts,
|
|
822
|
+
sdkName: (_a = opts.sdkName) != null ? _a : "pi-agent",
|
|
823
|
+
libraryName: (_b = opts.libraryName) != null ? _b : libraryName,
|
|
824
|
+
libraryVersion: (_c = opts.libraryVersion) != null ? _c : libraryVersion,
|
|
825
|
+
defaultEventName: (_d = opts.defaultEventName) != null ? _d : "pi_agent_prompt"
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
830
|
+
constructor(opts) {
|
|
831
|
+
var _a, _b, _c;
|
|
832
|
+
super({
|
|
833
|
+
...opts,
|
|
834
|
+
sdkName: (_a = opts.sdkName) != null ? _a : "pi-agent",
|
|
835
|
+
serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.pi-agent",
|
|
836
|
+
serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
enqueue(span) {
|
|
840
|
+
var _a;
|
|
841
|
+
const attrs = (_a = span.attributes) != null ? _a : [];
|
|
842
|
+
attrs.unshift(
|
|
843
|
+
{ key: "span.id", value: { stringValue: span.spanId } },
|
|
844
|
+
...span.parentSpanId ? [{ key: "span.parent.id", value: { stringValue: span.parentSpanId } }] : []
|
|
845
|
+
);
|
|
846
|
+
span.attributes = attrs;
|
|
847
|
+
super.enqueue(span);
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
// src/internal/helpers.ts
|
|
852
|
+
var import_node_os2 = require("os");
|
|
853
|
+
function extractAssistantText(message) {
|
|
854
|
+
if (!("role" in message) || message.role !== "assistant") return void 0;
|
|
855
|
+
if (!Array.isArray(message.content)) return void 0;
|
|
856
|
+
const textParts = [];
|
|
857
|
+
for (const block of message.content) {
|
|
858
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
859
|
+
textParts.push(block.text);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return textParts.length > 0 ? textParts.join("\n") : void 0;
|
|
863
|
+
}
|
|
864
|
+
function formatToolSpanName(toolName, args) {
|
|
865
|
+
if (!args || typeof args !== "object") return toolName;
|
|
866
|
+
try {
|
|
867
|
+
const obj = args;
|
|
868
|
+
const firstValue = Object.values(obj)[0];
|
|
869
|
+
if (typeof firstValue === "string" && firstValue.length > 0) {
|
|
870
|
+
const preview = firstValue.length > 40 ? firstValue.slice(0, 37) + "..." : firstValue;
|
|
871
|
+
return `${toolName}: ${preview}`;
|
|
872
|
+
}
|
|
873
|
+
} catch (e) {
|
|
874
|
+
}
|
|
875
|
+
return toolName;
|
|
876
|
+
}
|
|
877
|
+
function safeStringify(value) {
|
|
878
|
+
if (value === void 0 || value === null) return void 0;
|
|
879
|
+
try {
|
|
880
|
+
return JSON.stringify(value);
|
|
881
|
+
} catch (e) {
|
|
882
|
+
try {
|
|
883
|
+
return String(value);
|
|
884
|
+
} catch (e2) {
|
|
885
|
+
return "[unserializable]";
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
var MAX_ATTR_LENGTH = 32768;
|
|
890
|
+
function truncate(value) {
|
|
891
|
+
if (value === void 0) return void 0;
|
|
892
|
+
if (value.length <= MAX_ATTR_LENGTH) return value;
|
|
893
|
+
const suffix = "\n...[truncated]";
|
|
894
|
+
return value.slice(0, MAX_ATTR_LENGTH - suffix.length) + suffix;
|
|
895
|
+
}
|
|
896
|
+
var _hostname;
|
|
897
|
+
function getHostname() {
|
|
898
|
+
var _a;
|
|
899
|
+
if (_hostname) return _hostname;
|
|
900
|
+
try {
|
|
901
|
+
_hostname = (0, import_node_os2.hostname)();
|
|
902
|
+
} catch (e) {
|
|
903
|
+
_hostname = (_a = process.env.HOSTNAME) != null ? _a : "unknown";
|
|
904
|
+
}
|
|
905
|
+
return _hostname;
|
|
906
|
+
}
|
|
907
|
+
var _username;
|
|
908
|
+
function getUsername() {
|
|
909
|
+
var _a, _b;
|
|
910
|
+
if (_username) return _username;
|
|
911
|
+
try {
|
|
912
|
+
_username = (0, import_node_os2.userInfo)().username;
|
|
913
|
+
} catch (e) {
|
|
914
|
+
_username = (_b = (_a = process.env.USER) != null ? _a : process.env.USERNAME) != null ? _b : "unknown";
|
|
915
|
+
}
|
|
916
|
+
return _username;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// src/internal/extension-tracing.ts
|
|
920
|
+
function safeParsArgs(argsStr) {
|
|
921
|
+
try {
|
|
922
|
+
return JSON.parse(argsStr);
|
|
923
|
+
} catch (e) {
|
|
924
|
+
return void 0;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
var MAX_SYSTEM_PROMPT_LENGTH = 32768;
|
|
928
|
+
function createSessionState(sessionId) {
|
|
929
|
+
return {
|
|
930
|
+
sessionId,
|
|
931
|
+
currentInput: "",
|
|
932
|
+
turnNumber: 0,
|
|
933
|
+
totalInputTokens: 0,
|
|
934
|
+
totalOutputTokens: 0,
|
|
935
|
+
totalCacheReadTokens: 0,
|
|
936
|
+
toolSpanStarts: /* @__PURE__ */ new Map(),
|
|
937
|
+
toolCallToLlmParent: /* @__PURE__ */ new Map()
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
function getUserId(state, metadata) {
|
|
941
|
+
var _a;
|
|
942
|
+
return (_a = metadata == null ? void 0 : metadata.userId) != null ? _a : state.sessionId;
|
|
943
|
+
}
|
|
944
|
+
function getEventName(config) {
|
|
945
|
+
var _a, _b;
|
|
946
|
+
return (_b = (_a = config.eventMetadata) == null ? void 0 : _a.eventName) != null ? _b : config.eventName;
|
|
947
|
+
}
|
|
948
|
+
function truncateSystemPrompt(systemPrompt) {
|
|
949
|
+
if (systemPrompt.length <= MAX_SYSTEM_PROMPT_LENGTH) return systemPrompt;
|
|
950
|
+
const suffix = "\n...[truncated]";
|
|
951
|
+
return systemPrompt.slice(0, MAX_SYSTEM_PROMPT_LENGTH - suffix.length) + suffix;
|
|
952
|
+
}
|
|
953
|
+
function getBaseProperties(config, ctx) {
|
|
954
|
+
var _a;
|
|
955
|
+
return {
|
|
956
|
+
workspace: ctx.cwd,
|
|
957
|
+
directory: ctx.cwd,
|
|
958
|
+
hostname: getHostname(),
|
|
959
|
+
os: process.platform,
|
|
960
|
+
username: getUsername(),
|
|
961
|
+
sdk_version: libraryVersion,
|
|
962
|
+
...(_a = config.eventMetadata) == null ? void 0 : _a.properties
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
function getSystemPromptAttributes(systemPrompt) {
|
|
966
|
+
if (!systemPrompt) return [];
|
|
967
|
+
return [
|
|
968
|
+
attrString("gen_ai.prompt.0.role", "system"),
|
|
969
|
+
attrString("gen_ai.prompt.0.content", systemPrompt)
|
|
970
|
+
];
|
|
971
|
+
}
|
|
972
|
+
function getAssistantText(message) {
|
|
973
|
+
var _a;
|
|
974
|
+
return (_a = extractAssistantText(message)) != null ? _a : "";
|
|
975
|
+
}
|
|
976
|
+
function getAssistantError(message) {
|
|
977
|
+
var _a;
|
|
978
|
+
if (message.role !== "assistant") return void 0;
|
|
979
|
+
if (message.stopReason !== "error" && message.stopReason !== "aborted") return void 0;
|
|
980
|
+
return (_a = message.errorMessage) != null ? _a : `Assistant ${message.stopReason}`;
|
|
981
|
+
}
|
|
982
|
+
function getState(stateRef, ctx) {
|
|
983
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
984
|
+
if (!stateRef.current || stateRef.current.sessionId !== sessionId) {
|
|
985
|
+
stateRef.current = createSessionState(sessionId);
|
|
986
|
+
}
|
|
987
|
+
return stateRef.current;
|
|
988
|
+
}
|
|
989
|
+
function registerTracing(pi, config, eventShipper, traceShipper) {
|
|
990
|
+
const stateRef = {};
|
|
991
|
+
function logError(hook, err) {
|
|
992
|
+
console.log(
|
|
993
|
+
`[raindrop-ai/pi-agent] [error] Error in ${hook}: ${err instanceof Error ? err.message : String(err)}`
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
function startTurnSpan(state) {
|
|
997
|
+
if (!state.currentEventId || !state.currentRootSpan) return;
|
|
998
|
+
if (state.currentTurnSpan) {
|
|
999
|
+
traceShipper.endSpan(state.currentTurnSpan);
|
|
1000
|
+
}
|
|
1001
|
+
state.turnNumber += 1;
|
|
1002
|
+
state.currentTurnSpan = traceShipper.startSpan({
|
|
1003
|
+
name: `Turn ${state.turnNumber}`,
|
|
1004
|
+
parent: state.currentRootSpan.ids,
|
|
1005
|
+
eventId: state.currentEventId,
|
|
1006
|
+
attributes: [
|
|
1007
|
+
attrString("ai.operationId", "ai.turn"),
|
|
1008
|
+
attrInt("ai.turn_number", state.turnNumber)
|
|
1009
|
+
]
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
function ensureTurnSpan(state) {
|
|
1013
|
+
if (state.currentTurnSpan) return;
|
|
1014
|
+
startTurnSpan(state);
|
|
1015
|
+
}
|
|
1016
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
1017
|
+
try {
|
|
1018
|
+
stateRef.current = createSessionState(ctx.sessionManager.getSessionId());
|
|
1019
|
+
} catch (err) {
|
|
1020
|
+
logError("session_start", err);
|
|
1021
|
+
}
|
|
1022
|
+
});
|
|
1023
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
1024
|
+
var _a, _b, _c;
|
|
1025
|
+
try {
|
|
1026
|
+
const state = getState(stateRef, ctx);
|
|
1027
|
+
if (state.currentTurnSpan) {
|
|
1028
|
+
traceShipper.endSpan(state.currentTurnSpan);
|
|
1029
|
+
state.currentTurnSpan = void 0;
|
|
1030
|
+
}
|
|
1031
|
+
if (state.currentRootSpan) {
|
|
1032
|
+
traceShipper.endSpan(state.currentRootSpan, { error: "Previous run was not finalized" });
|
|
1033
|
+
state.currentRootSpan = void 0;
|
|
1034
|
+
}
|
|
1035
|
+
if (state.currentEventId) {
|
|
1036
|
+
await eventShipper.finish((_a = state.currentEventRequestId) != null ? _a : state.currentEventId, {
|
|
1037
|
+
userId: getUserId(state, config.eventMetadata),
|
|
1038
|
+
properties: { sdk_version: libraryVersion, incomplete: true }
|
|
1039
|
+
});
|
|
1040
|
+
state.currentEventRequestId = void 0;
|
|
1041
|
+
state.currentEventId = void 0;
|
|
1042
|
+
}
|
|
1043
|
+
state.toolSpanStarts.clear();
|
|
1044
|
+
state.toolCallToLlmParent.clear();
|
|
1045
|
+
state.currentInput = event.prompt;
|
|
1046
|
+
state.turnNumber = 0;
|
|
1047
|
+
state.currentSystemPrompt = config.captureSystemPrompt ? truncateSystemPrompt(event.systemPrompt) : void 0;
|
|
1048
|
+
state.currentEventRequestId = generateId();
|
|
1049
|
+
state.totalInputTokens = 0;
|
|
1050
|
+
state.totalOutputTokens = 0;
|
|
1051
|
+
state.totalCacheReadTokens = 0;
|
|
1052
|
+
const attachments = (_c = (_b = event.images) == null ? void 0 : _b.map((image, index) => {
|
|
1053
|
+
var _a2, _b2;
|
|
1054
|
+
return {
|
|
1055
|
+
type: "image",
|
|
1056
|
+
role: "input",
|
|
1057
|
+
name: `image-${index + 1}.${(_b2 = (_a2 = image.mimeType.split("/")[1]) == null ? void 0 : _a2.split("+")[0]) != null ? _b2 : "png"}`,
|
|
1058
|
+
value: `data:${image.mimeType};base64,${image.data}`
|
|
1059
|
+
};
|
|
1060
|
+
})) != null ? _c : [];
|
|
1061
|
+
await eventShipper.patch(state.currentEventRequestId, {
|
|
1062
|
+
isPending: true,
|
|
1063
|
+
userId: getUserId(state, config.eventMetadata),
|
|
1064
|
+
convoId: state.sessionId,
|
|
1065
|
+
eventName: getEventName(config),
|
|
1066
|
+
input: event.prompt,
|
|
1067
|
+
...attachments.length > 0 ? { attachments } : {},
|
|
1068
|
+
properties: getBaseProperties(config, ctx)
|
|
1069
|
+
});
|
|
1070
|
+
await eventShipper.flush();
|
|
1071
|
+
state.currentEventId = state.currentEventRequestId;
|
|
1072
|
+
state.currentRootSpan = traceShipper.startSpan({
|
|
1073
|
+
name: "ai.event",
|
|
1074
|
+
eventId: state.currentEventId,
|
|
1075
|
+
attributes: [
|
|
1076
|
+
attrString("ai.prompt", truncate(state.currentInput)),
|
|
1077
|
+
attrString("workspace", ctx.cwd),
|
|
1078
|
+
attrString("hostname", getHostname()),
|
|
1079
|
+
attrString("os", process.platform),
|
|
1080
|
+
attrString("username", getUsername())
|
|
1081
|
+
]
|
|
1082
|
+
});
|
|
1083
|
+
} catch (err) {
|
|
1084
|
+
logError("before_agent_start", err);
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
pi.on("turn_start", async (_event, ctx) => {
|
|
1088
|
+
try {
|
|
1089
|
+
const state = getState(stateRef, ctx);
|
|
1090
|
+
startTurnSpan(state);
|
|
1091
|
+
} catch (err) {
|
|
1092
|
+
logError("turn_start", err);
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
pi.on("turn_end", async (_event, ctx) => {
|
|
1096
|
+
try {
|
|
1097
|
+
const state = getState(stateRef, ctx);
|
|
1098
|
+
if (!state.currentTurnSpan) return;
|
|
1099
|
+
traceShipper.endSpan(state.currentTurnSpan);
|
|
1100
|
+
state.currentTurnSpan = void 0;
|
|
1101
|
+
} catch (err) {
|
|
1102
|
+
logError("turn_end", err);
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
pi.on("message_end", async (event, ctx) => {
|
|
1106
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1107
|
+
try {
|
|
1108
|
+
if (((_a = event.message) == null ? void 0 : _a.role) !== "assistant") return;
|
|
1109
|
+
const state = getState(stateRef, ctx);
|
|
1110
|
+
if (!state.currentEventId || !state.currentRootSpan) return;
|
|
1111
|
+
ensureTurnSpan(state);
|
|
1112
|
+
const message = event.message;
|
|
1113
|
+
const provider = (_b = message.provider) != null ? _b : "";
|
|
1114
|
+
const modelId = (_c = message.model) != null ? _c : "";
|
|
1115
|
+
const modelName = provider && modelId ? `${provider}/${modelId}` : modelId || "llm";
|
|
1116
|
+
const errorForSpan = getAssistantError(message);
|
|
1117
|
+
const outputText = getAssistantText(message);
|
|
1118
|
+
const inputTokens = (_d = message.usage) == null ? void 0 : _d.input;
|
|
1119
|
+
const outputTokens = (_e = message.usage) == null ? void 0 : _e.output;
|
|
1120
|
+
const cacheReadTokens = (_f = message.usage) == null ? void 0 : _f.cacheRead;
|
|
1121
|
+
if (typeof inputTokens === "number") state.totalInputTokens += inputTokens;
|
|
1122
|
+
if (typeof outputTokens === "number") state.totalOutputTokens += outputTokens;
|
|
1123
|
+
if (typeof cacheReadTokens === "number" && cacheReadTokens > 0) state.totalCacheReadTokens += cacheReadTokens;
|
|
1124
|
+
const turnParent = (_g = state.currentTurnSpan) != null ? _g : state.currentRootSpan;
|
|
1125
|
+
const llmAttrs = [
|
|
1126
|
+
attrString("ai.operationId", "generateText"),
|
|
1127
|
+
provider ? attrString("gen_ai.system", provider) : void 0,
|
|
1128
|
+
modelId ? attrString("gen_ai.request.model", modelId) : void 0,
|
|
1129
|
+
modelId ? attrString("gen_ai.response.model", modelId) : void 0,
|
|
1130
|
+
typeof inputTokens === "number" ? attrInt("gen_ai.usage.input_tokens", inputTokens) : void 0,
|
|
1131
|
+
typeof outputTokens === "number" ? attrInt("gen_ai.usage.output_tokens", outputTokens) : void 0,
|
|
1132
|
+
typeof cacheReadTokens === "number" && cacheReadTokens > 0 ? attrInt("gen_ai.usage.cache_read_tokens", cacheReadTokens) : void 0,
|
|
1133
|
+
outputText ? attrString("ai.response.text", truncate(outputText)) : void 0,
|
|
1134
|
+
state.currentInput ? attrString("ai.prompt", truncate(state.currentInput)) : void 0,
|
|
1135
|
+
message.stopReason ? attrString("ai.stop_reason", message.stopReason) : void 0,
|
|
1136
|
+
...getSystemPromptAttributes(state.currentSystemPrompt)
|
|
1137
|
+
].filter(Boolean);
|
|
1138
|
+
const llmSpan = traceShipper.startSpan({
|
|
1139
|
+
name: modelName,
|
|
1140
|
+
parent: turnParent.ids,
|
|
1141
|
+
eventId: state.currentEventId,
|
|
1142
|
+
attributes: llmAttrs
|
|
1143
|
+
});
|
|
1144
|
+
traceShipper.endSpan(llmSpan, errorForSpan ? { error: errorForSpan } : void 0);
|
|
1145
|
+
if (Array.isArray(message.content)) {
|
|
1146
|
+
for (const part of message.content) {
|
|
1147
|
+
if (part && typeof part === "object" && part.type === "toolCall" && typeof part.id === "string") {
|
|
1148
|
+
state.toolCallToLlmParent.set(part.id, llmSpan.ids);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
if (message.stopReason === "toolUse") {
|
|
1153
|
+
await traceShipper.flush();
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
if (state.currentTurnSpan) {
|
|
1157
|
+
traceShipper.endSpan(state.currentTurnSpan);
|
|
1158
|
+
state.currentTurnSpan = void 0;
|
|
1159
|
+
}
|
|
1160
|
+
state.currentRootSpan.name = modelName;
|
|
1161
|
+
traceShipper.endSpan(state.currentRootSpan, {
|
|
1162
|
+
attributes: [
|
|
1163
|
+
...modelId ? [attrString("gen_ai.response.model", modelId)] : [],
|
|
1164
|
+
...outputText ? [attrString("ai.response.text", truncate(outputText))] : [],
|
|
1165
|
+
attrInt("ai.total_turns", state.turnNumber)
|
|
1166
|
+
],
|
|
1167
|
+
...errorForSpan ? { error: errorForSpan } : {}
|
|
1168
|
+
});
|
|
1169
|
+
state.currentRootSpan = void 0;
|
|
1170
|
+
await eventShipper.finish((_h = state.currentEventRequestId) != null ? _h : state.currentEventId, {
|
|
1171
|
+
userId: getUserId(state, config.eventMetadata),
|
|
1172
|
+
model: modelName,
|
|
1173
|
+
...outputText.trim() ? { output: outputText } : {},
|
|
1174
|
+
properties: {
|
|
1175
|
+
sdk_version: libraryVersion,
|
|
1176
|
+
stop_reason: message.stopReason,
|
|
1177
|
+
...state.totalInputTokens > 0 ? { "ai.usage.prompt_tokens": state.totalInputTokens } : {},
|
|
1178
|
+
...state.totalOutputTokens > 0 ? { "ai.usage.completion_tokens": state.totalOutputTokens } : {},
|
|
1179
|
+
...state.totalCacheReadTokens > 0 ? { "ai.usage.cache_read_tokens": state.totalCacheReadTokens } : {}
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
state.currentEventRequestId = void 0;
|
|
1183
|
+
state.currentEventId = void 0;
|
|
1184
|
+
state.toolSpanStarts.clear();
|
|
1185
|
+
state.toolCallToLlmParent.clear();
|
|
1186
|
+
await traceShipper.flush();
|
|
1187
|
+
} catch (err) {
|
|
1188
|
+
logError("message_end", err);
|
|
1189
|
+
}
|
|
1190
|
+
});
|
|
1191
|
+
pi.on("tool_execution_start", async (event, ctx) => {
|
|
1192
|
+
var _a, _b, _c;
|
|
1193
|
+
try {
|
|
1194
|
+
const state = getState(stateRef, ctx);
|
|
1195
|
+
if (!state.currentEventId || !state.currentRootSpan) return;
|
|
1196
|
+
const llmParent = state.toolCallToLlmParent.get(event.toolCallId);
|
|
1197
|
+
const parent = (_b = llmParent != null ? llmParent : (_a = state.currentTurnSpan) == null ? void 0 : _a.ids) != null ? _b : state.currentRootSpan.ids;
|
|
1198
|
+
state.toolSpanStarts.set(event.toolCallId, {
|
|
1199
|
+
startTimeUnixNano: nowUnixNanoString(),
|
|
1200
|
+
parent,
|
|
1201
|
+
eventId: state.currentEventId,
|
|
1202
|
+
name: event.toolName,
|
|
1203
|
+
args: (_c = safeStringify(event.args)) != null ? _c : "{}"
|
|
1204
|
+
});
|
|
1205
|
+
} catch (err) {
|
|
1206
|
+
logError("tool_execution_start", err);
|
|
1207
|
+
}
|
|
1208
|
+
});
|
|
1209
|
+
pi.on("tool_execution_end", async (event, ctx) => {
|
|
1210
|
+
try {
|
|
1211
|
+
const state = getState(stateRef, ctx);
|
|
1212
|
+
const start = state.toolSpanStarts.get(event.toolCallId);
|
|
1213
|
+
if (!start) return;
|
|
1214
|
+
state.toolSpanStarts.delete(event.toolCallId);
|
|
1215
|
+
state.toolCallToLlmParent.delete(event.toolCallId);
|
|
1216
|
+
const resultStr = safeStringify(event.result);
|
|
1217
|
+
traceShipper.createSpan({
|
|
1218
|
+
name: formatToolSpanName(start.name, safeParsArgs(start.args)),
|
|
1219
|
+
parent: start.parent,
|
|
1220
|
+
eventId: start.eventId,
|
|
1221
|
+
startTimeUnixNano: start.startTimeUnixNano,
|
|
1222
|
+
endTimeUnixNano: nowUnixNanoString(),
|
|
1223
|
+
attributes: [
|
|
1224
|
+
attrString("ai.operationId", "ai.toolCall"),
|
|
1225
|
+
attrString("ai.toolCall.name", start.name),
|
|
1226
|
+
attrString("ai.toolCall.id", event.toolCallId),
|
|
1227
|
+
attrString("ai.toolCall.args", truncate(start.args)),
|
|
1228
|
+
...resultStr ? [attrString("ai.toolCall.result", truncate(resultStr))] : []
|
|
1229
|
+
],
|
|
1230
|
+
...event.isError ? { status: { code: 2, message: `Tool "${start.name}" failed` } } : {}
|
|
1231
|
+
});
|
|
1232
|
+
} catch (err) {
|
|
1233
|
+
logError("tool_execution_end", err);
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
pi.on("agent_end", async (_event, ctx) => {
|
|
1237
|
+
var _a;
|
|
1238
|
+
try {
|
|
1239
|
+
const state = getState(stateRef, ctx);
|
|
1240
|
+
if (state.currentTurnSpan) {
|
|
1241
|
+
traceShipper.endSpan(state.currentTurnSpan);
|
|
1242
|
+
state.currentTurnSpan = void 0;
|
|
1243
|
+
}
|
|
1244
|
+
if (state.currentRootSpan) {
|
|
1245
|
+
traceShipper.endSpan(state.currentRootSpan, {
|
|
1246
|
+
error: "Agent ended before a final assistant response was recorded"
|
|
1247
|
+
});
|
|
1248
|
+
state.currentRootSpan = void 0;
|
|
1249
|
+
}
|
|
1250
|
+
if (state.currentEventId) {
|
|
1251
|
+
await eventShipper.finish((_a = state.currentEventRequestId) != null ? _a : state.currentEventId, {
|
|
1252
|
+
userId: getUserId(state, config.eventMetadata),
|
|
1253
|
+
properties: {
|
|
1254
|
+
sdk_version: libraryVersion,
|
|
1255
|
+
incomplete: true
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
state.currentEventRequestId = void 0;
|
|
1259
|
+
state.currentEventId = void 0;
|
|
1260
|
+
}
|
|
1261
|
+
state.toolSpanStarts.clear();
|
|
1262
|
+
state.toolCallToLlmParent.clear();
|
|
1263
|
+
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
1264
|
+
} catch (err) {
|
|
1265
|
+
logError("agent_end", err);
|
|
1266
|
+
}
|
|
1267
|
+
});
|
|
1268
|
+
pi.on("session_shutdown", async (_event, _ctx) => {
|
|
1269
|
+
try {
|
|
1270
|
+
stateRef.current = void 0;
|
|
1271
|
+
await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
|
|
1272
|
+
} catch (err) {
|
|
1273
|
+
logError("session_shutdown", err);
|
|
1274
|
+
}
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// src/extension.ts
|
|
1279
|
+
var PLUGIN_NAME = "@raindrop-ai/pi-agent";
|
|
1280
|
+
function extension(pi) {
|
|
1281
|
+
const config = loadConfig(process.cwd());
|
|
1282
|
+
function appLog(level, message) {
|
|
1283
|
+
console.log(`[raindrop-ai/pi-agent] [${level}] ${message}`);
|
|
1284
|
+
}
|
|
1285
|
+
appLog("info", `Loading ${PLUGIN_NAME} v${libraryVersion}`);
|
|
1286
|
+
if (!config.writeKey) {
|
|
1287
|
+
appLog(
|
|
1288
|
+
"warn",
|
|
1289
|
+
"RAINDROP_WRITE_KEY not set \u2014 Raindrop tracing disabled. Set it in your environment or in ~/.pi/agent/raindrop.json."
|
|
1290
|
+
);
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
if (config.debug) {
|
|
1294
|
+
appLog("info", `Raindrop tracing enabled (endpoint: ${config.endpoint})`);
|
|
1295
|
+
}
|
|
1296
|
+
const eventShipper = new EventShipper2({
|
|
1297
|
+
writeKey: config.writeKey,
|
|
1298
|
+
endpoint: config.endpoint,
|
|
1299
|
+
debug: config.debug
|
|
1300
|
+
});
|
|
1301
|
+
const traceShipper = new TraceShipper2({
|
|
1302
|
+
writeKey: config.writeKey,
|
|
1303
|
+
endpoint: config.endpoint,
|
|
1304
|
+
debug: config.debug
|
|
1305
|
+
});
|
|
1306
|
+
registerTracing(pi, config, eventShipper, traceShipper);
|
|
1307
|
+
}
|
|
1308
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1309
|
+
0 && (module.exports = {
|
|
1310
|
+
registerTracing
|
|
1311
|
+
});
|