@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.js
CHANGED
|
@@ -26,18 +26,27 @@ function loadConfig(projectDirectory) {
|
|
|
26
26
|
} catch (e) {
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
let eventMetadata;
|
|
30
|
+
const envMeta = process.env["RAINDROP_EVENT_METADATA"];
|
|
31
|
+
if (envMeta) {
|
|
32
|
+
try {
|
|
33
|
+
eventMetadata = JSON.parse(envMeta);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
29
37
|
return {
|
|
30
38
|
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
31
39
|
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
32
40
|
eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
|
|
33
|
-
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false
|
|
41
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
42
|
+
eventMetadata
|
|
34
43
|
};
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
// package.json
|
|
38
47
|
var package_default = {
|
|
39
48
|
name: "@raindrop-ai/opencode-plugin",
|
|
40
|
-
version: "0.0.
|
|
49
|
+
version: "0.0.6",
|
|
41
50
|
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
42
51
|
type: "module",
|
|
43
52
|
main: "dist/index.cjs",
|
|
@@ -58,7 +67,7 @@ var package_default = {
|
|
|
58
67
|
build: "tsup",
|
|
59
68
|
dev: "tsup --watch",
|
|
60
69
|
clean: "rm -rf dist",
|
|
61
|
-
test: "cd tests &&
|
|
70
|
+
test: "cd tests && pnpm test"
|
|
62
71
|
},
|
|
63
72
|
peerDependencies: {
|
|
64
73
|
"@opencode-ai/plugin": ">=1.2.0",
|
|
@@ -70,6 +79,7 @@ var package_default = {
|
|
|
70
79
|
}
|
|
71
80
|
},
|
|
72
81
|
devDependencies: {
|
|
82
|
+
"@raindrop-ai/core": "workspace:*",
|
|
73
83
|
"@opencode-ai/plugin": "^1.2.0",
|
|
74
84
|
"@opencode-ai/sdk": "^1.2.0",
|
|
75
85
|
"@types/node": "^20.11.17",
|
|
@@ -87,33 +97,44 @@ var package_default = {
|
|
|
87
97
|
dts: {
|
|
88
98
|
resolve: true
|
|
89
99
|
},
|
|
90
|
-
clean: true
|
|
100
|
+
clean: true,
|
|
101
|
+
noExternal: [
|
|
102
|
+
"@raindrop-ai/core"
|
|
103
|
+
]
|
|
91
104
|
},
|
|
92
105
|
publishConfig: {
|
|
93
106
|
access: "public"
|
|
94
107
|
}
|
|
95
108
|
};
|
|
96
109
|
|
|
97
|
-
// src/
|
|
110
|
+
// src/package-info.ts
|
|
111
|
+
var PLUGIN_NAME = package_default.name;
|
|
98
112
|
var PLUGIN_VERSION = package_default.version;
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
|
|
114
|
+
// ../core/dist/chunk-FTBZHS25.js
|
|
115
|
+
function getCrypto() {
|
|
116
|
+
const c = globalThis.crypto;
|
|
117
|
+
return c;
|
|
101
118
|
}
|
|
102
119
|
function randomBytes(length) {
|
|
103
|
-
const
|
|
120
|
+
const cryptoObj = getCrypto();
|
|
104
121
|
const out = new Uint8Array(length);
|
|
105
|
-
if (
|
|
106
|
-
|
|
122
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
123
|
+
cryptoObj.getRandomValues(out);
|
|
107
124
|
return out;
|
|
108
125
|
}
|
|
109
126
|
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
110
127
|
return out;
|
|
111
128
|
}
|
|
112
129
|
function base64Encode(bytes) {
|
|
113
|
-
const
|
|
114
|
-
if (
|
|
130
|
+
const maybeBuffer = globalThis.Buffer;
|
|
131
|
+
if (maybeBuffer) {
|
|
132
|
+
return maybeBuffer.from(bytes).toString("base64");
|
|
133
|
+
}
|
|
115
134
|
let binary = "";
|
|
116
|
-
for (let i2 = 0; i2 < bytes.length; i2++)
|
|
135
|
+
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
136
|
+
binary += String.fromCharCode(bytes[i2]);
|
|
137
|
+
}
|
|
117
138
|
const btoaFn = globalThis.btoa;
|
|
118
139
|
if (typeof btoaFn === "function") return btoaFn(binary);
|
|
119
140
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
@@ -134,69 +155,9 @@ function base64Encode(bytes) {
|
|
|
134
155
|
}
|
|
135
156
|
return out;
|
|
136
157
|
}
|
|
137
|
-
var SERVICE_NAME = "raindrop.opencode-plugin";
|
|
138
|
-
var SpanStatusCode = {
|
|
139
|
-
ERROR: 2
|
|
140
|
-
};
|
|
141
158
|
function generateId() {
|
|
142
159
|
return base64Encode(randomBytes(12)).replace(/[+/=]/g, "").slice(0, 16);
|
|
143
160
|
}
|
|
144
|
-
function createSpanIds(parent) {
|
|
145
|
-
const traceId = parent ? parent.traceIdB64 : base64Encode(randomBytes(16));
|
|
146
|
-
const spanId = base64Encode(randomBytes(8));
|
|
147
|
-
return {
|
|
148
|
-
traceIdB64: traceId,
|
|
149
|
-
spanIdB64: spanId,
|
|
150
|
-
parentSpanIdB64: parent ? parent.spanIdB64 : void 0
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
function nowUnixNanoString() {
|
|
154
|
-
return Date.now().toString() + "000000";
|
|
155
|
-
}
|
|
156
|
-
function attrString(key, value) {
|
|
157
|
-
if (value === void 0) return void 0;
|
|
158
|
-
return { key, value: { stringValue: value } };
|
|
159
|
-
}
|
|
160
|
-
function attrInt(key, value) {
|
|
161
|
-
if (value === void 0) return void 0;
|
|
162
|
-
if (!Number.isFinite(value)) return void 0;
|
|
163
|
-
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
164
|
-
}
|
|
165
|
-
function buildOtlpSpan(args) {
|
|
166
|
-
const attrs = [
|
|
167
|
-
attrString("span.id", args.ids.spanIdB64),
|
|
168
|
-
attrString("span.parent.id", args.ids.parentSpanIdB64),
|
|
169
|
-
...args.attributes
|
|
170
|
-
].filter((x) => x !== void 0);
|
|
171
|
-
const span = {
|
|
172
|
-
traceId: args.ids.traceIdB64,
|
|
173
|
-
spanId: args.ids.spanIdB64,
|
|
174
|
-
name: args.name,
|
|
175
|
-
startTimeUnixNano: args.startTimeUnixNano,
|
|
176
|
-
endTimeUnixNano: args.endTimeUnixNano
|
|
177
|
-
};
|
|
178
|
-
if (args.ids.parentSpanIdB64) span.parentSpanId = args.ids.parentSpanIdB64;
|
|
179
|
-
if (attrs.length) span.attributes = attrs;
|
|
180
|
-
if (args.status) span.status = args.status;
|
|
181
|
-
return span;
|
|
182
|
-
}
|
|
183
|
-
function buildExportTraceServiceRequest(spans) {
|
|
184
|
-
return {
|
|
185
|
-
resourceSpans: [
|
|
186
|
-
{
|
|
187
|
-
resource: {
|
|
188
|
-
attributes: [{ key: "service.name", value: { stringValue: SERVICE_NAME } }]
|
|
189
|
-
},
|
|
190
|
-
scopeSpans: [
|
|
191
|
-
{
|
|
192
|
-
scope: { name: SERVICE_NAME, version: PLUGIN_VERSION },
|
|
193
|
-
spans
|
|
194
|
-
}
|
|
195
|
-
]
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
161
|
function wait(ms) {
|
|
201
162
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
202
163
|
}
|
|
@@ -209,7 +170,7 @@ function parseRetryAfter(headers) {
|
|
|
209
170
|
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
210
171
|
if (!value) return void 0;
|
|
211
172
|
const asNumber = Number(value);
|
|
212
|
-
if (!Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
173
|
+
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
213
174
|
const asDate = new Date(value).getTime();
|
|
214
175
|
if (!Number.isNaN(asDate)) {
|
|
215
176
|
const delta = asDate - Date.now();
|
|
@@ -218,26 +179,29 @@ function parseRetryAfter(headers) {
|
|
|
218
179
|
return void 0;
|
|
219
180
|
}
|
|
220
181
|
function getRetryDelayMs(attemptNumber, previousError) {
|
|
221
|
-
if (previousError
|
|
182
|
+
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
222
183
|
const v = previousError.retryAfterMs;
|
|
223
184
|
if (typeof v === "number") return Math.max(0, v);
|
|
224
185
|
}
|
|
225
186
|
if (attemptNumber <= 1) return 0;
|
|
226
|
-
|
|
187
|
+
const base = 500;
|
|
188
|
+
const factor = Math.pow(2, attemptNumber - 2);
|
|
189
|
+
return base * factor;
|
|
227
190
|
}
|
|
228
191
|
async function withRetry(operation, opName, opts) {
|
|
192
|
+
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
229
193
|
let lastError = void 0;
|
|
230
|
-
for (let
|
|
231
|
-
if (
|
|
232
|
-
const delay = getRetryDelayMs(
|
|
194
|
+
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
195
|
+
if (attemptNumber > 1) {
|
|
196
|
+
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
233
197
|
if (opts.debug) {
|
|
234
198
|
console.warn(
|
|
235
|
-
|
|
199
|
+
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
236
200
|
);
|
|
237
201
|
}
|
|
238
202
|
if (delay > 0) await wait(delay);
|
|
239
203
|
} else if (opts.debug) {
|
|
240
|
-
console.log(
|
|
204
|
+
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
241
205
|
}
|
|
242
206
|
try {
|
|
243
207
|
return await operation();
|
|
@@ -246,20 +210,26 @@ async function withRetry(operation, opName, opts) {
|
|
|
246
210
|
if (opts.debug) {
|
|
247
211
|
const msg = err instanceof Error ? err.message : String(err);
|
|
248
212
|
console.warn(
|
|
249
|
-
|
|
213
|
+
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
250
214
|
);
|
|
251
215
|
}
|
|
252
|
-
if (
|
|
216
|
+
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
217
|
+
break;
|
|
218
|
+
if (attemptNumber === opts.maxAttempts) break;
|
|
253
219
|
}
|
|
254
220
|
}
|
|
255
221
|
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
256
222
|
}
|
|
257
223
|
async function postJson(url, body, headers, opts) {
|
|
224
|
+
const opName = `POST ${url}`;
|
|
258
225
|
await withRetry(
|
|
259
226
|
async () => {
|
|
260
227
|
const resp = await fetch(url, {
|
|
261
228
|
method: "POST",
|
|
262
|
-
headers: {
|
|
229
|
+
headers: {
|
|
230
|
+
"Content-Type": "application/json",
|
|
231
|
+
...headers
|
|
232
|
+
},
|
|
263
233
|
body: JSON.stringify(body)
|
|
264
234
|
});
|
|
265
235
|
if (!resp.ok) {
|
|
@@ -269,13 +239,71 @@ async function postJson(url, body, headers, opts) {
|
|
|
269
239
|
);
|
|
270
240
|
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
271
241
|
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
242
|
+
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
272
243
|
throw err;
|
|
273
244
|
}
|
|
274
245
|
},
|
|
275
|
-
|
|
246
|
+
opName,
|
|
276
247
|
opts
|
|
277
248
|
);
|
|
278
249
|
}
|
|
250
|
+
var SpanStatusCode = {
|
|
251
|
+
UNSET: 0,
|
|
252
|
+
OK: 1,
|
|
253
|
+
ERROR: 2
|
|
254
|
+
};
|
|
255
|
+
function createSpanIds(parent) {
|
|
256
|
+
const traceId = parent ? parent.traceIdB64 : base64Encode(randomBytes(16));
|
|
257
|
+
const spanId = base64Encode(randomBytes(8));
|
|
258
|
+
return {
|
|
259
|
+
traceIdB64: traceId,
|
|
260
|
+
spanIdB64: spanId,
|
|
261
|
+
parentSpanIdB64: parent ? parent.spanIdB64 : void 0
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function nowUnixNanoString() {
|
|
265
|
+
return Date.now().toString() + "000000";
|
|
266
|
+
}
|
|
267
|
+
function attrString(key, value) {
|
|
268
|
+
if (value === void 0) return void 0;
|
|
269
|
+
return { key, value: { stringValue: value } };
|
|
270
|
+
}
|
|
271
|
+
function attrInt(key, value) {
|
|
272
|
+
if (value === void 0) return void 0;
|
|
273
|
+
if (!Number.isFinite(value)) return void 0;
|
|
274
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
275
|
+
}
|
|
276
|
+
function buildOtlpSpan(args) {
|
|
277
|
+
const attrs = args.attributes.filter((x) => x !== void 0);
|
|
278
|
+
const span = {
|
|
279
|
+
traceId: args.ids.traceIdB64,
|
|
280
|
+
spanId: args.ids.spanIdB64,
|
|
281
|
+
name: args.name,
|
|
282
|
+
startTimeUnixNano: args.startTimeUnixNano,
|
|
283
|
+
endTimeUnixNano: args.endTimeUnixNano
|
|
284
|
+
};
|
|
285
|
+
if (args.ids.parentSpanIdB64) span.parentSpanId = args.ids.parentSpanIdB64;
|
|
286
|
+
if (attrs.length) span.attributes = attrs;
|
|
287
|
+
if (args.status) span.status = args.status;
|
|
288
|
+
return span;
|
|
289
|
+
}
|
|
290
|
+
function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", serviceVersion = "0.0.0") {
|
|
291
|
+
return {
|
|
292
|
+
resourceSpans: [
|
|
293
|
+
{
|
|
294
|
+
resource: {
|
|
295
|
+
attributes: [{ key: "service.name", value: { stringValue: serviceName } }]
|
|
296
|
+
},
|
|
297
|
+
scopeSpans: [
|
|
298
|
+
{
|
|
299
|
+
scope: { name: serviceName, version: serviceVersion },
|
|
300
|
+
spans
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
}
|
|
279
307
|
function mergePatches(target, source) {
|
|
280
308
|
var _a, _b, _c, _d;
|
|
281
309
|
const out = { ...target, ...source };
|
|
@@ -293,34 +321,58 @@ var EventShipper = class {
|
|
|
293
321
|
this.sticky = /* @__PURE__ */ new Map();
|
|
294
322
|
this.timers = /* @__PURE__ */ new Map();
|
|
295
323
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
296
|
-
var _a, _b;
|
|
297
|
-
this.writeKey = opts.writeKey;
|
|
298
|
-
this.baseUrl = (
|
|
324
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
325
|
+
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
326
|
+
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
327
|
+
this.enabled = opts.enabled !== false;
|
|
299
328
|
this.debug = opts.debug;
|
|
300
|
-
this.partialFlushMs = (
|
|
329
|
+
this.partialFlushMs = (_c = opts.partialFlushMs) != null ? _c : 1e3;
|
|
330
|
+
this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
|
|
331
|
+
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
332
|
+
this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
|
|
333
|
+
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
334
|
+
this.context = {
|
|
335
|
+
library: {
|
|
336
|
+
name: (_f = opts.libraryName) != null ? _f : "@raindrop-ai/core",
|
|
337
|
+
version: (_g = opts.libraryVersion) != null ? _g : "0.0.0"
|
|
338
|
+
},
|
|
339
|
+
metadata: {
|
|
340
|
+
jsRuntime: isNode ? "node" : "web",
|
|
341
|
+
...isNode ? { nodeVersion: process.version } : {}
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
isDebugEnabled() {
|
|
346
|
+
return this.debug;
|
|
347
|
+
}
|
|
348
|
+
authHeaders() {
|
|
349
|
+
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
301
350
|
}
|
|
302
351
|
async patch(eventId, patch) {
|
|
303
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
304
|
-
if (!
|
|
352
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
353
|
+
if (!this.enabled) return;
|
|
354
|
+
if (!eventId || !eventId.trim()) return;
|
|
305
355
|
if (this.debug) {
|
|
306
|
-
console.log(
|
|
356
|
+
console.log(`${this.prefix} queue patch`, {
|
|
307
357
|
eventId,
|
|
308
358
|
userId: patch.userId,
|
|
359
|
+
eventName: patch.eventName,
|
|
309
360
|
hasInput: typeof patch.input === "string" && patch.input.length > 0,
|
|
310
361
|
hasOutput: typeof patch.output === "string" && patch.output.length > 0,
|
|
362
|
+
attachments: (_b = (_a = patch.attachments) == null ? void 0 : _a.length) != null ? _b : 0,
|
|
311
363
|
isPending: patch.isPending
|
|
312
364
|
});
|
|
313
365
|
}
|
|
314
|
-
const sticky = (
|
|
315
|
-
const existing = (
|
|
366
|
+
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
367
|
+
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
316
368
|
const merged = mergePatches(existing, patch);
|
|
317
|
-
merged.isPending = (
|
|
369
|
+
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
318
370
|
this.buffers.set(eventId, merged);
|
|
319
371
|
this.sticky.set(eventId, {
|
|
320
|
-
userId: (
|
|
321
|
-
convoId: (
|
|
322
|
-
eventName: (
|
|
323
|
-
isPending: (
|
|
372
|
+
userId: (_h = merged.userId) != null ? _h : sticky.userId,
|
|
373
|
+
convoId: (_i = merged.convoId) != null ? _i : sticky.convoId,
|
|
374
|
+
eventName: (_j = merged.eventName) != null ? _j : sticky.eventName,
|
|
375
|
+
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending
|
|
324
376
|
});
|
|
325
377
|
const t = this.timers.get(eventId);
|
|
326
378
|
if (t) clearTimeout(t);
|
|
@@ -338,6 +390,7 @@ var EventShipper = class {
|
|
|
338
390
|
await this.patch(eventId, { ...patch, isPending: false });
|
|
339
391
|
}
|
|
340
392
|
async flush() {
|
|
393
|
+
if (!this.enabled) return;
|
|
341
394
|
const ids = [...this.buffers.keys()];
|
|
342
395
|
await Promise.all(ids.map((id) => this.flushOne(id)));
|
|
343
396
|
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
@@ -348,8 +401,70 @@ var EventShipper = class {
|
|
|
348
401
|
this.timers.clear();
|
|
349
402
|
await this.flush();
|
|
350
403
|
}
|
|
404
|
+
async trackSignal(signal) {
|
|
405
|
+
var _a, _b;
|
|
406
|
+
if (!this.enabled) return;
|
|
407
|
+
const body = [
|
|
408
|
+
{
|
|
409
|
+
event_id: signal.eventId,
|
|
410
|
+
signal_name: signal.name,
|
|
411
|
+
signal_type: (_a = signal.type) != null ? _a : "default",
|
|
412
|
+
timestamp: signal.timestamp,
|
|
413
|
+
sentiment: signal.sentiment,
|
|
414
|
+
attachment_id: signal.attachmentId,
|
|
415
|
+
properties: {
|
|
416
|
+
...(_b = signal.properties) != null ? _b : {},
|
|
417
|
+
...signal.comment ? { comment: signal.comment } : {},
|
|
418
|
+
...signal.after ? { after: signal.after } : {}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
];
|
|
422
|
+
const url = `${this.baseUrl}signals/track`;
|
|
423
|
+
try {
|
|
424
|
+
await postJson(url, body, this.authHeaders(), {
|
|
425
|
+
maxAttempts: 3,
|
|
426
|
+
debug: this.debug,
|
|
427
|
+
sdkName: this.sdkName
|
|
428
|
+
});
|
|
429
|
+
} catch (err) {
|
|
430
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
431
|
+
console.warn(`${this.prefix} failed to send signal (dropping): ${msg}`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async identify(users) {
|
|
435
|
+
if (!this.enabled) return;
|
|
436
|
+
const list = Array.isArray(users) ? users : [users];
|
|
437
|
+
const body = list.filter((user) => {
|
|
438
|
+
if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
|
|
439
|
+
if (this.debug) {
|
|
440
|
+
console.warn(`${this.prefix} skipping identify: missing userId`);
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
return true;
|
|
445
|
+
}).map((user) => {
|
|
446
|
+
var _a;
|
|
447
|
+
return {
|
|
448
|
+
user_id: user.userId,
|
|
449
|
+
traits: (_a = user.traits) != null ? _a : {}
|
|
450
|
+
};
|
|
451
|
+
});
|
|
452
|
+
if (body.length === 0) return;
|
|
453
|
+
const url = `${this.baseUrl}users/identify`;
|
|
454
|
+
try {
|
|
455
|
+
await postJson(url, body, this.authHeaders(), {
|
|
456
|
+
maxAttempts: 3,
|
|
457
|
+
debug: this.debug,
|
|
458
|
+
sdkName: this.sdkName
|
|
459
|
+
});
|
|
460
|
+
} catch (err) {
|
|
461
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
462
|
+
console.warn(`${this.prefix} failed to send identify (dropping): ${msg}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
351
465
|
async flushOne(eventId) {
|
|
352
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
466
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
467
|
+
if (!this.enabled) return;
|
|
353
468
|
const timer = this.timers.get(eventId);
|
|
354
469
|
if (timer) {
|
|
355
470
|
clearTimeout(timer);
|
|
@@ -359,105 +474,123 @@ var EventShipper = class {
|
|
|
359
474
|
this.buffers.delete(eventId);
|
|
360
475
|
if (!accumulated) return;
|
|
361
476
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
362
|
-
const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c :
|
|
477
|
+
const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c : this.defaultEventName;
|
|
363
478
|
const userId = (_d = accumulated.userId) != null ? _d : sticky.userId;
|
|
364
479
|
if (!userId) {
|
|
365
480
|
if (this.debug) {
|
|
366
|
-
console.warn(
|
|
367
|
-
`[raindrop-ai/opencode-plugin] skipping track_partial for ${eventId}: missing userId`
|
|
368
|
-
);
|
|
481
|
+
console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
|
|
369
482
|
}
|
|
483
|
+
this.sticky.delete(eventId);
|
|
370
484
|
return;
|
|
371
485
|
}
|
|
486
|
+
const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
|
|
372
487
|
const payload = {
|
|
373
488
|
event_id: eventId,
|
|
374
489
|
user_id: userId,
|
|
375
490
|
event: eventName,
|
|
376
|
-
timestamp: (
|
|
491
|
+
timestamp: (_f = accumulated.timestamp) != null ? _f : (/* @__PURE__ */ new Date()).toISOString(),
|
|
377
492
|
ai_data: {
|
|
378
493
|
input: accumulated.input,
|
|
379
494
|
output: accumulated.output,
|
|
380
495
|
model: accumulated.model,
|
|
381
|
-
convo_id: (
|
|
496
|
+
convo_id: (_g = accumulated.convoId) != null ? _g : sticky.convoId
|
|
382
497
|
},
|
|
383
498
|
properties: {
|
|
384
|
-
...
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
metadata: { jsRuntime: "node" }
|
|
388
|
-
}
|
|
499
|
+
...restProperties,
|
|
500
|
+
...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
|
|
501
|
+
$context: this.context
|
|
389
502
|
},
|
|
390
503
|
attachments: accumulated.attachments,
|
|
391
504
|
is_pending: ((_i = (_h = accumulated.isPending) != null ? _h : sticky.isPending) != null ? _i : true) !== false
|
|
392
505
|
};
|
|
393
506
|
const url = `${this.baseUrl}events/track_partial`;
|
|
394
507
|
if (this.debug) {
|
|
395
|
-
console.log(
|
|
508
|
+
console.log(`${this.prefix} sending track_partial`, {
|
|
396
509
|
eventId,
|
|
397
510
|
eventName,
|
|
398
511
|
userId,
|
|
399
|
-
isPending: payload
|
|
512
|
+
isPending: payload.is_pending,
|
|
400
513
|
inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
|
|
401
514
|
outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
|
|
515
|
+
attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
|
|
516
|
+
attachmentKinds: (_m = (_l = accumulated.attachments) == null ? void 0 : _l.map((a) => ({
|
|
517
|
+
type: a.type,
|
|
518
|
+
role: a.role,
|
|
519
|
+
name: a.name,
|
|
520
|
+
valuePreview: a.value.slice(0, 60)
|
|
521
|
+
}))) != null ? _m : [],
|
|
402
522
|
endpoint: url
|
|
403
523
|
});
|
|
404
524
|
}
|
|
405
|
-
const p = postJson(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
);
|
|
525
|
+
const p = postJson(url, payload, this.authHeaders(), {
|
|
526
|
+
maxAttempts: 3,
|
|
527
|
+
debug: this.debug,
|
|
528
|
+
sdkName: this.sdkName
|
|
529
|
+
});
|
|
411
530
|
this.inFlight.add(p);
|
|
412
531
|
try {
|
|
413
532
|
try {
|
|
414
533
|
await p;
|
|
415
534
|
if (this.debug) {
|
|
416
|
-
console.log(
|
|
535
|
+
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
417
536
|
}
|
|
418
537
|
} catch (err) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
console.warn(
|
|
422
|
-
`[raindrop-ai/opencode-plugin] failed to send track_partial (dropping): ${msg}`
|
|
423
|
-
);
|
|
424
|
-
}
|
|
538
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
539
|
+
console.warn(`${this.prefix} failed to send track_partial (dropping): ${msg}`);
|
|
425
540
|
}
|
|
426
541
|
} finally {
|
|
427
542
|
this.inFlight.delete(p);
|
|
428
543
|
}
|
|
429
|
-
|
|
544
|
+
const isPending = payload.is_pending;
|
|
545
|
+
if (!isPending) {
|
|
546
|
+
this.sticky.delete(eventId);
|
|
547
|
+
}
|
|
430
548
|
}
|
|
431
549
|
};
|
|
432
550
|
var TraceShipper = class {
|
|
433
551
|
constructor(opts) {
|
|
434
552
|
this.queue = [];
|
|
435
553
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
436
|
-
var _a, _b;
|
|
437
|
-
this.writeKey = opts.writeKey;
|
|
438
|
-
this.baseUrl = (
|
|
554
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
555
|
+
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
556
|
+
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
557
|
+
this.enabled = opts.enabled !== false;
|
|
439
558
|
this.debug = opts.debug;
|
|
440
|
-
this.
|
|
441
|
-
this.
|
|
442
|
-
this.
|
|
559
|
+
this.debugSpans = opts.debugSpans === true;
|
|
560
|
+
this.flushIntervalMs = (_c = opts.flushIntervalMs) != null ? _c : 1e3;
|
|
561
|
+
this.maxBatchSize = (_d = opts.maxBatchSize) != null ? _d : 50;
|
|
562
|
+
this.maxQueueSize = (_e = opts.maxQueueSize) != null ? _e : 5e3;
|
|
563
|
+
this.sdkName = (_f = opts.sdkName) != null ? _f : "core";
|
|
564
|
+
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
565
|
+
this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
|
|
566
|
+
this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
|
|
567
|
+
}
|
|
568
|
+
isDebugEnabled() {
|
|
569
|
+
return this.debug;
|
|
570
|
+
}
|
|
571
|
+
authHeaders() {
|
|
572
|
+
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
443
573
|
}
|
|
444
574
|
startSpan(args) {
|
|
445
|
-
var _a;
|
|
575
|
+
var _a, _b;
|
|
446
576
|
const ids = createSpanIds(args.parent);
|
|
447
|
-
const started = nowUnixNanoString();
|
|
577
|
+
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
448
578
|
const attrs = [
|
|
449
|
-
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
|
|
579
|
+
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
580
|
+
attrString("ai.operationId", args.operationId)
|
|
450
581
|
];
|
|
451
|
-
if ((
|
|
582
|
+
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
452
583
|
return { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
|
|
453
584
|
}
|
|
454
585
|
endSpan(span, extra) {
|
|
455
|
-
var _a;
|
|
586
|
+
var _a, _b;
|
|
456
587
|
if (span.endTimeUnixNano) return;
|
|
457
|
-
span.endTimeUnixNano = nowUnixNanoString();
|
|
458
|
-
if ((
|
|
459
|
-
|
|
460
|
-
|
|
588
|
+
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
589
|
+
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
590
|
+
span.attributes.push(...extra.attributes);
|
|
591
|
+
}
|
|
592
|
+
let status = extra == null ? void 0 : extra.status;
|
|
593
|
+
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
461
594
|
const message = extra.error instanceof Error ? extra.error.message : String(extra.error);
|
|
462
595
|
status = { code: SpanStatusCode.ERROR, message };
|
|
463
596
|
}
|
|
@@ -471,10 +604,6 @@ var TraceShipper = class {
|
|
|
471
604
|
});
|
|
472
605
|
this.enqueue(otlp);
|
|
473
606
|
}
|
|
474
|
-
/**
|
|
475
|
-
* Create and enqueue a span with both start and end times (atomic insert).
|
|
476
|
-
* Used for tool spans and any span whose full duration is known at write time.
|
|
477
|
-
*/
|
|
478
607
|
createSpan(args) {
|
|
479
608
|
var _a;
|
|
480
609
|
const ids = createSpanIds(args.parent);
|
|
@@ -493,7 +622,18 @@ var TraceShipper = class {
|
|
|
493
622
|
this.enqueue(otlp);
|
|
494
623
|
}
|
|
495
624
|
enqueue(span) {
|
|
496
|
-
if (this.
|
|
625
|
+
if (!this.enabled) return;
|
|
626
|
+
if (this.debugSpans) {
|
|
627
|
+
const short = (s) => s ? s.slice(-8) : "none";
|
|
628
|
+
console.log(
|
|
629
|
+
`${this.prefix}[span] name=${span.name} trace=${short(span.traceId)} span=${short(span.spanId)} parent=${short(
|
|
630
|
+
span.parentSpanId
|
|
631
|
+
)}`
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
635
|
+
this.queue.shift();
|
|
636
|
+
}
|
|
497
637
|
this.queue.push(span);
|
|
498
638
|
if (this.queue.length >= this.maxBatchSize) {
|
|
499
639
|
void this.flush().catch(() => {
|
|
@@ -509,42 +649,34 @@ var TraceShipper = class {
|
|
|
509
649
|
}
|
|
510
650
|
}
|
|
511
651
|
async flush() {
|
|
652
|
+
if (!this.enabled) return;
|
|
512
653
|
if (this.timer) {
|
|
513
654
|
clearTimeout(this.timer);
|
|
514
655
|
this.timer = void 0;
|
|
515
656
|
}
|
|
516
657
|
while (this.queue.length > 0) {
|
|
517
658
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
518
|
-
const body = buildExportTraceServiceRequest(batch);
|
|
659
|
+
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
519
660
|
const url = `${this.baseUrl}traces`;
|
|
520
|
-
const spanNames = batch.map((span) => span.name);
|
|
521
661
|
if (this.debug) {
|
|
522
|
-
console.log(
|
|
662
|
+
console.log(`${this.prefix} sending traces batch`, {
|
|
523
663
|
spans: batch.length,
|
|
524
|
-
endpoint: url
|
|
525
|
-
spanNames
|
|
664
|
+
endpoint: url
|
|
526
665
|
});
|
|
527
666
|
}
|
|
528
|
-
const p = postJson(
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
);
|
|
667
|
+
const p = postJson(url, body, this.authHeaders(), {
|
|
668
|
+
maxAttempts: 3,
|
|
669
|
+
debug: this.debug,
|
|
670
|
+
sdkName: this.sdkName
|
|
671
|
+
});
|
|
534
672
|
this.inFlight.add(p);
|
|
535
673
|
try {
|
|
536
674
|
try {
|
|
537
675
|
await p;
|
|
538
|
-
if (this.debug) {
|
|
539
|
-
console.log(`[raindrop-ai/opencode-plugin] sent ${batch.length} spans`, {
|
|
540
|
-
spanNames
|
|
541
|
-
});
|
|
542
|
-
}
|
|
676
|
+
if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
|
|
543
677
|
} catch (err) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
console.warn(`[raindrop-ai/opencode-plugin] failed to send spans (dropping): ${msg}`);
|
|
547
|
-
}
|
|
678
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
679
|
+
console.warn(`${this.prefix} failed to send ${batch.length} spans: ${msg}`);
|
|
548
680
|
}
|
|
549
681
|
} finally {
|
|
550
682
|
this.inFlight.delete(p);
|
|
@@ -562,6 +694,41 @@ var TraceShipper = class {
|
|
|
562
694
|
}
|
|
563
695
|
};
|
|
564
696
|
|
|
697
|
+
// src/shipper.ts
|
|
698
|
+
var EventShipper2 = class extends EventShipper {
|
|
699
|
+
constructor(opts) {
|
|
700
|
+
var _a, _b, _c, _d;
|
|
701
|
+
super({
|
|
702
|
+
...opts,
|
|
703
|
+
sdkName: (_a = opts.sdkName) != null ? _a : "opencode-plugin",
|
|
704
|
+
libraryName: (_b = opts.libraryName) != null ? _b : PLUGIN_NAME,
|
|
705
|
+
libraryVersion: (_c = opts.libraryVersion) != null ? _c : PLUGIN_VERSION,
|
|
706
|
+
defaultEventName: (_d = opts.defaultEventName) != null ? _d : "opencode_session"
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
711
|
+
constructor(opts) {
|
|
712
|
+
var _a, _b, _c;
|
|
713
|
+
super({
|
|
714
|
+
...opts,
|
|
715
|
+
sdkName: (_a = opts.sdkName) != null ? _a : "opencode-plugin",
|
|
716
|
+
serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.opencode-plugin",
|
|
717
|
+
serviceVersion: (_c = opts.serviceVersion) != null ? _c : PLUGIN_VERSION
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
enqueue(span) {
|
|
721
|
+
var _a;
|
|
722
|
+
const attrs = (_a = span.attributes) != null ? _a : [];
|
|
723
|
+
attrs.unshift(
|
|
724
|
+
{ key: "span.id", value: { stringValue: span.spanId } },
|
|
725
|
+
...span.parentSpanId ? [{ key: "span.parent.id", value: { stringValue: span.parentSpanId } }] : []
|
|
726
|
+
);
|
|
727
|
+
span.attributes = attrs;
|
|
728
|
+
super.enqueue(span);
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
|
|
565
732
|
// src/tracing-linkage-helpers.ts
|
|
566
733
|
function createSessionParentMapHelpers({
|
|
567
734
|
sessions: sessions2,
|
|
@@ -647,8 +814,6 @@ var pendingChildSessionsByCallKey = /* @__PURE__ */ new Map();
|
|
|
647
814
|
function createSessionState(sessionId) {
|
|
648
815
|
return {
|
|
649
816
|
sessionId,
|
|
650
|
-
turnNumber: 0,
|
|
651
|
-
toolCount: 0,
|
|
652
817
|
currentInput: "",
|
|
653
818
|
outputParts: /* @__PURE__ */ new Map(),
|
|
654
819
|
reasoningParts: /* @__PURE__ */ new Map(),
|
|
@@ -702,7 +867,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
702
867
|
// event — session lifecycle + streaming parts
|
|
703
868
|
// ------------------------------------------------------------------
|
|
704
869
|
event: async ({ event }) => {
|
|
705
|
-
var _a, _b, _c, _d, _e;
|
|
870
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
706
871
|
try {
|
|
707
872
|
const props = event.properties;
|
|
708
873
|
const info = props["info"];
|
|
@@ -920,12 +1085,11 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
920
1085
|
}
|
|
921
1086
|
if (!state.parentId) {
|
|
922
1087
|
await eventShipper.finish(state.currentEventId, {
|
|
923
|
-
userId: state.sessionId,
|
|
1088
|
+
userId: (_d = (_c = state.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state.sessionId,
|
|
924
1089
|
model: modelName,
|
|
925
1090
|
output: outputText,
|
|
926
1091
|
properties: {
|
|
927
|
-
|
|
928
|
-
tool_count: state.toolCount
|
|
1092
|
+
plugin_version: PLUGIN_VERSION
|
|
929
1093
|
}
|
|
930
1094
|
});
|
|
931
1095
|
}
|
|
@@ -963,7 +1127,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
963
1127
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
964
1128
|
sessions.delete(String(sessionID));
|
|
965
1129
|
} else if (event.type === "session.error") {
|
|
966
|
-
const errorSessionID = (
|
|
1130
|
+
const errorSessionID = (_e = props["sessionID"]) != null ? _e : sessionID;
|
|
967
1131
|
if (errorSessionID === void 0 || errorSessionID === "")
|
|
968
1132
|
throw new Error("session.error: missing sessionID");
|
|
969
1133
|
const state = sessions.get(String(errorSessionID));
|
|
@@ -971,7 +1135,7 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
971
1135
|
const errorObj = props["error"];
|
|
972
1136
|
if (errorObj == null) throw new Error("session.error: missing error object");
|
|
973
1137
|
const errorName = errorObj.name;
|
|
974
|
-
const errorMessage = (
|
|
1138
|
+
const errorMessage = (_g = (_f = errorObj.data) == null ? void 0 : _f.message) != null ? _g : errorObj.name;
|
|
975
1139
|
if (errorName == null && errorMessage == null)
|
|
976
1140
|
throw new Error("session.error: error object must have name or data.message");
|
|
977
1141
|
const errorStr = `${errorMessage != null ? errorMessage : errorName}
|
|
@@ -998,6 +1162,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
998
1162
|
// chat.message — user sent a message; start a new turn with a fresh event ID
|
|
999
1163
|
// ------------------------------------------------------------------
|
|
1000
1164
|
"chat.message": async (messageInput, output) => {
|
|
1165
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1001
1166
|
try {
|
|
1002
1167
|
const { sessionID } = messageInput;
|
|
1003
1168
|
let state = sessions.get(sessionID);
|
|
@@ -1010,15 +1175,24 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1010
1175
|
traceShipper.endSpan(state.currentRootSpan);
|
|
1011
1176
|
state.currentRootSpan = void 0;
|
|
1012
1177
|
}
|
|
1013
|
-
state.turnNumber++;
|
|
1014
1178
|
if (output == null) throw new Error("chat.message: output is required");
|
|
1015
1179
|
const parts = output.parts;
|
|
1016
1180
|
if (parts == null) throw new Error("chat.message: output.parts is required");
|
|
1017
1181
|
const textParts = [];
|
|
1018
1182
|
const newAttachments = [];
|
|
1183
|
+
const baseMeta = { ...config.eventMetadata };
|
|
1184
|
+
const promptMeta = {};
|
|
1019
1185
|
for (const part of parts) {
|
|
1020
1186
|
if (part["type"] === "text" && typeof part["text"] === "string") {
|
|
1021
1187
|
textParts.push(part["text"]);
|
|
1188
|
+
const meta = part["metadata"];
|
|
1189
|
+
if (meta != null && typeof meta === "object") {
|
|
1190
|
+
const m = meta;
|
|
1191
|
+
if (typeof m["userId"] === "string") promptMeta.userId = m["userId"];
|
|
1192
|
+
if (typeof m["eventName"] === "string") promptMeta.eventName = m["eventName"];
|
|
1193
|
+
if (m["properties"] != null && typeof m["properties"] === "object")
|
|
1194
|
+
promptMeta.properties = m["properties"];
|
|
1195
|
+
}
|
|
1022
1196
|
} else if (part["type"] === "file") {
|
|
1023
1197
|
const mimeType = part["mediaType"];
|
|
1024
1198
|
const filename = part["filename"];
|
|
@@ -1030,6 +1204,11 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1030
1204
|
}
|
|
1031
1205
|
}
|
|
1032
1206
|
}
|
|
1207
|
+
state.eventMetadata = {
|
|
1208
|
+
...baseMeta,
|
|
1209
|
+
...promptMeta,
|
|
1210
|
+
properties: baseMeta.properties || promptMeta.properties ? { ...(_a = baseMeta.properties) != null ? _a : {}, ...(_b = promptMeta.properties) != null ? _b : {} } : void 0
|
|
1211
|
+
};
|
|
1033
1212
|
const userText = textParts.join("\n");
|
|
1034
1213
|
state.currentInput = userText;
|
|
1035
1214
|
if (state.parentId) {
|
|
@@ -1065,9 +1244,9 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1065
1244
|
});
|
|
1066
1245
|
await eventShipper.patch(state.currentEventId, {
|
|
1067
1246
|
isPending: true,
|
|
1068
|
-
userId: state.sessionId,
|
|
1247
|
+
userId: (_d = (_c = state.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state.sessionId,
|
|
1069
1248
|
convoId: state.sessionId,
|
|
1070
|
-
eventName: config.eventName,
|
|
1249
|
+
eventName: (_f = (_e = state.eventMetadata) == null ? void 0 : _e.eventName) != null ? _f : config.eventName,
|
|
1071
1250
|
input: userText,
|
|
1072
1251
|
...newAttachments.length > 0 ? { attachments: newAttachments } : {},
|
|
1073
1252
|
properties: {
|
|
@@ -1075,8 +1254,8 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1075
1254
|
directory,
|
|
1076
1255
|
hostname,
|
|
1077
1256
|
os,
|
|
1078
|
-
|
|
1079
|
-
|
|
1257
|
+
plugin_version: PLUGIN_VERSION,
|
|
1258
|
+
...(_g = state.eventMetadata) == null ? void 0 : _g.properties
|
|
1080
1259
|
}
|
|
1081
1260
|
});
|
|
1082
1261
|
} catch (err) {
|
|
@@ -1087,7 +1266,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1087
1266
|
// For child sessions, tool spans are parented directly to the parent task span.
|
|
1088
1267
|
// ------------------------------------------------------------------
|
|
1089
1268
|
"tool.execute.before": async (toolInput, _output) => {
|
|
1090
|
-
var _a;
|
|
1269
|
+
var _a, _b, _c;
|
|
1091
1270
|
try {
|
|
1092
1271
|
const { tool, sessionID, callID } = toolInput;
|
|
1093
1272
|
const state = sessions.get(sessionID);
|
|
@@ -1111,7 +1290,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1111
1290
|
ids: liveTaskSpan.ids,
|
|
1112
1291
|
eventContext: {
|
|
1113
1292
|
eventId: state.currentEventId,
|
|
1114
|
-
userId: state.sessionId,
|
|
1293
|
+
userId: (_c = (_b = state.eventMetadata) == null ? void 0 : _b.userId) != null ? _c : state.sessionId,
|
|
1115
1294
|
convoId: state.sessionId
|
|
1116
1295
|
}
|
|
1117
1296
|
};
|
|
@@ -1152,7 +1331,6 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1152
1331
|
const { tool, sessionID, callID, args } = toolInput;
|
|
1153
1332
|
const state = sessions.get(sessionID);
|
|
1154
1333
|
if (!state || !state.currentEventId) return;
|
|
1155
|
-
state.toolCount++;
|
|
1156
1334
|
if (args === void 0 || args === null)
|
|
1157
1335
|
throw new Error("tool.execute.after: args is required");
|
|
1158
1336
|
const toolCallArgs = typeof args === "string" ? args : JSON.stringify(args);
|
|
@@ -1206,12 +1384,6 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
1206
1384
|
if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
|
|
1207
1385
|
}
|
|
1208
1386
|
}
|
|
1209
|
-
if (!state.parentId) {
|
|
1210
|
-
await eventShipper.patch(state.currentEventId, {
|
|
1211
|
-
userId: state.sessionId,
|
|
1212
|
-
properties: { tool_count: state.toolCount }
|
|
1213
|
-
});
|
|
1214
|
-
}
|
|
1215
1387
|
} catch (err) {
|
|
1216
1388
|
console.log(
|
|
1217
1389
|
`[raindrop-ai/opencode-plugin] [error] Error in tool.execute.after hook: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -1228,6 +1400,7 @@ async function plugin(input) {
|
|
|
1228
1400
|
function appLog(level, message) {
|
|
1229
1401
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
1230
1402
|
}
|
|
1403
|
+
appLog("info", `Loading ${PLUGIN_NAME} v${PLUGIN_VERSION}`);
|
|
1231
1404
|
if (!config.writeKey) {
|
|
1232
1405
|
appLog(
|
|
1233
1406
|
"warn",
|
|
@@ -1238,12 +1411,12 @@ async function plugin(input) {
|
|
|
1238
1411
|
if (config.debug) {
|
|
1239
1412
|
appLog("info", `Raindrop tracing enabled (endpoint: ${config.endpoint})`);
|
|
1240
1413
|
}
|
|
1241
|
-
const eventShipper = new
|
|
1414
|
+
const eventShipper = new EventShipper2({
|
|
1242
1415
|
writeKey: config.writeKey,
|
|
1243
1416
|
endpoint: config.endpoint,
|
|
1244
1417
|
debug: config.debug
|
|
1245
1418
|
});
|
|
1246
|
-
const traceShipper = new
|
|
1419
|
+
const traceShipper = new TraceShipper2({
|
|
1247
1420
|
writeKey: config.writeKey,
|
|
1248
1421
|
endpoint: config.endpoint,
|
|
1249
1422
|
debug: config.debug
|