@raindrop-ai/opencode-plugin 0.0.11 → 0.0.12
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 +278 -152
- package/dist/index.js +278 -152
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -24,124 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
|
|
27
|
-
//
|
|
28
|
-
var import_node_fs = require("fs");
|
|
29
|
-
var import_node_os = require("os");
|
|
30
|
-
var import_node_path = require("path");
|
|
31
|
-
function loadConfig(projectDirectory) {
|
|
32
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
33
|
-
let merged = {};
|
|
34
|
-
const configPaths = [
|
|
35
|
-
(0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "opencode", "raindrop.json"),
|
|
36
|
-
(0, import_node_path.join)(projectDirectory, ".opencode", "raindrop.json")
|
|
37
|
-
];
|
|
38
|
-
for (const configPath of configPaths) {
|
|
39
|
-
try {
|
|
40
|
-
if ((0, import_node_fs.existsSync)(configPath)) {
|
|
41
|
-
const content = (0, import_node_fs.readFileSync)(configPath, "utf-8");
|
|
42
|
-
const parsed = JSON.parse(content);
|
|
43
|
-
merged = { ...merged, ...parsed };
|
|
44
|
-
}
|
|
45
|
-
} catch (e) {
|
|
46
|
-
}
|
|
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
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
58
|
-
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
59
|
-
eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
|
|
60
|
-
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
61
|
-
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
|
|
62
|
-
eventMetadata
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// package.json
|
|
67
|
-
var package_default = {
|
|
68
|
-
name: "@raindrop-ai/opencode-plugin",
|
|
69
|
-
version: "0.0.11",
|
|
70
|
-
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
71
|
-
type: "module",
|
|
72
|
-
main: "dist/index.js",
|
|
73
|
-
module: "dist/index.js",
|
|
74
|
-
types: "dist/index.d.ts",
|
|
75
|
-
license: "MIT",
|
|
76
|
-
repository: {
|
|
77
|
-
type: "git",
|
|
78
|
-
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
79
|
-
directory: "packages/opencode-plugin"
|
|
80
|
-
},
|
|
81
|
-
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/opencode-plugin#readme",
|
|
82
|
-
bugs: {
|
|
83
|
-
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
84
|
-
},
|
|
85
|
-
exports: {
|
|
86
|
-
".": {
|
|
87
|
-
types: "./dist/index.d.ts",
|
|
88
|
-
import: "./dist/index.js",
|
|
89
|
-
require: "./dist/index.cjs"
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
sideEffects: false,
|
|
93
|
-
files: [
|
|
94
|
-
"dist/**"
|
|
95
|
-
],
|
|
96
|
-
scripts: {
|
|
97
|
-
build: "tsup",
|
|
98
|
-
dev: "tsup --watch",
|
|
99
|
-
clean: "rm -rf dist",
|
|
100
|
-
test: "cd tests && pnpm test"
|
|
101
|
-
},
|
|
102
|
-
peerDependencies: {
|
|
103
|
-
"@opencode-ai/plugin": ">=1.3.0",
|
|
104
|
-
"@opencode-ai/sdk": ">=1.3.0"
|
|
105
|
-
},
|
|
106
|
-
peerDependenciesMeta: {
|
|
107
|
-
"@opencode-ai/sdk": {
|
|
108
|
-
optional: true
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
devDependencies: {
|
|
112
|
-
"@raindrop-ai/core": "workspace:*",
|
|
113
|
-
"@opencode-ai/plugin": "^1.3.3",
|
|
114
|
-
"@opencode-ai/sdk": "^1.3.3",
|
|
115
|
-
"@types/node": "^20.11.17",
|
|
116
|
-
tsup: "^8.4.0",
|
|
117
|
-
typescript: "^5.3.3"
|
|
118
|
-
},
|
|
119
|
-
tsup: {
|
|
120
|
-
entry: [
|
|
121
|
-
"src/index.ts"
|
|
122
|
-
],
|
|
123
|
-
format: [
|
|
124
|
-
"cjs",
|
|
125
|
-
"esm"
|
|
126
|
-
],
|
|
127
|
-
dts: {
|
|
128
|
-
resolve: true
|
|
129
|
-
},
|
|
130
|
-
clean: true,
|
|
131
|
-
noExternal: [
|
|
132
|
-
"@raindrop-ai/core"
|
|
133
|
-
]
|
|
134
|
-
},
|
|
135
|
-
publishConfig: {
|
|
136
|
-
access: "public"
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// src/package-info.ts
|
|
141
|
-
var PLUGIN_NAME = package_default.name;
|
|
142
|
-
var PLUGIN_VERSION = package_default.version;
|
|
143
|
-
|
|
144
|
-
// ../core/dist/chunk-4UCYIEH4.js
|
|
27
|
+
// ../core/dist/chunk-OLYXZCOK.js
|
|
145
28
|
function getCrypto() {
|
|
146
29
|
const c = globalThis.crypto;
|
|
147
30
|
return c;
|
|
@@ -334,6 +217,91 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
|
|
|
334
217
|
]
|
|
335
218
|
};
|
|
336
219
|
}
|
|
220
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
221
|
+
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
222
|
+
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
223
|
+
function readEnvVar(name) {
|
|
224
|
+
var _a;
|
|
225
|
+
try {
|
|
226
|
+
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
227
|
+
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
228
|
+
return env[name];
|
|
229
|
+
}
|
|
230
|
+
} catch (e) {
|
|
231
|
+
}
|
|
232
|
+
return void 0;
|
|
233
|
+
}
|
|
234
|
+
function readWorkshopEnv() {
|
|
235
|
+
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
236
|
+
if (raw === void 0) return void 0;
|
|
237
|
+
const trimmed = raw.trim();
|
|
238
|
+
if (trimmed.length === 0) return void 0;
|
|
239
|
+
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
240
|
+
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
241
|
+
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
function isLocalDevHost(hostname) {
|
|
245
|
+
if (!hostname) return false;
|
|
246
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
if (hostname.endsWith(".localhost")) return true;
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
function readRuntimeHostname() {
|
|
253
|
+
try {
|
|
254
|
+
const loc = globalThis == null ? void 0 : globalThis.location;
|
|
255
|
+
if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
|
|
256
|
+
return loc.hostname;
|
|
257
|
+
}
|
|
258
|
+
} catch (e) {
|
|
259
|
+
}
|
|
260
|
+
return void 0;
|
|
261
|
+
}
|
|
262
|
+
function shouldAutoEnableLocalWorkshop() {
|
|
263
|
+
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
264
|
+
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
268
|
+
var _a, _b, _c;
|
|
269
|
+
if (baseUrl === null) return null;
|
|
270
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
271
|
+
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
272
|
+
}
|
|
273
|
+
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
274
|
+
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
275
|
+
const workshopEnv = readWorkshopEnv();
|
|
276
|
+
if (workshopEnv === "disable") return null;
|
|
277
|
+
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
278
|
+
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
279
|
+
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
283
|
+
var _a;
|
|
284
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
285
|
+
if (!baseUrl) return;
|
|
286
|
+
void postJson(`${baseUrl}traces`, body, {}, {
|
|
287
|
+
maxAttempts: 1,
|
|
288
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
289
|
+
sdkName: options.sdkName
|
|
290
|
+
}).catch(() => {
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
294
|
+
var _a;
|
|
295
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
296
|
+
if (!baseUrl) return;
|
|
297
|
+
const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
|
|
298
|
+
void postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
299
|
+
maxAttempts: 1,
|
|
300
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
301
|
+
sdkName: options.sdkName
|
|
302
|
+
}).catch(() => {
|
|
303
|
+
});
|
|
304
|
+
}
|
|
337
305
|
function mergePatches(target, source) {
|
|
338
306
|
var _a, _b, _c, _d;
|
|
339
307
|
const out = { ...target, ...source };
|
|
@@ -351,7 +319,7 @@ var EventShipper = class {
|
|
|
351
319
|
this.sticky = /* @__PURE__ */ new Map();
|
|
352
320
|
this.timers = /* @__PURE__ */ new Map();
|
|
353
321
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
354
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
322
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
355
323
|
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
356
324
|
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
357
325
|
this.enabled = opts.enabled !== false;
|
|
@@ -360,11 +328,15 @@ var EventShipper = class {
|
|
|
360
328
|
this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
|
|
361
329
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
362
330
|
this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
|
|
331
|
+
this.localDebuggerUrl = (_f = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _f : void 0;
|
|
332
|
+
if (this.debug && this.localDebuggerUrl) {
|
|
333
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
334
|
+
}
|
|
363
335
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
364
336
|
this.context = {
|
|
365
337
|
library: {
|
|
366
|
-
name: (
|
|
367
|
-
version: (
|
|
338
|
+
name: (_g = opts.libraryName) != null ? _g : "@raindrop-ai/core",
|
|
339
|
+
version: (_h = opts.libraryVersion) != null ? _h : "0.0.0"
|
|
368
340
|
},
|
|
369
341
|
metadata: {
|
|
370
342
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -450,6 +422,7 @@ var EventShipper = class {
|
|
|
450
422
|
}
|
|
451
423
|
}
|
|
452
424
|
];
|
|
425
|
+
if (!this.writeKey) return;
|
|
453
426
|
const url = `${this.baseUrl}signals/track`;
|
|
454
427
|
try {
|
|
455
428
|
await postJson(url, body, this.authHeaders(), {
|
|
@@ -480,6 +453,7 @@ var EventShipper = class {
|
|
|
480
453
|
traits: (_a = user.traits) != null ? _a : {}
|
|
481
454
|
};
|
|
482
455
|
});
|
|
456
|
+
if (!this.writeKey) return;
|
|
483
457
|
if (body.length === 0) return;
|
|
484
458
|
const url = `${this.baseUrl}users/identify`;
|
|
485
459
|
try {
|
|
@@ -556,6 +530,18 @@ var EventShipper = class {
|
|
|
556
530
|
endpoint: url
|
|
557
531
|
});
|
|
558
532
|
}
|
|
533
|
+
if (this.localDebuggerUrl) {
|
|
534
|
+
mirrorPartialEventToLocalDebugger(payload, {
|
|
535
|
+
baseUrl: this.localDebuggerUrl,
|
|
536
|
+
writeKey: this.writeKey,
|
|
537
|
+
debug: this.debug,
|
|
538
|
+
sdkName: this.sdkName
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
if (!this.writeKey) {
|
|
542
|
+
if (!isPending) this.sticky.delete(eventId);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
559
545
|
const p = postJson(url, payload, this.authHeaders(), {
|
|
560
546
|
maxAttempts: 3,
|
|
561
547
|
debug: this.debug,
|
|
@@ -580,28 +566,11 @@ var EventShipper = class {
|
|
|
580
566
|
}
|
|
581
567
|
}
|
|
582
568
|
};
|
|
583
|
-
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
584
|
-
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
585
|
-
var _a, _b, _c;
|
|
586
|
-
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;
|
|
587
|
-
return resolved ? (_c = formatEndpoint(resolved)) != null ? _c : null : null;
|
|
588
|
-
}
|
|
589
|
-
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
590
|
-
var _a;
|
|
591
|
-
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
592
|
-
if (!baseUrl) return;
|
|
593
|
-
void postJson(`${baseUrl}traces`, body, {}, {
|
|
594
|
-
maxAttempts: 1,
|
|
595
|
-
debug: (_a = options.debug) != null ? _a : false,
|
|
596
|
-
sdkName: options.sdkName
|
|
597
|
-
}).catch(() => {
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
569
|
var TraceShipper = class {
|
|
601
570
|
constructor(opts) {
|
|
602
571
|
this.queue = [];
|
|
603
572
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
604
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
573
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
605
574
|
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
606
575
|
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
607
576
|
this.enabled = opts.enabled !== false;
|
|
@@ -614,12 +583,9 @@ var TraceShipper = class {
|
|
|
614
583
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
615
584
|
this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
|
|
616
585
|
this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
|
|
617
|
-
|
|
618
|
-
if (
|
|
619
|
-
this.
|
|
620
|
-
if (this.debug) {
|
|
621
|
-
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
622
|
-
}
|
|
586
|
+
this.localDebuggerUrl = (_i = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _i : void 0;
|
|
587
|
+
if (this.debug && this.localDebuggerUrl) {
|
|
588
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
623
589
|
}
|
|
624
590
|
}
|
|
625
591
|
isDebugEnabled() {
|
|
@@ -747,6 +713,7 @@ var TraceShipper = class {
|
|
|
747
713
|
}
|
|
748
714
|
while (this.queue.length > 0) {
|
|
749
715
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
716
|
+
if (!this.writeKey) continue;
|
|
750
717
|
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
751
718
|
const url = `${this.baseUrl}traces`;
|
|
752
719
|
if (this.debug) {
|
|
@@ -789,6 +756,134 @@ var TraceShipper = class {
|
|
|
789
756
|
var import_async_hooks = require("async_hooks");
|
|
790
757
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
|
|
791
758
|
|
|
759
|
+
// src/config.ts
|
|
760
|
+
var import_node_fs = require("fs");
|
|
761
|
+
var import_node_os = require("os");
|
|
762
|
+
var import_node_path = require("path");
|
|
763
|
+
function loadConfig(projectDirectory) {
|
|
764
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
765
|
+
let merged = {};
|
|
766
|
+
const configPaths = [
|
|
767
|
+
(0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "opencode", "raindrop.json"),
|
|
768
|
+
(0, import_node_path.join)(projectDirectory, ".opencode", "raindrop.json")
|
|
769
|
+
];
|
|
770
|
+
for (const configPath of configPaths) {
|
|
771
|
+
try {
|
|
772
|
+
if ((0, import_node_fs.existsSync)(configPath)) {
|
|
773
|
+
const content = (0, import_node_fs.readFileSync)(configPath, "utf-8");
|
|
774
|
+
const parsed = JSON.parse(content);
|
|
775
|
+
merged = { ...merged, ...parsed };
|
|
776
|
+
}
|
|
777
|
+
} catch (e) {
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
let eventMetadata;
|
|
781
|
+
const envMeta = process.env["RAINDROP_EVENT_METADATA"];
|
|
782
|
+
if (envMeta) {
|
|
783
|
+
try {
|
|
784
|
+
eventMetadata = JSON.parse(envMeta);
|
|
785
|
+
} catch (e) {
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return {
|
|
789
|
+
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
790
|
+
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
791
|
+
eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
|
|
792
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
793
|
+
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
|
|
794
|
+
eventMetadata,
|
|
795
|
+
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
function resolveLocalWorkshopUrl(fileValue) {
|
|
799
|
+
const envValue = process.env["RAINDROP_LOCAL_WORKSHOP_URL"];
|
|
800
|
+
if (envValue !== void 0) {
|
|
801
|
+
if (envValue === "" || envValue.toLowerCase() === "null" || envValue.toLowerCase() === "false") {
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
804
|
+
return envValue;
|
|
805
|
+
}
|
|
806
|
+
return fileValue;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// package.json
|
|
810
|
+
var package_default = {
|
|
811
|
+
name: "@raindrop-ai/opencode-plugin",
|
|
812
|
+
version: "0.0.12",
|
|
813
|
+
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
814
|
+
type: "module",
|
|
815
|
+
main: "dist/index.js",
|
|
816
|
+
module: "dist/index.js",
|
|
817
|
+
types: "dist/index.d.ts",
|
|
818
|
+
license: "MIT",
|
|
819
|
+
repository: {
|
|
820
|
+
type: "git",
|
|
821
|
+
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
822
|
+
directory: "packages/opencode-plugin"
|
|
823
|
+
},
|
|
824
|
+
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/opencode-plugin#readme",
|
|
825
|
+
bugs: {
|
|
826
|
+
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
827
|
+
},
|
|
828
|
+
exports: {
|
|
829
|
+
".": {
|
|
830
|
+
types: "./dist/index.d.ts",
|
|
831
|
+
import: "./dist/index.js",
|
|
832
|
+
require: "./dist/index.cjs"
|
|
833
|
+
}
|
|
834
|
+
},
|
|
835
|
+
sideEffects: false,
|
|
836
|
+
files: [
|
|
837
|
+
"dist/**"
|
|
838
|
+
],
|
|
839
|
+
scripts: {
|
|
840
|
+
build: "tsup",
|
|
841
|
+
dev: "tsup --watch",
|
|
842
|
+
clean: "rm -rf dist",
|
|
843
|
+
test: "cd tests && pnpm test"
|
|
844
|
+
},
|
|
845
|
+
peerDependencies: {
|
|
846
|
+
"@opencode-ai/plugin": ">=1.3.0",
|
|
847
|
+
"@opencode-ai/sdk": ">=1.3.0"
|
|
848
|
+
},
|
|
849
|
+
peerDependenciesMeta: {
|
|
850
|
+
"@opencode-ai/sdk": {
|
|
851
|
+
optional: true
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
devDependencies: {
|
|
855
|
+
"@raindrop-ai/core": "workspace:*",
|
|
856
|
+
"@opencode-ai/plugin": "^1.3.3",
|
|
857
|
+
"@opencode-ai/sdk": "^1.3.3",
|
|
858
|
+
"@types/node": "^20.11.17",
|
|
859
|
+
tsup: "^8.4.0",
|
|
860
|
+
typescript: "^5.3.3"
|
|
861
|
+
},
|
|
862
|
+
tsup: {
|
|
863
|
+
entry: [
|
|
864
|
+
"src/index.ts"
|
|
865
|
+
],
|
|
866
|
+
format: [
|
|
867
|
+
"cjs",
|
|
868
|
+
"esm"
|
|
869
|
+
],
|
|
870
|
+
dts: {
|
|
871
|
+
resolve: true
|
|
872
|
+
},
|
|
873
|
+
clean: true,
|
|
874
|
+
noExternal: [
|
|
875
|
+
"@raindrop-ai/core"
|
|
876
|
+
]
|
|
877
|
+
},
|
|
878
|
+
publishConfig: {
|
|
879
|
+
access: "public"
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
// src/package-info.ts
|
|
884
|
+
var PLUGIN_NAME = package_default.name;
|
|
885
|
+
var PLUGIN_VERSION = package_default.version;
|
|
886
|
+
|
|
792
887
|
// src/shipper.ts
|
|
793
888
|
var EventShipper2 = class extends EventShipper {
|
|
794
889
|
constructor(opts) {
|
|
@@ -959,6 +1054,19 @@ function endPendingToolSpanWithError(state, callID, tool, toolCallArgs, errorMes
|
|
|
959
1054
|
}
|
|
960
1055
|
return true;
|
|
961
1056
|
}
|
|
1057
|
+
function unwrapQuotes(s) {
|
|
1058
|
+
if (s.length < 2) return s;
|
|
1059
|
+
const first = s[0];
|
|
1060
|
+
const last = s[s.length - 1];
|
|
1061
|
+
if ((first === '"' || first === "'") && first === last) return s.slice(1, -1);
|
|
1062
|
+
return s;
|
|
1063
|
+
}
|
|
1064
|
+
function buildPromptMessages(systemPrompt, userInput) {
|
|
1065
|
+
const messages = [];
|
|
1066
|
+
if (systemPrompt) messages.push({ role: "system", content: systemPrompt });
|
|
1067
|
+
messages.push({ role: "user", content: unwrapQuotes(userInput) });
|
|
1068
|
+
return JSON.stringify(messages);
|
|
1069
|
+
}
|
|
962
1070
|
function getHostname() {
|
|
963
1071
|
var _a;
|
|
964
1072
|
try {
|
|
@@ -1184,9 +1292,14 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
1184
1292
|
const rootSpan = state.currentRootSpan;
|
|
1185
1293
|
const isCompaction = state.isCompacting === true;
|
|
1186
1294
|
if (state.parentId) {
|
|
1295
|
+
const userInput = unwrapQuotes(state.currentInput);
|
|
1187
1296
|
const llmAttrs = [
|
|
1188
1297
|
attrString("ai.operationId", "generateText"),
|
|
1189
|
-
attrString("ai.prompt",
|
|
1298
|
+
attrString("ai.prompt", userInput),
|
|
1299
|
+
attrString(
|
|
1300
|
+
"ai.prompt.messages",
|
|
1301
|
+
buildPromptMessages(state.currentSystemPrompt, state.currentInput)
|
|
1302
|
+
),
|
|
1190
1303
|
attrString("ai.response.text", outputText),
|
|
1191
1304
|
attrString("gen_ai.system", providerID),
|
|
1192
1305
|
attrString("gen_ai.request.model", modelID),
|
|
@@ -1231,9 +1344,14 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
1231
1344
|
});
|
|
1232
1345
|
} else {
|
|
1233
1346
|
rootSpan.name = isCompaction ? "ai.compaction" : modelName;
|
|
1347
|
+
const userInput = unwrapQuotes(state.currentInput);
|
|
1234
1348
|
const rootAttrs = [
|
|
1235
1349
|
attrString("ai.operationId", "generateText"),
|
|
1236
|
-
attrString("ai.prompt",
|
|
1350
|
+
attrString("ai.prompt", userInput),
|
|
1351
|
+
attrString(
|
|
1352
|
+
"ai.prompt.messages",
|
|
1353
|
+
buildPromptMessages(state.currentSystemPrompt, state.currentInput)
|
|
1354
|
+
),
|
|
1237
1355
|
attrString("ai.response.text", outputText),
|
|
1238
1356
|
attrString("gen_ai.system", providerID),
|
|
1239
1357
|
attrString("gen_ai.request.model", modelID),
|
|
@@ -1624,25 +1742,33 @@ async function plugin(input) {
|
|
|
1624
1742
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
1625
1743
|
}
|
|
1626
1744
|
appLog("info", `Loading ${PLUGIN_NAME} v${PLUGIN_VERSION}`);
|
|
1627
|
-
|
|
1745
|
+
const resolvedLocalUrl = resolveLocalDebuggerBaseUrl(config.localWorkshopUrl);
|
|
1746
|
+
const hasLocalDestination = resolvedLocalUrl !== null;
|
|
1747
|
+
if (!config.writeKey && !hasLocalDestination) {
|
|
1628
1748
|
appLog(
|
|
1629
1749
|
"warn",
|
|
1630
|
-
"RAINDROP_WRITE_KEY not set \u2014 Raindrop tracing disabled. Set
|
|
1750
|
+
"RAINDROP_WRITE_KEY not set and no local Workshop daemon detected \u2014 Raindrop tracing disabled. Set RAINDROP_WRITE_KEY for cloud, or RAINDROP_LOCAL_WORKSHOP_URL / RAINDROP_LOCAL_DEBUGGER for local-only mode."
|
|
1631
1751
|
);
|
|
1632
1752
|
return {};
|
|
1633
1753
|
}
|
|
1634
1754
|
if (config.debug) {
|
|
1635
|
-
|
|
1755
|
+
const destinations = [
|
|
1756
|
+
config.writeKey ? `cloud (${config.endpoint})` : null,
|
|
1757
|
+
resolvedLocalUrl ? `local Workshop (${resolvedLocalUrl})` : null
|
|
1758
|
+
].filter(Boolean);
|
|
1759
|
+
appLog("info", `Raindrop tracing enabled \u2014 destinations: ${destinations.join(", ")}`);
|
|
1636
1760
|
}
|
|
1637
1761
|
const eventShipper = new EventShipper2({
|
|
1638
1762
|
writeKey: config.writeKey,
|
|
1639
1763
|
endpoint: config.endpoint,
|
|
1640
|
-
debug: config.debug
|
|
1764
|
+
debug: config.debug,
|
|
1765
|
+
localDebuggerUrl: config.localWorkshopUrl
|
|
1641
1766
|
});
|
|
1642
1767
|
const traceShipper = new TraceShipper2({
|
|
1643
1768
|
writeKey: config.writeKey,
|
|
1644
1769
|
endpoint: config.endpoint,
|
|
1645
|
-
debug: config.debug
|
|
1770
|
+
debug: config.debug,
|
|
1771
|
+
localDebuggerUrl: config.localWorkshopUrl
|
|
1646
1772
|
});
|
|
1647
1773
|
const worktree = (_a = input.worktree) != null ? _a : input.directory;
|
|
1648
1774
|
const hooks = createHooks(
|
package/dist/index.js
CHANGED
|
@@ -5,124 +5,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
5
5
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
import { existsSync, readFileSync } from "fs";
|
|
10
|
-
import { homedir } from "os";
|
|
11
|
-
import { join } from "path";
|
|
12
|
-
function loadConfig(projectDirectory) {
|
|
13
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
14
|
-
let merged = {};
|
|
15
|
-
const configPaths = [
|
|
16
|
-
join(homedir(), ".config", "opencode", "raindrop.json"),
|
|
17
|
-
join(projectDirectory, ".opencode", "raindrop.json")
|
|
18
|
-
];
|
|
19
|
-
for (const configPath of configPaths) {
|
|
20
|
-
try {
|
|
21
|
-
if (existsSync(configPath)) {
|
|
22
|
-
const content = readFileSync(configPath, "utf-8");
|
|
23
|
-
const parsed = JSON.parse(content);
|
|
24
|
-
merged = { ...merged, ...parsed };
|
|
25
|
-
}
|
|
26
|
-
} catch (e) {
|
|
27
|
-
}
|
|
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
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
39
|
-
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
40
|
-
eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
|
|
41
|
-
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
42
|
-
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
|
|
43
|
-
eventMetadata
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// package.json
|
|
48
|
-
var package_default = {
|
|
49
|
-
name: "@raindrop-ai/opencode-plugin",
|
|
50
|
-
version: "0.0.11",
|
|
51
|
-
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
52
|
-
type: "module",
|
|
53
|
-
main: "dist/index.js",
|
|
54
|
-
module: "dist/index.js",
|
|
55
|
-
types: "dist/index.d.ts",
|
|
56
|
-
license: "MIT",
|
|
57
|
-
repository: {
|
|
58
|
-
type: "git",
|
|
59
|
-
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
60
|
-
directory: "packages/opencode-plugin"
|
|
61
|
-
},
|
|
62
|
-
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/opencode-plugin#readme",
|
|
63
|
-
bugs: {
|
|
64
|
-
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
65
|
-
},
|
|
66
|
-
exports: {
|
|
67
|
-
".": {
|
|
68
|
-
types: "./dist/index.d.ts",
|
|
69
|
-
import: "./dist/index.js",
|
|
70
|
-
require: "./dist/index.cjs"
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
sideEffects: false,
|
|
74
|
-
files: [
|
|
75
|
-
"dist/**"
|
|
76
|
-
],
|
|
77
|
-
scripts: {
|
|
78
|
-
build: "tsup",
|
|
79
|
-
dev: "tsup --watch",
|
|
80
|
-
clean: "rm -rf dist",
|
|
81
|
-
test: "cd tests && pnpm test"
|
|
82
|
-
},
|
|
83
|
-
peerDependencies: {
|
|
84
|
-
"@opencode-ai/plugin": ">=1.3.0",
|
|
85
|
-
"@opencode-ai/sdk": ">=1.3.0"
|
|
86
|
-
},
|
|
87
|
-
peerDependenciesMeta: {
|
|
88
|
-
"@opencode-ai/sdk": {
|
|
89
|
-
optional: true
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
devDependencies: {
|
|
93
|
-
"@raindrop-ai/core": "workspace:*",
|
|
94
|
-
"@opencode-ai/plugin": "^1.3.3",
|
|
95
|
-
"@opencode-ai/sdk": "^1.3.3",
|
|
96
|
-
"@types/node": "^20.11.17",
|
|
97
|
-
tsup: "^8.4.0",
|
|
98
|
-
typescript: "^5.3.3"
|
|
99
|
-
},
|
|
100
|
-
tsup: {
|
|
101
|
-
entry: [
|
|
102
|
-
"src/index.ts"
|
|
103
|
-
],
|
|
104
|
-
format: [
|
|
105
|
-
"cjs",
|
|
106
|
-
"esm"
|
|
107
|
-
],
|
|
108
|
-
dts: {
|
|
109
|
-
resolve: true
|
|
110
|
-
},
|
|
111
|
-
clean: true,
|
|
112
|
-
noExternal: [
|
|
113
|
-
"@raindrop-ai/core"
|
|
114
|
-
]
|
|
115
|
-
},
|
|
116
|
-
publishConfig: {
|
|
117
|
-
access: "public"
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
// src/package-info.ts
|
|
122
|
-
var PLUGIN_NAME = package_default.name;
|
|
123
|
-
var PLUGIN_VERSION = package_default.version;
|
|
124
|
-
|
|
125
|
-
// ../core/dist/chunk-4UCYIEH4.js
|
|
8
|
+
// ../core/dist/chunk-OLYXZCOK.js
|
|
126
9
|
function getCrypto() {
|
|
127
10
|
const c = globalThis.crypto;
|
|
128
11
|
return c;
|
|
@@ -315,6 +198,91 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
|
|
|
315
198
|
]
|
|
316
199
|
};
|
|
317
200
|
}
|
|
201
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
202
|
+
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
203
|
+
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
204
|
+
function readEnvVar(name) {
|
|
205
|
+
var _a;
|
|
206
|
+
try {
|
|
207
|
+
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
208
|
+
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
209
|
+
return env[name];
|
|
210
|
+
}
|
|
211
|
+
} catch (e) {
|
|
212
|
+
}
|
|
213
|
+
return void 0;
|
|
214
|
+
}
|
|
215
|
+
function readWorkshopEnv() {
|
|
216
|
+
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
217
|
+
if (raw === void 0) return void 0;
|
|
218
|
+
const trimmed = raw.trim();
|
|
219
|
+
if (trimmed.length === 0) return void 0;
|
|
220
|
+
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
221
|
+
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
222
|
+
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
function isLocalDevHost(hostname) {
|
|
226
|
+
if (!hostname) return false;
|
|
227
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
if (hostname.endsWith(".localhost")) return true;
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
function readRuntimeHostname() {
|
|
234
|
+
try {
|
|
235
|
+
const loc = globalThis == null ? void 0 : globalThis.location;
|
|
236
|
+
if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
|
|
237
|
+
return loc.hostname;
|
|
238
|
+
}
|
|
239
|
+
} catch (e) {
|
|
240
|
+
}
|
|
241
|
+
return void 0;
|
|
242
|
+
}
|
|
243
|
+
function shouldAutoEnableLocalWorkshop() {
|
|
244
|
+
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
245
|
+
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
249
|
+
var _a, _b, _c;
|
|
250
|
+
if (baseUrl === null) return null;
|
|
251
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
252
|
+
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
253
|
+
}
|
|
254
|
+
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
255
|
+
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
256
|
+
const workshopEnv = readWorkshopEnv();
|
|
257
|
+
if (workshopEnv === "disable") return null;
|
|
258
|
+
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
259
|
+
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
260
|
+
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
264
|
+
var _a;
|
|
265
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
266
|
+
if (!baseUrl) return;
|
|
267
|
+
void postJson(`${baseUrl}traces`, body, {}, {
|
|
268
|
+
maxAttempts: 1,
|
|
269
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
270
|
+
sdkName: options.sdkName
|
|
271
|
+
}).catch(() => {
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
275
|
+
var _a;
|
|
276
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
277
|
+
if (!baseUrl) return;
|
|
278
|
+
const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
|
|
279
|
+
void postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
280
|
+
maxAttempts: 1,
|
|
281
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
282
|
+
sdkName: options.sdkName
|
|
283
|
+
}).catch(() => {
|
|
284
|
+
});
|
|
285
|
+
}
|
|
318
286
|
function mergePatches(target, source) {
|
|
319
287
|
var _a, _b, _c, _d;
|
|
320
288
|
const out = { ...target, ...source };
|
|
@@ -332,7 +300,7 @@ var EventShipper = class {
|
|
|
332
300
|
this.sticky = /* @__PURE__ */ new Map();
|
|
333
301
|
this.timers = /* @__PURE__ */ new Map();
|
|
334
302
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
335
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
303
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
336
304
|
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
337
305
|
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
338
306
|
this.enabled = opts.enabled !== false;
|
|
@@ -341,11 +309,15 @@ var EventShipper = class {
|
|
|
341
309
|
this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
|
|
342
310
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
343
311
|
this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
|
|
312
|
+
this.localDebuggerUrl = (_f = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _f : void 0;
|
|
313
|
+
if (this.debug && this.localDebuggerUrl) {
|
|
314
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
315
|
+
}
|
|
344
316
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
345
317
|
this.context = {
|
|
346
318
|
library: {
|
|
347
|
-
name: (
|
|
348
|
-
version: (
|
|
319
|
+
name: (_g = opts.libraryName) != null ? _g : "@raindrop-ai/core",
|
|
320
|
+
version: (_h = opts.libraryVersion) != null ? _h : "0.0.0"
|
|
349
321
|
},
|
|
350
322
|
metadata: {
|
|
351
323
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -431,6 +403,7 @@ var EventShipper = class {
|
|
|
431
403
|
}
|
|
432
404
|
}
|
|
433
405
|
];
|
|
406
|
+
if (!this.writeKey) return;
|
|
434
407
|
const url = `${this.baseUrl}signals/track`;
|
|
435
408
|
try {
|
|
436
409
|
await postJson(url, body, this.authHeaders(), {
|
|
@@ -461,6 +434,7 @@ var EventShipper = class {
|
|
|
461
434
|
traits: (_a = user.traits) != null ? _a : {}
|
|
462
435
|
};
|
|
463
436
|
});
|
|
437
|
+
if (!this.writeKey) return;
|
|
464
438
|
if (body.length === 0) return;
|
|
465
439
|
const url = `${this.baseUrl}users/identify`;
|
|
466
440
|
try {
|
|
@@ -537,6 +511,18 @@ var EventShipper = class {
|
|
|
537
511
|
endpoint: url
|
|
538
512
|
});
|
|
539
513
|
}
|
|
514
|
+
if (this.localDebuggerUrl) {
|
|
515
|
+
mirrorPartialEventToLocalDebugger(payload, {
|
|
516
|
+
baseUrl: this.localDebuggerUrl,
|
|
517
|
+
writeKey: this.writeKey,
|
|
518
|
+
debug: this.debug,
|
|
519
|
+
sdkName: this.sdkName
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
if (!this.writeKey) {
|
|
523
|
+
if (!isPending) this.sticky.delete(eventId);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
540
526
|
const p = postJson(url, payload, this.authHeaders(), {
|
|
541
527
|
maxAttempts: 3,
|
|
542
528
|
debug: this.debug,
|
|
@@ -561,28 +547,11 @@ var EventShipper = class {
|
|
|
561
547
|
}
|
|
562
548
|
}
|
|
563
549
|
};
|
|
564
|
-
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
565
|
-
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
566
|
-
var _a, _b, _c;
|
|
567
|
-
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;
|
|
568
|
-
return resolved ? (_c = formatEndpoint(resolved)) != null ? _c : null : null;
|
|
569
|
-
}
|
|
570
|
-
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
571
|
-
var _a;
|
|
572
|
-
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
573
|
-
if (!baseUrl) return;
|
|
574
|
-
void postJson(`${baseUrl}traces`, body, {}, {
|
|
575
|
-
maxAttempts: 1,
|
|
576
|
-
debug: (_a = options.debug) != null ? _a : false,
|
|
577
|
-
sdkName: options.sdkName
|
|
578
|
-
}).catch(() => {
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
550
|
var TraceShipper = class {
|
|
582
551
|
constructor(opts) {
|
|
583
552
|
this.queue = [];
|
|
584
553
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
585
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
554
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
586
555
|
this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
|
|
587
556
|
this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
|
|
588
557
|
this.enabled = opts.enabled !== false;
|
|
@@ -595,12 +564,9 @@ var TraceShipper = class {
|
|
|
595
564
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
596
565
|
this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
|
|
597
566
|
this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
|
|
598
|
-
|
|
599
|
-
if (
|
|
600
|
-
this.
|
|
601
|
-
if (this.debug) {
|
|
602
|
-
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
603
|
-
}
|
|
567
|
+
this.localDebuggerUrl = (_i = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _i : void 0;
|
|
568
|
+
if (this.debug && this.localDebuggerUrl) {
|
|
569
|
+
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
604
570
|
}
|
|
605
571
|
}
|
|
606
572
|
isDebugEnabled() {
|
|
@@ -728,6 +694,7 @@ var TraceShipper = class {
|
|
|
728
694
|
}
|
|
729
695
|
while (this.queue.length > 0) {
|
|
730
696
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
697
|
+
if (!this.writeKey) continue;
|
|
731
698
|
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
732
699
|
const url = `${this.baseUrl}traces`;
|
|
733
700
|
if (this.debug) {
|
|
@@ -770,6 +737,134 @@ var TraceShipper = class {
|
|
|
770
737
|
import { AsyncLocalStorage } from "async_hooks";
|
|
771
738
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
|
|
772
739
|
|
|
740
|
+
// src/config.ts
|
|
741
|
+
import { existsSync, readFileSync } from "fs";
|
|
742
|
+
import { homedir } from "os";
|
|
743
|
+
import { join } from "path";
|
|
744
|
+
function loadConfig(projectDirectory) {
|
|
745
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
746
|
+
let merged = {};
|
|
747
|
+
const configPaths = [
|
|
748
|
+
join(homedir(), ".config", "opencode", "raindrop.json"),
|
|
749
|
+
join(projectDirectory, ".opencode", "raindrop.json")
|
|
750
|
+
];
|
|
751
|
+
for (const configPath of configPaths) {
|
|
752
|
+
try {
|
|
753
|
+
if (existsSync(configPath)) {
|
|
754
|
+
const content = readFileSync(configPath, "utf-8");
|
|
755
|
+
const parsed = JSON.parse(content);
|
|
756
|
+
merged = { ...merged, ...parsed };
|
|
757
|
+
}
|
|
758
|
+
} catch (e) {
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
let eventMetadata;
|
|
762
|
+
const envMeta = process.env["RAINDROP_EVENT_METADATA"];
|
|
763
|
+
if (envMeta) {
|
|
764
|
+
try {
|
|
765
|
+
eventMetadata = JSON.parse(envMeta);
|
|
766
|
+
} catch (e) {
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return {
|
|
770
|
+
writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
|
|
771
|
+
endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
|
|
772
|
+
eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
|
|
773
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
|
|
774
|
+
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
|
|
775
|
+
eventMetadata,
|
|
776
|
+
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
function resolveLocalWorkshopUrl(fileValue) {
|
|
780
|
+
const envValue = process.env["RAINDROP_LOCAL_WORKSHOP_URL"];
|
|
781
|
+
if (envValue !== void 0) {
|
|
782
|
+
if (envValue === "" || envValue.toLowerCase() === "null" || envValue.toLowerCase() === "false") {
|
|
783
|
+
return null;
|
|
784
|
+
}
|
|
785
|
+
return envValue;
|
|
786
|
+
}
|
|
787
|
+
return fileValue;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// package.json
|
|
791
|
+
var package_default = {
|
|
792
|
+
name: "@raindrop-ai/opencode-plugin",
|
|
793
|
+
version: "0.0.12",
|
|
794
|
+
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
795
|
+
type: "module",
|
|
796
|
+
main: "dist/index.js",
|
|
797
|
+
module: "dist/index.js",
|
|
798
|
+
types: "dist/index.d.ts",
|
|
799
|
+
license: "MIT",
|
|
800
|
+
repository: {
|
|
801
|
+
type: "git",
|
|
802
|
+
url: "git+https://github.com/raindrop-ai/raindrop-js.git",
|
|
803
|
+
directory: "packages/opencode-plugin"
|
|
804
|
+
},
|
|
805
|
+
homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/opencode-plugin#readme",
|
|
806
|
+
bugs: {
|
|
807
|
+
url: "https://github.com/raindrop-ai/raindrop-js/issues"
|
|
808
|
+
},
|
|
809
|
+
exports: {
|
|
810
|
+
".": {
|
|
811
|
+
types: "./dist/index.d.ts",
|
|
812
|
+
import: "./dist/index.js",
|
|
813
|
+
require: "./dist/index.cjs"
|
|
814
|
+
}
|
|
815
|
+
},
|
|
816
|
+
sideEffects: false,
|
|
817
|
+
files: [
|
|
818
|
+
"dist/**"
|
|
819
|
+
],
|
|
820
|
+
scripts: {
|
|
821
|
+
build: "tsup",
|
|
822
|
+
dev: "tsup --watch",
|
|
823
|
+
clean: "rm -rf dist",
|
|
824
|
+
test: "cd tests && pnpm test"
|
|
825
|
+
},
|
|
826
|
+
peerDependencies: {
|
|
827
|
+
"@opencode-ai/plugin": ">=1.3.0",
|
|
828
|
+
"@opencode-ai/sdk": ">=1.3.0"
|
|
829
|
+
},
|
|
830
|
+
peerDependenciesMeta: {
|
|
831
|
+
"@opencode-ai/sdk": {
|
|
832
|
+
optional: true
|
|
833
|
+
}
|
|
834
|
+
},
|
|
835
|
+
devDependencies: {
|
|
836
|
+
"@raindrop-ai/core": "workspace:*",
|
|
837
|
+
"@opencode-ai/plugin": "^1.3.3",
|
|
838
|
+
"@opencode-ai/sdk": "^1.3.3",
|
|
839
|
+
"@types/node": "^20.11.17",
|
|
840
|
+
tsup: "^8.4.0",
|
|
841
|
+
typescript: "^5.3.3"
|
|
842
|
+
},
|
|
843
|
+
tsup: {
|
|
844
|
+
entry: [
|
|
845
|
+
"src/index.ts"
|
|
846
|
+
],
|
|
847
|
+
format: [
|
|
848
|
+
"cjs",
|
|
849
|
+
"esm"
|
|
850
|
+
],
|
|
851
|
+
dts: {
|
|
852
|
+
resolve: true
|
|
853
|
+
},
|
|
854
|
+
clean: true,
|
|
855
|
+
noExternal: [
|
|
856
|
+
"@raindrop-ai/core"
|
|
857
|
+
]
|
|
858
|
+
},
|
|
859
|
+
publishConfig: {
|
|
860
|
+
access: "public"
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
// src/package-info.ts
|
|
865
|
+
var PLUGIN_NAME = package_default.name;
|
|
866
|
+
var PLUGIN_VERSION = package_default.version;
|
|
867
|
+
|
|
773
868
|
// src/shipper.ts
|
|
774
869
|
var EventShipper2 = class extends EventShipper {
|
|
775
870
|
constructor(opts) {
|
|
@@ -940,6 +1035,19 @@ function endPendingToolSpanWithError(state, callID, tool, toolCallArgs, errorMes
|
|
|
940
1035
|
}
|
|
941
1036
|
return true;
|
|
942
1037
|
}
|
|
1038
|
+
function unwrapQuotes(s) {
|
|
1039
|
+
if (s.length < 2) return s;
|
|
1040
|
+
const first = s[0];
|
|
1041
|
+
const last = s[s.length - 1];
|
|
1042
|
+
if ((first === '"' || first === "'") && first === last) return s.slice(1, -1);
|
|
1043
|
+
return s;
|
|
1044
|
+
}
|
|
1045
|
+
function buildPromptMessages(systemPrompt, userInput) {
|
|
1046
|
+
const messages = [];
|
|
1047
|
+
if (systemPrompt) messages.push({ role: "system", content: systemPrompt });
|
|
1048
|
+
messages.push({ role: "user", content: unwrapQuotes(userInput) });
|
|
1049
|
+
return JSON.stringify(messages);
|
|
1050
|
+
}
|
|
943
1051
|
function getHostname() {
|
|
944
1052
|
var _a;
|
|
945
1053
|
try {
|
|
@@ -1165,9 +1273,14 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
1165
1273
|
const rootSpan = state.currentRootSpan;
|
|
1166
1274
|
const isCompaction = state.isCompacting === true;
|
|
1167
1275
|
if (state.parentId) {
|
|
1276
|
+
const userInput = unwrapQuotes(state.currentInput);
|
|
1168
1277
|
const llmAttrs = [
|
|
1169
1278
|
attrString("ai.operationId", "generateText"),
|
|
1170
|
-
attrString("ai.prompt",
|
|
1279
|
+
attrString("ai.prompt", userInput),
|
|
1280
|
+
attrString(
|
|
1281
|
+
"ai.prompt.messages",
|
|
1282
|
+
buildPromptMessages(state.currentSystemPrompt, state.currentInput)
|
|
1283
|
+
),
|
|
1171
1284
|
attrString("ai.response.text", outputText),
|
|
1172
1285
|
attrString("gen_ai.system", providerID),
|
|
1173
1286
|
attrString("gen_ai.request.model", modelID),
|
|
@@ -1212,9 +1325,14 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
1212
1325
|
});
|
|
1213
1326
|
} else {
|
|
1214
1327
|
rootSpan.name = isCompaction ? "ai.compaction" : modelName;
|
|
1328
|
+
const userInput = unwrapQuotes(state.currentInput);
|
|
1215
1329
|
const rootAttrs = [
|
|
1216
1330
|
attrString("ai.operationId", "generateText"),
|
|
1217
|
-
attrString("ai.prompt",
|
|
1331
|
+
attrString("ai.prompt", userInput),
|
|
1332
|
+
attrString(
|
|
1333
|
+
"ai.prompt.messages",
|
|
1334
|
+
buildPromptMessages(state.currentSystemPrompt, state.currentInput)
|
|
1335
|
+
),
|
|
1218
1336
|
attrString("ai.response.text", outputText),
|
|
1219
1337
|
attrString("gen_ai.system", providerID),
|
|
1220
1338
|
attrString("gen_ai.request.model", modelID),
|
|
@@ -1605,25 +1723,33 @@ async function plugin(input) {
|
|
|
1605
1723
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
1606
1724
|
}
|
|
1607
1725
|
appLog("info", `Loading ${PLUGIN_NAME} v${PLUGIN_VERSION}`);
|
|
1608
|
-
|
|
1726
|
+
const resolvedLocalUrl = resolveLocalDebuggerBaseUrl(config.localWorkshopUrl);
|
|
1727
|
+
const hasLocalDestination = resolvedLocalUrl !== null;
|
|
1728
|
+
if (!config.writeKey && !hasLocalDestination) {
|
|
1609
1729
|
appLog(
|
|
1610
1730
|
"warn",
|
|
1611
|
-
"RAINDROP_WRITE_KEY not set \u2014 Raindrop tracing disabled. Set
|
|
1731
|
+
"RAINDROP_WRITE_KEY not set and no local Workshop daemon detected \u2014 Raindrop tracing disabled. Set RAINDROP_WRITE_KEY for cloud, or RAINDROP_LOCAL_WORKSHOP_URL / RAINDROP_LOCAL_DEBUGGER for local-only mode."
|
|
1612
1732
|
);
|
|
1613
1733
|
return {};
|
|
1614
1734
|
}
|
|
1615
1735
|
if (config.debug) {
|
|
1616
|
-
|
|
1736
|
+
const destinations = [
|
|
1737
|
+
config.writeKey ? `cloud (${config.endpoint})` : null,
|
|
1738
|
+
resolvedLocalUrl ? `local Workshop (${resolvedLocalUrl})` : null
|
|
1739
|
+
].filter(Boolean);
|
|
1740
|
+
appLog("info", `Raindrop tracing enabled \u2014 destinations: ${destinations.join(", ")}`);
|
|
1617
1741
|
}
|
|
1618
1742
|
const eventShipper = new EventShipper2({
|
|
1619
1743
|
writeKey: config.writeKey,
|
|
1620
1744
|
endpoint: config.endpoint,
|
|
1621
|
-
debug: config.debug
|
|
1745
|
+
debug: config.debug,
|
|
1746
|
+
localDebuggerUrl: config.localWorkshopUrl
|
|
1622
1747
|
});
|
|
1623
1748
|
const traceShipper = new TraceShipper2({
|
|
1624
1749
|
writeKey: config.writeKey,
|
|
1625
1750
|
endpoint: config.endpoint,
|
|
1626
|
-
debug: config.debug
|
|
1751
|
+
debug: config.debug,
|
|
1752
|
+
localDebuggerUrl: config.localWorkshopUrl
|
|
1627
1753
|
});
|
|
1628
1754
|
const worktree = (_a = input.worktree) != null ? _a : input.directory;
|
|
1629
1755
|
const hooks = createHooks(
|