@raindrop-ai/opencode-plugin 0.0.4 → 0.0.6
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/dist/index.cjs +364 -191
- package/dist/index.js +364 -191
- package/package.json +7 -3
package/dist/index.cjs
CHANGED
|
@@ -45,18 +45,27 @@ function loadConfig(projectDirectory) {
|
|
|
45
45
|
} catch (e) {
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
let eventMetadata;
|
|
49
|
+
const envMeta = process.env["RAINDROP_EVENT_METADATA"];
|
|
50
|
+
if (envMeta) {
|
|
51
|
+
try {
|
|
52
|
+
eventMetadata = JSON.parse(envMeta);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
48
56
|
return {
|
|
49
57
|
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
50
58
|
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
51
59
|
eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
|
|
52
|
-
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false
|
|
60
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
61
|
+
eventMetadata
|
|
53
62
|
};
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
// package.json
|
|
57
66
|
var package_default = {
|
|
58
67
|
name: "@raindrop-ai/opencode-plugin",
|
|
59
|
-
version: "0.0.
|
|
68
|
+
version: "0.0.6",
|
|
60
69
|
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
61
70
|
type: "module",
|
|
62
71
|
main: "dist/index.cjs",
|
|
@@ -77,7 +86,7 @@ var package_default = {
|
|
|
77
86
|
build: "tsup",
|
|
78
87
|
dev: "tsup --watch",
|
|
79
88
|
clean: "rm -rf dist",
|
|
80
|
-
test: "cd tests &&
|
|
89
|
+
test: "cd tests && pnpm test"
|
|
81
90
|
},
|
|
82
91
|
peerDependencies: {
|
|
83
92
|
"@opencode-ai/plugin": ">=1.2.0",
|
|
@@ -89,6 +98,7 @@ var package_default = {
|
|
|
89
98
|
}
|
|
90
99
|
},
|
|
91
100
|
devDependencies: {
|
|
101
|
+
"@raindrop-ai/core": "workspace:*",
|
|
92
102
|
"@opencode-ai/plugin": "^1.2.0",
|
|
93
103
|
"@opencode-ai/sdk": "^1.2.0",
|
|
94
104
|
"@types/node": "^20.11.17",
|
|
@@ -106,33 +116,44 @@ var package_default = {
|
|
|
106
116
|
dts: {
|
|
107
117
|
resolve: true
|
|
108
118
|
},
|
|
109
|
-
clean: true
|
|
119
|
+
clean: true,
|
|
120
|
+
noExternal: [
|
|
121
|
+
"@raindrop-ai/core"
|
|
122
|
+
]
|
|
110
123
|
},
|
|
111
124
|
publishConfig: {
|
|
112
125
|
access: "public"
|
|
113
126
|
}
|
|
114
127
|
};
|
|
115
128
|
|
|
116
|
-
// src/
|
|
129
|
+
// src/package-info.ts
|
|
130
|
+
var PLUGIN_NAME = package_default.name;
|
|
117
131
|
var PLUGIN_VERSION = package_default.version;
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
|
|
133
|
+
// ../core/dist/chunk-FTBZHS25.js
|
|
134
|
+
function getCrypto() {
|
|
135
|
+
const c = globalThis.crypto;
|
|
136
|
+
return c;
|
|
120
137
|
}
|
|
121
138
|
function randomBytes(length) {
|
|
122
|
-
const
|
|
139
|
+
const cryptoObj = getCrypto();
|
|
123
140
|
const out = new Uint8Array(length);
|
|
124
|
-
if (
|
|
125
|
-
|
|
141
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
142
|
+
cryptoObj.getRandomValues(out);
|
|
126
143
|
return out;
|
|
127
144
|
}
|
|
128
145
|
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
129
146
|
return out;
|
|
130
147
|
}
|
|
131
148
|
function base64Encode(bytes) {
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
149
|
+
const maybeBuffer = globalThis.Buffer;
|
|
150
|
+
if (maybeBuffer) {
|
|
151
|
+
return maybeBuffer.from(bytes).toString("base64");
|
|
152
|
+
}
|
|
134
153
|
let binary = "";
|
|
135
|
-
for (let i2 = 0; i2 < bytes.length; i2++)
|
|
154
|
+
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
155
|
+
binary += String.fromCharCode(bytes[i2]);
|
|
156
|
+
}
|
|
136
157
|
const btoaFn = globalThis.btoa;
|
|
137
158
|
if (typeof btoaFn === "function") return btoaFn(binary);
|
|
138
159
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
@@ -153,69 +174,9 @@ function base64Encode(bytes) {
|
|
|
153
174
|
}
|
|
154
175
|
return out;
|
|
155
176
|
}
|
|
156
|
-
var SERVICE_NAME = "raindrop.opencode-plugin";
|
|
157
|
-
var SpanStatusCode = {
|
|
158
|
-
ERROR: 2
|
|
159
|
-
};
|
|
160
177
|
function generateId() {
|
|
161
178
|
return base64Encode(randomBytes(12)).replace(/[+/=]/g, "").slice(0, 16);
|
|
162
179
|
}
|
|
163
|
-
function createSpanIds(parent) {
|
|
164
|
-
const traceId = parent ? parent.traceIdB64 : base64Encode(randomBytes(16));
|
|
165
|
-
const spanId = base64Encode(randomBytes(8));
|
|
166
|
-
return {
|
|
167
|
-
traceIdB64: traceId,
|
|
168
|
-
spanIdB64: spanId,
|
|
169
|
-
parentSpanIdB64: parent ? parent.spanIdB64 : void 0
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function nowUnixNanoString() {
|
|
173
|
-
return Date.now().toString() + "000000";
|
|
174
|
-
}
|
|
175
|
-
function attrString(key, value) {
|
|
176
|
-
if (value === void 0) return void 0;
|
|
177
|
-
return { key, value: { stringValue: value } };
|
|
178
|
-
}
|
|
179
|
-
function attrInt(key, value) {
|
|
180
|
-
if (value === void 0) return void 0;
|
|
181
|
-
if (!Number.isFinite(value)) return void 0;
|
|
182
|
-
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
183
|
-
}
|
|
184
|
-
function buildOtlpSpan(args) {
|
|
185
|
-
const attrs = [
|
|
186
|
-
attrString("span.id", args.ids.spanIdB64),
|
|
187
|
-
attrString("span.parent.id", args.ids.parentSpanIdB64),
|
|
188
|
-
...args.attributes
|
|
189
|
-
].filter((x) => x !== void 0);
|
|
190
|
-
const span = {
|
|
191
|
-
traceId: args.ids.traceIdB64,
|
|
192
|
-
spanId: args.ids.spanIdB64,
|
|
193
|
-
name: args.name,
|
|
194
|
-
startTimeUnixNano: args.startTimeUnixNano,
|
|
195
|
-
endTimeUnixNano: args.endTimeUnixNano
|
|
196
|
-
};
|
|
197
|
-
if (args.ids.parentSpanIdB64) span.parentSpanId = args.ids.parentSpanIdB64;
|
|
198
|
-
if (attrs.length) span.attributes = attrs;
|
|
199
|
-
if (args.status) span.status = args.status;
|
|
200
|
-
return span;
|
|
201
|
-
}
|
|
202
|
-
function buildExportTraceServiceRequest(spans) {
|
|
203
|
-
return {
|
|
204
|
-
resourceSpans: [
|
|
205
|
-
{
|
|
206
|
-
resource: {
|
|
207
|
-
attributes: [{ key: "service.name", value: { stringValue: SERVICE_NAME } }]
|
|
208
|
-
},
|
|
209
|
-
scopeSpans: [
|
|
210
|
-
{
|
|
211
|
-
scope: { name: SERVICE_NAME, version: PLUGIN_VERSION },
|
|
212
|
-
spans
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
]
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
180
|
function wait(ms) {
|
|
220
181
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
221
182
|
}
|
|
@@ -228,7 +189,7 @@ function parseRetryAfter(headers) {
|
|
|
228
189
|
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
229
190
|
if (!value) return void 0;
|
|
230
191
|
const asNumber = Number(value);
|
|
231
|
-
if (!Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
192
|
+
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
232
193
|
const asDate = new Date(value).getTime();
|
|
233
194
|
if (!Number.isNaN(asDate)) {
|
|
234
195
|
const delta = asDate - Date.now();
|
|
@@ -237,26 +198,29 @@ function parseRetryAfter(headers) {
|
|
|
237
198
|
return void 0;
|
|
238
199
|
}
|
|
239
200
|
function getRetryDelayMs(attemptNumber, previousError) {
|
|
240
|
-
if (previousError
|
|
201
|
+
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
241
202
|
const v = previousError.retryAfterMs;
|
|
242
203
|
if (typeof v === "number") return Math.max(0, v);
|
|
243
204
|
}
|
|
244
205
|
if (attemptNumber <= 1) return 0;
|
|
245
|
-
|
|
206
|
+
const base = 500;
|
|
207
|
+
const factor = Math.pow(2, attemptNumber - 2);
|
|
208
|
+
return base * factor;
|
|
246
209
|
}
|
|
247
210
|
async function withRetry(operation, opName, opts) {
|
|
211
|
+
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
248
212
|
let lastError = void 0;
|
|
249
|
-
for (let
|
|
250
|
-
if (
|
|
251
|
-
const delay = getRetryDelayMs(
|
|
213
|
+
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
214
|
+
if (attemptNumber > 1) {
|
|
215
|
+
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
252
216
|
if (opts.debug) {
|
|
253
217
|
console.warn(
|
|
254
|
-
|
|
218
|
+
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
255
219
|
);
|
|
256
220
|
}
|
|
257
221
|
if (delay > 0) await wait(delay);
|
|
258
222
|
} else if (opts.debug) {
|
|
259
|
-
console.log(
|
|
223
|
+
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
260
224
|
}
|
|
261
225
|
try {
|
|
262
226
|
return await operation();
|
|
@@ -265,20 +229,26 @@ async function withRetry(operation, opName, opts) {
|
|
|
265
229
|
if (opts.debug) {
|
|
266
230
|
const msg = err instanceof Error ? err.message : String(err);
|
|
267
231
|
console.warn(
|
|
268
|
-
|
|
232
|
+
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
269
233
|
);
|
|
270
234
|
}
|
|
271
|
-
if (
|
|
235
|
+
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
236
|
+
break;
|
|
237
|
+
if (attemptNumber === opts.maxAttempts) break;
|
|
272
238
|
}
|
|
273
239
|
}
|
|
274
240
|
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
275
241
|
}
|
|
276
242
|
async function postJson(url, body, headers, opts) {
|
|
243
|
+
const opName = `POST ${url}`;
|
|
277
244
|
await withRetry(
|
|
278
245
|
async () => {
|
|
279
246
|
const resp = await fetch(url, {
|
|
280
247
|
method: "POST",
|
|
281
|
-
headers: {
|
|
248
|
+
headers: {
|
|
249
|
+
"Content-Type": "application/json",
|
|
250
|
+
...headers
|
|
251
|
+
},
|
|
282
252
|
body: JSON.stringify(body)
|
|
283
253
|
});
|
|
284
254
|
if (!resp.ok) {
|
|
@@ -288,13 +258,71 @@ async function postJson(url, body, headers, opts) {
|
|
|
288
258
|
);
|
|
289
259
|
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
290
260
|
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
261
|
+
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
291
262
|
throw err;
|
|
292
263
|
}
|
|
293
264
|
},
|
|
294
|
-
|
|
265
|
+
opName,
|
|
295
266
|
opts
|
|
296
267
|
);
|
|
297
268
|
}
|
|
269
|
+
var SpanStatusCode = {
|
|
270
|
+
UNSET: 0,
|
|
271
|
+
OK: 1,
|
|
272
|
+
ERROR: 2
|
|
273
|
+
};
|
|
274
|
+
function createSpanIds(parent) {
|
|
275
|
+
const traceId = parent ? parent.traceIdB64 : base64Encode(randomBytes(16));
|
|
276
|
+
const spanId = base64Encode(randomBytes(8));
|
|
277
|
+
return {
|
|
278
|
+
traceIdB64: traceId,
|
|
279
|
+
spanIdB64: spanId,
|
|
280
|
+
parentSpanIdB64: parent ? parent.spanIdB64 : void 0
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function nowUnixNanoString() {
|
|
284
|
+
return Date.now().toString() + "000000";
|
|
285
|
+
}
|
|
286
|
+
function attrString(key, value) {
|
|
287
|
+
if (value === void 0) return void 0;
|
|
288
|
+
return { key, value: { stringValue: value } };
|
|
289
|
+
}
|
|
290
|
+
function attrInt(key, value) {
|
|
291
|
+
if (value === void 0) return void 0;
|
|
292
|
+
if (!Number.isFinite(value)) return void 0;
|
|
293
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
294
|
+
}
|
|
295
|
+
function buildOtlpSpan(args) {
|
|
296
|
+
const attrs = args.attributes.filter((x) => x !== void 0);
|
|
297
|
+
const span = {
|
|
298
|
+
traceId: args.ids.traceIdB64,
|
|
299
|
+
spanId: args.ids.spanIdB64,
|
|
300
|
+
name: args.name,
|
|
301
|
+
startTimeUnixNano: args.startTimeUnixNano,
|
|
302
|
+
endTimeUnixNano: args.endTimeUnixNano
|
|
303
|
+
};
|
|
304
|
+
if (args.ids.parentSpanIdB64) span.parentSpanId = args.ids.parentSpanIdB64;
|
|
305
|
+
if (attrs.length) span.attributes = attrs;
|
|
306
|
+
if (args.status) span.status = args.status;
|
|
307
|
+
return span;
|
|
308
|
+
}
|
|
309
|
+
function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", serviceVersion = "0.0.0") {
|
|
310
|
+
return {
|
|
311
|
+
resourceSpans: [
|
|
312
|
+
{
|
|
313
|
+
resource: {
|
|
314
|
+
attributes: [{ key: "service.name", value: { stringValue: serviceName } }]
|
|
315
|
+
},
|
|
316
|
+
scopeSpans: [
|
|
317
|
+
{
|
|
318
|
+
scope: { name: serviceName, version: serviceVersion },
|
|
319
|
+
spans
|
|
320
|
+
}
|
|
321
|
+
]
|
|
322
|
+
}
|
|
323
|
+
]
|
|
324
|
+
};
|
|
325
|
+
}
|
|
298
326
|
function mergePatches(target, source) {
|
|
299
327
|
var _a, _b, _c, _d;
|
|
300
328
|
const out = { ...target, ...source };
|
|
@@ -312,34 +340,58 @@ var EventShipper = class {
|
|
|
312
340
|
this.sticky = /* @__PURE__ */ new Map();
|
|
313
341
|
this.timers = /* @__PURE__ */ new Map();
|
|
314
342
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
315
|
-
var _a, _b;
|
|
316
|
-
this.writeKey = opts.writeKey;
|
|
317
|
-
this.baseUrl = (
|
|
343
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
344
|
+
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
345
|
+
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
346
|
+
this.enabled = opts.enabled !== false;
|
|
318
347
|
this.debug = opts.debug;
|
|
319
|
-
this.partialFlushMs = (
|
|
348
|
+
this.partialFlushMs = (_c = opts.partialFlushMs) != null ? _c : 1e3;
|
|
349
|
+
this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
|
|
350
|
+
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
351
|
+
this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
|
|
352
|
+
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
353
|
+
this.context = {
|
|
354
|
+
library: {
|
|
355
|
+
name: (_f = opts.libraryName) != null ? _f : "@raindrop-ai/core",
|
|
356
|
+
version: (_g = opts.libraryVersion) != null ? _g : "0.0.0"
|
|
357
|
+
},
|
|
358
|
+
metadata: {
|
|
359
|
+
jsRuntime: isNode ? "node" : "web",
|
|
360
|
+
...isNode ? { nodeVersion: process.version } : {}
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
isDebugEnabled() {
|
|
365
|
+
return this.debug;
|
|
366
|
+
}
|
|
367
|
+
authHeaders() {
|
|
368
|
+
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
320
369
|
}
|
|
321
370
|
async patch(eventId, patch) {
|
|
322
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
323
|
-
if (!
|
|
371
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
372
|
+
if (!this.enabled) return;
|
|
373
|
+
if (!eventId || !eventId.trim()) return;
|
|
324
374
|
if (this.debug) {
|
|
325
|
-
console.log(
|
|
375
|
+
console.log(`${this.prefix} queue patch`, {
|
|
326
376
|
eventId,
|
|
327
377
|
userId: patch.userId,
|
|
378
|
+
eventName: patch.eventName,
|
|
328
379
|
hasInput: typeof patch.input === "string" && patch.input.length > 0,
|
|
329
380
|
hasOutput: typeof patch.output === "string" && patch.output.length > 0,
|
|
381
|
+
attachments: (_b = (_a = patch.attachments) == null ? void 0 : _a.length) != null ? _b : 0,
|
|
330
382
|
isPending: patch.isPending
|
|
331
383
|
});
|
|
332
384
|
}
|
|
333
|
-
const sticky = (
|
|
334
|
-
const existing = (
|
|
385
|
+
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
386
|
+
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
335
387
|
const merged = mergePatches(existing, patch);
|
|
336
|
-
merged.isPending = (
|
|
388
|
+
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
337
389
|
this.buffers.set(eventId, merged);
|
|
338
390
|
this.sticky.set(eventId, {
|
|
339
|
-
userId: (
|
|
340
|
-
convoId: (
|
|
341
|
-
eventName: (
|
|
342
|
-
isPending: (
|
|
391
|
+
userId: (_h = merged.userId) != null ? _h : sticky.userId,
|
|
392
|
+
convoId: (_i = merged.convoId) != null ? _i : sticky.convoId,
|
|
393
|
+
eventName: (_j = merged.eventName) != null ? _j : sticky.eventName,
|
|
394
|
+
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending
|
|
343
395
|
});
|
|
344
396
|
const t = this.timers.get(eventId);
|
|
345
397
|
if (t) clearTimeout(t);
|
|
@@ -357,6 +409,7 @@ var EventShipper = class {
|
|
|
357
409
|
await this.patch(eventId, { ...patch, isPending: false });
|
|
358
410
|
}
|
|
359
411
|
async flush() {
|
|
412
|
+
if (!this.enabled) return;
|
|
360
413
|
const ids = [...this.buffers.keys()];
|
|
361
414
|
await Promise.all(ids.map((id) => this.flushOne(id)));
|
|
362
415
|
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
@@ -367,8 +420,70 @@ var EventShipper = class {
|
|
|
367
420
|
this.timers.clear();
|
|
368
421
|
await this.flush();
|
|
369
422
|
}
|
|
423
|
+
async trackSignal(signal) {
|
|
424
|
+
var _a, _b;
|
|
425
|
+
if (!this.enabled) return;
|
|
426
|
+
const body = [
|
|
427
|
+
{
|
|
428
|
+
event_id: signal.eventId,
|
|
429
|
+
signal_name: signal.name,
|
|
430
|
+
signal_type: (_a = signal.type) != null ? _a : "default",
|
|
431
|
+
timestamp: signal.timestamp,
|
|
432
|
+
sentiment: signal.sentiment,
|
|
433
|
+
attachment_id: signal.attachmentId,
|
|
434
|
+
properties: {
|
|
435
|
+
...(_b = signal.properties) != null ? _b : {},
|
|
436
|
+
...signal.comment ? { comment: signal.comment } : {},
|
|
437
|
+
...signal.after ? { after: signal.after } : {}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
];
|
|
441
|
+
const url = `${this.baseUrl}signals/track`;
|
|
442
|
+
try {
|
|
443
|
+
await postJson(url, body, this.authHeaders(), {
|
|
444
|
+
maxAttempts: 3,
|
|
445
|
+
debug: this.debug,
|
|
446
|
+
sdkName: this.sdkName
|
|
447
|
+
});
|
|
448
|
+
} catch (err) {
|
|
449
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
450
|
+
console.warn(`${this.prefix} failed to send signal (dropping): ${msg}`);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async identify(users) {
|
|
454
|
+
if (!this.enabled) return;
|
|
455
|
+
const list = Array.isArray(users) ? users : [users];
|
|
456
|
+
const body = list.filter((user) => {
|
|
457
|
+
if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
|
|
458
|
+
if (this.debug) {
|
|
459
|
+
console.warn(`${this.prefix} skipping identify: missing userId`);
|
|
460
|
+
}
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
return true;
|
|
464
|
+
}).map((user) => {
|
|
465
|
+
var _a;
|
|
466
|
+
return {
|
|
467
|
+
user_id: user.userId,
|
|
468
|
+
traits: (_a = user.traits) != null ? _a : {}
|
|
469
|
+
};
|
|
470
|
+
});
|
|
471
|
+
if (body.length === 0) return;
|
|
472
|
+
const url = `${this.baseUrl}users/identify`;
|
|
473
|
+
try {
|
|
474
|
+
await postJson(url, body, this.authHeaders(), {
|
|
475
|
+
maxAttempts: 3,
|
|
476
|
+
debug: this.debug,
|
|
477
|
+
sdkName: this.sdkName
|
|
478
|
+
});
|
|
479
|
+
} catch (err) {
|
|
480
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
481
|
+
console.warn(`${this.prefix} failed to send identify (dropping): ${msg}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
370
484
|
async flushOne(eventId) {
|
|
371
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
485
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
486
|
+
if (!this.enabled) return;
|
|
372
487
|
const timer = this.timers.get(eventId);
|
|
373
488
|
if (timer) {
|
|
374
489
|
clearTimeout(timer);
|
|
@@ -378,105 +493,123 @@ var EventShipper = class {
|
|
|
378
493
|
this.buffers.delete(eventId);
|
|
379
494
|
if (!accumulated) return;
|
|
380
495
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
381
|
-
const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c :
|
|
496
|
+
const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c : this.defaultEventName;
|
|
382
497
|
const userId = (_d = accumulated.userId) != null ? _d : sticky.userId;
|
|
383
498
|
if (!userId) {
|
|
384
499
|
if (this.debug) {
|
|
385
|
-
console.warn(
|
|
386
|
-
`[raindrop-ai/opencode-plugin] skipping track_partial for ${eventId}: missing userId`
|
|
387
|
-
);
|
|
500
|
+
console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
|
|
388
501
|
}
|
|
502
|
+
this.sticky.delete(eventId);
|
|
389
503
|
return;
|
|
390
504
|
}
|
|
505
|
+
const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
|
|
391
506
|
const payload = {
|
|
392
507
|
event_id: eventId,
|
|
393
508
|
user_id: userId,
|
|
394
509
|
event: eventName,
|
|
395
|
-
timestamp: (
|
|
510
|
+
timestamp: (_f = accumulated.timestamp) != null ? _f : (/* @__PURE__ */ new Date()).toISOString(),
|
|
396
511
|
ai_data: {
|
|
397
512
|
input: accumulated.input,
|
|
398
513
|
output: accumulated.output,
|
|
399
514
|
model: accumulated.model,
|
|
400
|
-
convo_id: (
|
|
515
|
+
convo_id: (_g = accumulated.convoId) != null ? _g : sticky.convoId
|
|
401
516
|
},
|
|
402
517
|
properties: {
|
|
403
|
-
...
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
metadata: { jsRuntime: "node" }
|
|
407
|
-
}
|
|
518
|
+
...restProperties,
|
|
519
|
+
...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
|
|
520
|
+
$context: this.context
|
|
408
521
|
},
|
|
409
522
|
attachments: accumulated.attachments,
|
|
410
523
|
is_pending: ((_i = (_h = accumulated.isPending) != null ? _h : sticky.isPending) != null ? _i : true) !== false
|
|
411
524
|
};
|
|
412
525
|
const url = `${this.baseUrl}events/track_partial`;
|
|
413
526
|
if (this.debug) {
|
|
414
|
-
console.log(
|
|
527
|
+
console.log(`${this.prefix} sending track_partial`, {
|
|
415
528
|
eventId,
|
|
416
529
|
eventName,
|
|
417
530
|
userId,
|
|
418
|
-
isPending: payload
|
|
531
|
+
isPending: payload.is_pending,
|
|
419
532
|
inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
|
|
420
533
|
outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
|
|
534
|
+
attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
|
|
535
|
+
attachmentKinds: (_m = (_l = accumulated.attachments) == null ? void 0 : _l.map((a) => ({
|
|
536
|
+
type: a.type,
|
|
537
|
+
role: a.role,
|
|
538
|
+
name: a.name,
|
|
539
|
+
valuePreview: a.value.slice(0, 60)
|
|
540
|
+
}))) != null ? _m : [],
|
|
421
541
|
endpoint: url
|
|
422
542
|
});
|
|
423
543
|
}
|
|
424
|
-
const p = postJson(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
);
|
|
544
|
+
const p = postJson(url, payload, this.authHeaders(), {
|
|
545
|
+
maxAttempts: 3,
|
|
546
|
+
debug: this.debug,
|
|
547
|
+
sdkName: this.sdkName
|
|
548
|
+
});
|
|
430
549
|
this.inFlight.add(p);
|
|
431
550
|
try {
|
|
432
551
|
try {
|
|
433
552
|
await p;
|
|
434
553
|
if (this.debug) {
|
|
435
|
-
console.log(
|
|
554
|
+
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
436
555
|
}
|
|
437
556
|
} catch (err) {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
console.warn(
|
|
441
|
-
`[raindrop-ai/opencode-plugin] failed to send track_partial (dropping): ${msg}`
|
|
442
|
-
);
|
|
443
|
-
}
|
|
557
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
558
|
+
console.warn(`${this.prefix} failed to send track_partial (dropping): ${msg}`);
|
|
444
559
|
}
|
|
445
560
|
} finally {
|
|
446
561
|
this.inFlight.delete(p);
|
|
447
562
|
}
|
|
448
|
-
|
|
563
|
+
const isPending = payload.is_pending;
|
|
564
|
+
if (!isPending) {
|
|
565
|
+
this.sticky.delete(eventId);
|
|
566
|
+
}
|
|
449
567
|
}
|
|
450
568
|
};
|
|
451
569
|
var TraceShipper = class {
|
|
452
570
|
constructor(opts) {
|
|
453
571
|
this.queue = [];
|
|
454
572
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
455
|
-
var _a, _b;
|
|
456
|
-
this.writeKey = opts.writeKey;
|
|
457
|
-
this.baseUrl = (
|
|
573
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
574
|
+
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
575
|
+
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
576
|
+
this.enabled = opts.enabled !== false;
|
|
458
577
|
this.debug = opts.debug;
|
|
459
|
-
this.
|
|
460
|
-
this.
|
|
461
|
-
this.
|
|
578
|
+
this.debugSpans = opts.debugSpans === true;
|
|
579
|
+
this.flushIntervalMs = (_c = opts.flushIntervalMs) != null ? _c : 1e3;
|
|
580
|
+
this.maxBatchSize = (_d = opts.maxBatchSize) != null ? _d : 50;
|
|
581
|
+
this.maxQueueSize = (_e = opts.maxQueueSize) != null ? _e : 5e3;
|
|
582
|
+
this.sdkName = (_f = opts.sdkName) != null ? _f : "core";
|
|
583
|
+
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
584
|
+
this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
|
|
585
|
+
this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
|
|
586
|
+
}
|
|
587
|
+
isDebugEnabled() {
|
|
588
|
+
return this.debug;
|
|
589
|
+
}
|
|
590
|
+
authHeaders() {
|
|
591
|
+
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
462
592
|
}
|
|
463
593
|
startSpan(args) {
|
|
464
|
-
var _a;
|
|
594
|
+
var _a, _b;
|
|
465
595
|
const ids = createSpanIds(args.parent);
|
|
466
|
-
const started = nowUnixNanoString();
|
|
596
|
+
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
467
597
|
const attrs = [
|
|
468
|
-
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
|
|
598
|
+
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
599
|
+
attrString("ai.operationId", args.operationId)
|
|
469
600
|
];
|
|
470
|
-
if ((
|
|
601
|
+
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
471
602
|
return { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
|
|
472
603
|
}
|
|
473
604
|
endSpan(span, extra) {
|
|
474
|
-
var _a;
|
|
605
|
+
var _a, _b;
|
|
475
606
|
if (span.endTimeUnixNano) return;
|
|
476
|
-
span.endTimeUnixNano = nowUnixNanoString();
|
|
477
|
-
if ((
|
|
478
|
-
|
|
479
|
-
|
|
607
|
+
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
608
|
+
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
609
|
+
span.attributes.push(...extra.attributes);
|
|
610
|
+
}
|
|
611
|
+
let status = extra == null ? void 0 : extra.status;
|
|
612
|
+
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
480
613
|
const message = extra.error instanceof Error ? extra.error.message : String(extra.error);
|
|
481
614
|
status = { code: SpanStatusCode.ERROR, message };
|
|
482
615
|
}
|
|
@@ -490,10 +623,6 @@ var TraceShipper = class {
|
|
|
490
623
|
});
|
|
491
624
|
this.enqueue(otlp);
|
|
492
625
|
}
|
|
493
|
-
/**
|
|
494
|
-
* Create and enqueue a span with both start and end times (atomic insert).
|
|
495
|
-
* Used for tool spans and any span whose full duration is known at write time.
|
|
496
|
-
*/
|
|
497
626
|
createSpan(args) {
|
|
498
627
|
var _a;
|
|
499
628
|
const ids = createSpanIds(args.parent);
|
|
@@ -512,7 +641,18 @@ var TraceShipper = class {
|
|
|
512
641
|
this.enqueue(otlp);
|
|
513
642
|
}
|
|
514
643
|
enqueue(span) {
|
|
515
|
-
if (this.
|
|
644
|
+
if (!this.enabled) return;
|
|
645
|
+
if (this.debugSpans) {
|
|
646
|
+
const short = (s) => s ? s.slice(-8) : "none";
|
|
647
|
+
console.log(
|
|
648
|
+
`${this.prefix}[span] name=${span.name} trace=${short(span.traceId)} span=${short(span.spanId)} parent=${short(
|
|
649
|
+
span.parentSpanId
|
|
650
|
+
)}`
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
654
|
+
this.queue.shift();
|
|
655
|
+
}
|
|
516
656
|
this.queue.push(span);
|
|
517
657
|
if (this.queue.length >= this.maxBatchSize) {
|
|
518
658
|
void this.flush().catch(() => {
|
|
@@ -528,42 +668,34 @@ var TraceShipper = class {
|
|
|
528
668
|
}
|
|
529
669
|
}
|
|
530
670
|
async flush() {
|
|
671
|
+
if (!this.enabled) return;
|
|
531
672
|
if (this.timer) {
|
|
532
673
|
clearTimeout(this.timer);
|
|
533
674
|
this.timer = void 0;
|
|
534
675
|
}
|
|
535
676
|
while (this.queue.length > 0) {
|
|
536
677
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
537
|
-
const body = buildExportTraceServiceRequest(batch);
|
|
678
|
+
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
538
679
|
const url = `${this.baseUrl}traces`;
|
|
539
|
-
const spanNames = batch.map((span) => span.name);
|
|
540
680
|
if (this.debug) {
|
|
541
|
-
console.log(
|
|
681
|
+
console.log(`${this.prefix} sending traces batch`, {
|
|
542
682
|
spans: batch.length,
|
|
543
|
-
endpoint: url
|
|
544
|
-
spanNames
|
|
683
|
+
endpoint: url
|
|
545
684
|
});
|
|
546
685
|
}
|
|
547
|
-
const p = postJson(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
);
|
|
686
|
+
const p = postJson(url, body, this.authHeaders(), {
|
|
687
|
+
maxAttempts: 3,
|
|
688
|
+
debug: this.debug,
|
|
689
|
+
sdkName: this.sdkName
|
|
690
|
+
});
|
|
553
691
|
this.inFlight.add(p);
|
|
554
692
|
try {
|
|
555
693
|
try {
|
|
556
694
|
await p;
|
|
557
|
-
if (this.debug) {
|
|
558
|
-
console.log(`[raindrop-ai/opencode-plugin] sent ${batch.length} spans`, {
|
|
559
|
-
spanNames
|
|
560
|
-
});
|
|
561
|
-
}
|
|
695
|
+
if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
|
|
562
696
|
} catch (err) {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
console.warn(`[raindrop-ai/opencode-plugin] failed to send spans (dropping): ${msg}`);
|
|
566
|
-
}
|
|
697
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
698
|
+
console.warn(`${this.prefix} failed to send ${batch.length} spans: ${msg}`);
|
|
567
699
|
}
|
|
568
700
|
} finally {
|
|
569
701
|
this.inFlight.delete(p);
|
|
@@ -581,6 +713,41 @@ var TraceShipper = class {
|
|
|
581
713
|
}
|
|
582
714
|
};
|
|
583
715
|
|
|
716
|
+
// src/shipper.ts
|
|
717
|
+
var EventShipper2 = class extends EventShipper {
|
|
718
|
+
constructor(opts) {
|
|
719
|
+
var _a, _b, _c, _d;
|
|
720
|
+
super({
|
|
721
|
+
...opts,
|
|
722
|
+
sdkName: (_a = opts.sdkName) != null ? _a : "opencode-plugin",
|
|
723
|
+
libraryName: (_b = opts.libraryName) != null ? _b : PLUGIN_NAME,
|
|
724
|
+
libraryVersion: (_c = opts.libraryVersion) != null ? _c : PLUGIN_VERSION,
|
|
725
|
+
defaultEventName: (_d = opts.defaultEventName) != null ? _d : "opencode_session"
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
730
|
+
constructor(opts) {
|
|
731
|
+
var _a, _b, _c;
|
|
732
|
+
super({
|
|
733
|
+
...opts,
|
|
734
|
+
sdkName: (_a = opts.sdkName) != null ? _a : "opencode-plugin",
|
|
735
|
+
serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.opencode-plugin",
|
|
736
|
+
serviceVersion: (_c = opts.serviceVersion) != null ? _c : PLUGIN_VERSION
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
enqueue(span) {
|
|
740
|
+
var _a;
|
|
741
|
+
const attrs = (_a = span.attributes) != null ? _a : [];
|
|
742
|
+
attrs.unshift(
|
|
743
|
+
{ key: "span.id", value: { stringValue: span.spanId } },
|
|
744
|
+
...span.parentSpanId ? [{ key: "span.parent.id", value: { stringValue: span.parentSpanId } }] : []
|
|
745
|
+
);
|
|
746
|
+
span.attributes = attrs;
|
|
747
|
+
super.enqueue(span);
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
|
|
584
751
|
// src/tracing-linkage-helpers.ts
|
|
585
752
|
function createSessionParentMapHelpers({
|
|
586
753
|
sessions: sessions2,
|
|
@@ -666,8 +833,6 @@ var pendingChildSessionsByCallKey = /* @__PURE__ */ new Map();
|
|
|
666
833
|
function createSessionState(sessionId) {
|
|
667
834
|
return {
|
|
668
835
|
sessionId,
|
|
669
|
-
turnNumber: 0,
|
|
670
|
-
toolCount: 0,
|
|
671
836
|
currentInput: "",
|
|
672
837
|
outputParts: /* @__PURE__ */ new Map(),
|
|
673
838
|
reasoningParts: /* @__PURE__ */ new Map(),
|
|
@@ -721,7 +886,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
721
886
|
// event — session lifecycle + streaming parts
|
|
722
887
|
// ------------------------------------------------------------------
|
|
723
888
|
event: async ({ event }) => {
|
|
724
|
-
var _a, _b, _c, _d, _e;
|
|
889
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
725
890
|
try {
|
|
726
891
|
const props = event.properties;
|
|
727
892
|
const info = props["info"];
|
|
@@ -939,12 +1104,11 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
939
1104
|
}
|
|
940
1105
|
if (!state.parentId) {
|
|
941
1106
|
await eventShipper.finish(state.currentEventId, {
|
|
942
|
-
userId: state.sessionId,
|
|
1107
|
+
userId: (_d = (_c = state.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state.sessionId,
|
|
943
1108
|
model: modelName,
|
|
944
1109
|
output: outputText,
|
|
945
1110
|
properties: {
|
|
946
|
-
|
|
947
|
-
tool_count: state.toolCount
|
|
1111
|
+
plugin_version: PLUGIN_VERSION
|
|
948
1112
|
}
|
|
949
1113
|
});
|
|
950
1114
|
}
|
|
@@ -982,7 +1146,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
982
1146
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
983
1147
|
sessions.delete(String(sessionID));
|
|
984
1148
|
} else if (event.type === "session.error") {
|
|
985
|
-
const errorSessionID = (
|
|
1149
|
+
const errorSessionID = (_e = props["sessionID"]) != null ? _e : sessionID;
|
|
986
1150
|
if (errorSessionID === void 0 || errorSessionID === "")
|
|
987
1151
|
throw new Error("session.error: missing sessionID");
|
|
988
1152
|
const state = sessions.get(String(errorSessionID));
|
|
@@ -990,7 +1154,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
990
1154
|
const errorObj = props["error"];
|
|
991
1155
|
if (errorObj == null) throw new Error("session.error: missing error object");
|
|
992
1156
|
const errorName = errorObj.name;
|
|
993
|
-
const errorMessage = (
|
|
1157
|
+
const errorMessage = (_g = (_f = errorObj.data) == null ? void 0 : _f.message) != null ? _g : errorObj.name;
|
|
994
1158
|
if (errorName == null && errorMessage == null)
|
|
995
1159
|
throw new Error("session.error: error object must have name or data.message");
|
|
996
1160
|
const errorStr = `${errorMessage != null ? errorMessage : errorName}
|
|
@@ -1017,6 +1181,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1017
1181
|
// chat.message — user sent a message; start a new turn with a fresh event ID
|
|
1018
1182
|
// ------------------------------------------------------------------
|
|
1019
1183
|
"chat.message": async (messageInput, output) => {
|
|
1184
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1020
1185
|
try {
|
|
1021
1186
|
const { sessionID } = messageInput;
|
|
1022
1187
|
let state = sessions.get(sessionID);
|
|
@@ -1029,15 +1194,24 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1029
1194
|
traceShipper.endSpan(state.currentRootSpan);
|
|
1030
1195
|
state.currentRootSpan = void 0;
|
|
1031
1196
|
}
|
|
1032
|
-
state.turnNumber++;
|
|
1033
1197
|
if (output == null) throw new Error("chat.message: output is required");
|
|
1034
1198
|
const parts = output.parts;
|
|
1035
1199
|
if (parts == null) throw new Error("chat.message: output.parts is required");
|
|
1036
1200
|
const textParts = [];
|
|
1037
1201
|
const newAttachments = [];
|
|
1202
|
+
const baseMeta = { ...config.eventMetadata };
|
|
1203
|
+
const promptMeta = {};
|
|
1038
1204
|
for (const part of parts) {
|
|
1039
1205
|
if (part["type"] === "text" && typeof part["text"] === "string") {
|
|
1040
1206
|
textParts.push(part["text"]);
|
|
1207
|
+
const meta = part["metadata"];
|
|
1208
|
+
if (meta != null && typeof meta === "object") {
|
|
1209
|
+
const m = meta;
|
|
1210
|
+
if (typeof m["userId"] === "string") promptMeta.userId = m["userId"];
|
|
1211
|
+
if (typeof m["eventName"] === "string") promptMeta.eventName = m["eventName"];
|
|
1212
|
+
if (m["properties"] != null && typeof m["properties"] === "object")
|
|
1213
|
+
promptMeta.properties = m["properties"];
|
|
1214
|
+
}
|
|
1041
1215
|
} else if (part["type"] === "file") {
|
|
1042
1216
|
const mimeType = part["mediaType"];
|
|
1043
1217
|
const filename = part["filename"];
|
|
@@ -1049,6 +1223,11 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1049
1223
|
}
|
|
1050
1224
|
}
|
|
1051
1225
|
}
|
|
1226
|
+
state.eventMetadata = {
|
|
1227
|
+
...baseMeta,
|
|
1228
|
+
...promptMeta,
|
|
1229
|
+
properties: baseMeta.properties || promptMeta.properties ? { ...(_a = baseMeta.properties) != null ? _a : {}, ...(_b = promptMeta.properties) != null ? _b : {} } : void 0
|
|
1230
|
+
};
|
|
1052
1231
|
const userText = textParts.join("\n");
|
|
1053
1232
|
state.currentInput = userText;
|
|
1054
1233
|
if (state.parentId) {
|
|
@@ -1084,9 +1263,9 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1084
1263
|
});
|
|
1085
1264
|
await eventShipper.patch(state.currentEventId, {
|
|
1086
1265
|
isPending: true,
|
|
1087
|
-
userId: state.sessionId,
|
|
1266
|
+
userId: (_d = (_c = state.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state.sessionId,
|
|
1088
1267
|
convoId: state.sessionId,
|
|
1089
|
-
eventName: config.eventName,
|
|
1268
|
+
eventName: (_f = (_e = state.eventMetadata) == null ? void 0 : _e.eventName) != null ? _f : config.eventName,
|
|
1090
1269
|
input: userText,
|
|
1091
1270
|
...newAttachments.length > 0 ? { attachments: newAttachments } : {},
|
|
1092
1271
|
properties: {
|
|
@@ -1094,8 +1273,8 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1094
1273
|
directory,
|
|
1095
1274
|
hostname,
|
|
1096
1275
|
os,
|
|
1097
|
-
|
|
1098
|
-
|
|
1276
|
+
plugin_version: PLUGIN_VERSION,
|
|
1277
|
+
...(_g = state.eventMetadata) == null ? void 0 : _g.properties
|
|
1099
1278
|
}
|
|
1100
1279
|
});
|
|
1101
1280
|
} catch (err) {
|
|
@@ -1106,7 +1285,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1106
1285
|
// For child sessions, tool spans are parented directly to the parent task span.
|
|
1107
1286
|
// ------------------------------------------------------------------
|
|
1108
1287
|
"tool.execute.before": async (toolInput, _output) => {
|
|
1109
|
-
var _a;
|
|
1288
|
+
var _a, _b, _c;
|
|
1110
1289
|
try {
|
|
1111
1290
|
const { tool, sessionID, callID } = toolInput;
|
|
1112
1291
|
const state = sessions.get(sessionID);
|
|
@@ -1130,7 +1309,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1130
1309
|
ids: liveTaskSpan.ids,
|
|
1131
1310
|
eventContext: {
|
|
1132
1311
|
eventId: state.currentEventId,
|
|
1133
|
-
userId: state.sessionId,
|
|
1312
|
+
userId: (_c = (_b = state.eventMetadata) == null ? void 0 : _b.userId) != null ? _c : state.sessionId,
|
|
1134
1313
|
convoId: state.sessionId
|
|
1135
1314
|
}
|
|
1136
1315
|
};
|
|
@@ -1171,7 +1350,6 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1171
1350
|
const { tool, sessionID, callID, args } = toolInput;
|
|
1172
1351
|
const state = sessions.get(sessionID);
|
|
1173
1352
|
if (!state || !state.currentEventId) return;
|
|
1174
|
-
state.toolCount++;
|
|
1175
1353
|
if (args === void 0 || args === null)
|
|
1176
1354
|
throw new Error("tool.execute.after: args is required");
|
|
1177
1355
|
const toolCallArgs = typeof args === "string" ? args : JSON.stringify(args);
|
|
@@ -1225,12 +1403,6 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1225
1403
|
if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
|
|
1226
1404
|
}
|
|
1227
1405
|
}
|
|
1228
|
-
if (!state.parentId) {
|
|
1229
|
-
await eventShipper.patch(state.currentEventId, {
|
|
1230
|
-
userId: state.sessionId,
|
|
1231
|
-
properties: { tool_count: state.toolCount }
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
1406
|
} catch (err) {
|
|
1235
1407
|
console.log(
|
|
1236
1408
|
`[raindrop-ai/opencode-plugin] [error] Error in tool.execute.after hook: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -1247,6 +1419,7 @@ async function plugin(input) {
|
|
|
1247
1419
|
function appLog(level, message) {
|
|
1248
1420
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
1249
1421
|
}
|
|
1422
|
+
appLog("info", `Loading ${PLUGIN_NAME} v${PLUGIN_VERSION}`);
|
|
1250
1423
|
if (!config.writeKey) {
|
|
1251
1424
|
appLog(
|
|
1252
1425
|
"warn",
|
|
@@ -1257,12 +1430,12 @@ async function plugin(input) {
|
|
|
1257
1430
|
if (config.debug) {
|
|
1258
1431
|
appLog("info", `Raindrop tracing enabled (endpoint: ${config.endpoint})`);
|
|
1259
1432
|
}
|
|
1260
|
-
const eventShipper = new
|
|
1433
|
+
const eventShipper = new EventShipper2({
|
|
1261
1434
|
writeKey: config.writeKey,
|
|
1262
1435
|
endpoint: config.endpoint,
|
|
1263
1436
|
debug: config.debug
|
|
1264
1437
|
});
|
|
1265
|
-
const traceShipper = new
|
|
1438
|
+
const traceShipper = new TraceShipper2({
|
|
1266
1439
|
writeKey: config.writeKey,
|
|
1267
1440
|
endpoint: config.endpoint,
|
|
1268
1441
|
debug: config.debug
|