@raindrop-ai/opencode-plugin 0.0.6 → 0.0.7

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 CHANGED
@@ -29,7 +29,7 @@ var import_node_fs = require("fs");
29
29
  var import_node_os = require("os");
30
30
  var import_node_path = require("path");
31
31
  function loadConfig(projectDirectory) {
32
- var _a, _b, _c, _d, _e, _f;
32
+ var _a, _b, _c, _d, _e, _f, _g;
33
33
  let merged = {};
34
34
  const configPaths = [
35
35
  (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "opencode", "raindrop.json"),
@@ -58,6 +58,7 @@ function loadConfig(projectDirectory) {
58
58
  endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
59
59
  eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
60
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,
61
62
  eventMetadata
62
63
  };
63
64
  }
@@ -65,7 +66,7 @@ function loadConfig(projectDirectory) {
65
66
  // package.json
66
67
  var package_default = {
67
68
  name: "@raindrop-ai/opencode-plugin",
68
- version: "0.0.6",
69
+ version: "0.0.7",
69
70
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
70
71
  type: "module",
71
72
  main: "dist/index.cjs",
@@ -89,8 +90,8 @@ var package_default = {
89
90
  test: "cd tests && pnpm test"
90
91
  },
91
92
  peerDependencies: {
92
- "@opencode-ai/plugin": ">=1.2.0",
93
- "@opencode-ai/sdk": ">=1.2.0"
93
+ "@opencode-ai/plugin": ">=1.3.0",
94
+ "@opencode-ai/sdk": ">=1.3.0"
94
95
  },
95
96
  peerDependenciesMeta: {
96
97
  "@opencode-ai/sdk": {
@@ -99,8 +100,8 @@ var package_default = {
99
100
  },
100
101
  devDependencies: {
101
102
  "@raindrop-ai/core": "workspace:*",
102
- "@opencode-ai/plugin": "^1.2.0",
103
- "@opencode-ai/sdk": "^1.2.0",
103
+ "@opencode-ai/plugin": "^1.3.3",
104
+ "@opencode-ai/sdk": "^1.3.3",
104
105
  "@types/node": "^20.11.17",
105
106
  tsup: "^8.4.0",
106
107
  typescript: "^5.3.3"
@@ -130,7 +131,7 @@ var package_default = {
130
131
  var PLUGIN_NAME = package_default.name;
131
132
  var PLUGIN_VERSION = package_default.version;
132
133
 
133
- // ../core/dist/chunk-FTBZHS25.js
134
+ // ../core/dist/chunk-H6VSZSLN.js
134
135
  function getCrypto() {
135
136
  const c = globalThis.crypto;
136
137
  return c;
@@ -375,6 +376,7 @@ var EventShipper = class {
375
376
  console.log(`${this.prefix} queue patch`, {
376
377
  eventId,
377
378
  userId: patch.userId,
379
+ convoId: patch.convoId,
378
380
  eventName: patch.eventName,
379
381
  hasInput: typeof patch.input === "string" && patch.input.length > 0,
380
382
  hasOutput: typeof patch.output === "string" && patch.output.length > 0,
@@ -503,16 +505,18 @@ var EventShipper = class {
503
505
  return;
504
506
  }
505
507
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
508
+ const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
509
+ const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
506
510
  const payload = {
507
511
  event_id: eventId,
508
512
  user_id: userId,
509
513
  event: eventName,
510
- timestamp: (_f = accumulated.timestamp) != null ? _f : (/* @__PURE__ */ new Date()).toISOString(),
514
+ timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
511
515
  ai_data: {
512
516
  input: accumulated.input,
513
517
  output: accumulated.output,
514
518
  model: accumulated.model,
515
- convo_id: (_g = accumulated.convoId) != null ? _g : sticky.convoId
519
+ convo_id: convoId
516
520
  },
517
521
  properties: {
518
522
  ...restProperties,
@@ -520,7 +524,7 @@ var EventShipper = class {
520
524
  $context: this.context
521
525
  },
522
526
  attachments: accumulated.attachments,
523
- is_pending: ((_i = (_h = accumulated.isPending) != null ? _h : sticky.isPending) != null ? _i : true) !== false
527
+ is_pending: isPending
524
528
  };
525
529
  const url = `${this.baseUrl}events/track_partial`;
526
530
  if (this.debug) {
@@ -528,7 +532,8 @@ var EventShipper = class {
528
532
  eventId,
529
533
  eventName,
530
534
  userId,
531
- isPending: payload.is_pending,
535
+ convoId,
536
+ isPending,
532
537
  inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
533
538
  outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
534
539
  attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
@@ -560,7 +565,6 @@ var EventShipper = class {
560
565
  } finally {
561
566
  this.inFlight.delete(p);
562
567
  }
563
- const isPending = payload.is_pending;
564
568
  if (!isPending) {
565
569
  this.sticky.delete(eventId);
566
570
  }
@@ -713,6 +717,10 @@ var TraceShipper = class {
713
717
  }
714
718
  };
715
719
 
720
+ // ../core/dist/index.node.js
721
+ var import_async_hooks = require("async_hooks");
722
+ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
723
+
716
724
  // src/shipper.ts
717
725
  var EventShipper2 = class extends EventShipper {
718
726
  constructor(opts) {
@@ -1021,6 +1029,12 @@ type: ${name != null ? name : "UnknownError"}`;
1021
1029
  if (reasoningTokens != null && typeof reasoningTokens === "number" && reasoningTokens > 0) {
1022
1030
  llmAttrs.push(attrInt("gen_ai.usage.reasoning_tokens", reasoningTokens));
1023
1031
  }
1032
+ if (state.currentSystemPrompt) {
1033
+ llmAttrs.push(
1034
+ attrString("gen_ai.prompt.0.role", "system"),
1035
+ attrString("gen_ai.prompt.0.content", state.currentSystemPrompt)
1036
+ );
1037
+ }
1024
1038
  const llmParent = state.parentId && state.parentTaskSpanIds ? state.parentTaskSpanIds : state.currentRootSpan.ids;
1025
1039
  const llmSpan = traceShipper.startSpan({
1026
1040
  name: modelName,
@@ -1050,6 +1064,12 @@ type: ${name != null ? name : "UnknownError"}`;
1050
1064
  if (reasoningTokens != null && typeof reasoningTokens === "number" && reasoningTokens > 0) {
1051
1065
  llmAttrs.push(attrInt("gen_ai.usage.reasoning_tokens", reasoningTokens));
1052
1066
  }
1067
+ if (state.currentSystemPrompt) {
1068
+ llmAttrs.push(
1069
+ attrString("gen_ai.prompt.0.role", "system"),
1070
+ attrString("gen_ai.prompt.0.content", state.currentSystemPrompt)
1071
+ );
1072
+ }
1053
1073
  if (!state.parentTaskSpanIds) {
1054
1074
  traceShipper.endSpan(rootSpan, {
1055
1075
  error: "Missing strict parent task for child session"
@@ -1090,6 +1110,12 @@ type: ${name != null ? name : "UnknownError"}`;
1090
1110
  if (reasoningTokens != null && typeof reasoningTokens === "number" && reasoningTokens > 0) {
1091
1111
  rootAttrs.push(attrInt("gen_ai.usage.reasoning_tokens", reasoningTokens));
1092
1112
  }
1113
+ if (state.currentSystemPrompt) {
1114
+ rootAttrs.push(
1115
+ attrString("gen_ai.prompt.0.role", "system"),
1116
+ attrString("gen_ai.prompt.0.content", state.currentSystemPrompt)
1117
+ );
1118
+ }
1093
1119
  traceShipper.endSpan(rootSpan, {
1094
1120
  attributes: rootAttrs,
1095
1121
  error: errorForSpan
@@ -1408,6 +1434,29 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
1408
1434
  `[raindrop-ai/opencode-plugin] [error] Error in tool.execute.after hook: ${err instanceof Error ? err.message : String(err)}`
1409
1435
  );
1410
1436
  }
1437
+ },
1438
+ // ------------------------------------------------------------------
1439
+ // experimental.chat.system.transform — capture system prompt (read-only)
1440
+ // ------------------------------------------------------------------
1441
+ "experimental.chat.system.transform": async (input, output) => {
1442
+ try {
1443
+ if (!config.captureSystemPrompt) return;
1444
+ const sessionID = input.sessionID;
1445
+ if (!sessionID) return;
1446
+ let state = sessions.get(sessionID);
1447
+ if (!state) {
1448
+ state = createSessionState(sessionID);
1449
+ sessions.set(sessionID, state);
1450
+ }
1451
+ const MAX_SYSTEM_PROMPT_LENGTH = 32768;
1452
+ const TRUNCATION_MARKER = "\n...[truncated]";
1453
+ const joined = output.system.join("\n\n");
1454
+ state.currentSystemPrompt = joined.length > MAX_SYSTEM_PROMPT_LENGTH ? joined.slice(0, MAX_SYSTEM_PROMPT_LENGTH - TRUNCATION_MARKER.length) + TRUNCATION_MARKER : joined;
1455
+ } catch (err) {
1456
+ console.log(
1457
+ `[raindrop-ai/opencode-plugin] [error] Error in experimental.chat.system.transform hook: ${err instanceof Error ? err.message : String(err)}`
1458
+ );
1459
+ }
1411
1460
  }
1412
1461
  };
1413
1462
  }
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { existsSync, readFileSync } from "fs";
10
10
  import { homedir } from "os";
11
11
  import { join } from "path";
12
12
  function loadConfig(projectDirectory) {
13
- var _a, _b, _c, _d, _e, _f;
13
+ var _a, _b, _c, _d, _e, _f, _g;
14
14
  let merged = {};
15
15
  const configPaths = [
16
16
  join(homedir(), ".config", "opencode", "raindrop.json"),
@@ -39,6 +39,7 @@ function loadConfig(projectDirectory) {
39
39
  endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
40
40
  eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
41
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,
42
43
  eventMetadata
43
44
  };
44
45
  }
@@ -46,7 +47,7 @@ function loadConfig(projectDirectory) {
46
47
  // package.json
47
48
  var package_default = {
48
49
  name: "@raindrop-ai/opencode-plugin",
49
- version: "0.0.6",
50
+ version: "0.0.7",
50
51
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
51
52
  type: "module",
52
53
  main: "dist/index.cjs",
@@ -70,8 +71,8 @@ var package_default = {
70
71
  test: "cd tests && pnpm test"
71
72
  },
72
73
  peerDependencies: {
73
- "@opencode-ai/plugin": ">=1.2.0",
74
- "@opencode-ai/sdk": ">=1.2.0"
74
+ "@opencode-ai/plugin": ">=1.3.0",
75
+ "@opencode-ai/sdk": ">=1.3.0"
75
76
  },
76
77
  peerDependenciesMeta: {
77
78
  "@opencode-ai/sdk": {
@@ -80,8 +81,8 @@ var package_default = {
80
81
  },
81
82
  devDependencies: {
82
83
  "@raindrop-ai/core": "workspace:*",
83
- "@opencode-ai/plugin": "^1.2.0",
84
- "@opencode-ai/sdk": "^1.2.0",
84
+ "@opencode-ai/plugin": "^1.3.3",
85
+ "@opencode-ai/sdk": "^1.3.3",
85
86
  "@types/node": "^20.11.17",
86
87
  tsup: "^8.4.0",
87
88
  typescript: "^5.3.3"
@@ -111,7 +112,7 @@ var package_default = {
111
112
  var PLUGIN_NAME = package_default.name;
112
113
  var PLUGIN_VERSION = package_default.version;
113
114
 
114
- // ../core/dist/chunk-FTBZHS25.js
115
+ // ../core/dist/chunk-H6VSZSLN.js
115
116
  function getCrypto() {
116
117
  const c = globalThis.crypto;
117
118
  return c;
@@ -356,6 +357,7 @@ var EventShipper = class {
356
357
  console.log(`${this.prefix} queue patch`, {
357
358
  eventId,
358
359
  userId: patch.userId,
360
+ convoId: patch.convoId,
359
361
  eventName: patch.eventName,
360
362
  hasInput: typeof patch.input === "string" && patch.input.length > 0,
361
363
  hasOutput: typeof patch.output === "string" && patch.output.length > 0,
@@ -484,16 +486,18 @@ var EventShipper = class {
484
486
  return;
485
487
  }
486
488
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
489
+ const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
490
+ const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
487
491
  const payload = {
488
492
  event_id: eventId,
489
493
  user_id: userId,
490
494
  event: eventName,
491
- timestamp: (_f = accumulated.timestamp) != null ? _f : (/* @__PURE__ */ new Date()).toISOString(),
495
+ timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
492
496
  ai_data: {
493
497
  input: accumulated.input,
494
498
  output: accumulated.output,
495
499
  model: accumulated.model,
496
- convo_id: (_g = accumulated.convoId) != null ? _g : sticky.convoId
500
+ convo_id: convoId
497
501
  },
498
502
  properties: {
499
503
  ...restProperties,
@@ -501,7 +505,7 @@ var EventShipper = class {
501
505
  $context: this.context
502
506
  },
503
507
  attachments: accumulated.attachments,
504
- is_pending: ((_i = (_h = accumulated.isPending) != null ? _h : sticky.isPending) != null ? _i : true) !== false
508
+ is_pending: isPending
505
509
  };
506
510
  const url = `${this.baseUrl}events/track_partial`;
507
511
  if (this.debug) {
@@ -509,7 +513,8 @@ var EventShipper = class {
509
513
  eventId,
510
514
  eventName,
511
515
  userId,
512
- isPending: payload.is_pending,
516
+ convoId,
517
+ isPending,
513
518
  inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
514
519
  outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
515
520
  attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
@@ -541,7 +546,6 @@ var EventShipper = class {
541
546
  } finally {
542
547
  this.inFlight.delete(p);
543
548
  }
544
- const isPending = payload.is_pending;
545
549
  if (!isPending) {
546
550
  this.sticky.delete(eventId);
547
551
  }
@@ -694,6 +698,10 @@ var TraceShipper = class {
694
698
  }
695
699
  };
696
700
 
701
+ // ../core/dist/index.node.js
702
+ import { AsyncLocalStorage } from "async_hooks";
703
+ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
704
+
697
705
  // src/shipper.ts
698
706
  var EventShipper2 = class extends EventShipper {
699
707
  constructor(opts) {
@@ -1002,6 +1010,12 @@ type: ${name != null ? name : "UnknownError"}`;
1002
1010
  if (reasoningTokens != null && typeof reasoningTokens === "number" && reasoningTokens > 0) {
1003
1011
  llmAttrs.push(attrInt("gen_ai.usage.reasoning_tokens", reasoningTokens));
1004
1012
  }
1013
+ if (state.currentSystemPrompt) {
1014
+ llmAttrs.push(
1015
+ attrString("gen_ai.prompt.0.role", "system"),
1016
+ attrString("gen_ai.prompt.0.content", state.currentSystemPrompt)
1017
+ );
1018
+ }
1005
1019
  const llmParent = state.parentId && state.parentTaskSpanIds ? state.parentTaskSpanIds : state.currentRootSpan.ids;
1006
1020
  const llmSpan = traceShipper.startSpan({
1007
1021
  name: modelName,
@@ -1031,6 +1045,12 @@ type: ${name != null ? name : "UnknownError"}`;
1031
1045
  if (reasoningTokens != null && typeof reasoningTokens === "number" && reasoningTokens > 0) {
1032
1046
  llmAttrs.push(attrInt("gen_ai.usage.reasoning_tokens", reasoningTokens));
1033
1047
  }
1048
+ if (state.currentSystemPrompt) {
1049
+ llmAttrs.push(
1050
+ attrString("gen_ai.prompt.0.role", "system"),
1051
+ attrString("gen_ai.prompt.0.content", state.currentSystemPrompt)
1052
+ );
1053
+ }
1034
1054
  if (!state.parentTaskSpanIds) {
1035
1055
  traceShipper.endSpan(rootSpan, {
1036
1056
  error: "Missing strict parent task for child session"
@@ -1071,6 +1091,12 @@ type: ${name != null ? name : "UnknownError"}`;
1071
1091
  if (reasoningTokens != null && typeof reasoningTokens === "number" && reasoningTokens > 0) {
1072
1092
  rootAttrs.push(attrInt("gen_ai.usage.reasoning_tokens", reasoningTokens));
1073
1093
  }
1094
+ if (state.currentSystemPrompt) {
1095
+ rootAttrs.push(
1096
+ attrString("gen_ai.prompt.0.role", "system"),
1097
+ attrString("gen_ai.prompt.0.content", state.currentSystemPrompt)
1098
+ );
1099
+ }
1074
1100
  traceShipper.endSpan(rootSpan, {
1075
1101
  attributes: rootAttrs,
1076
1102
  error: errorForSpan
@@ -1389,6 +1415,29 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
1389
1415
  `[raindrop-ai/opencode-plugin] [error] Error in tool.execute.after hook: ${err instanceof Error ? err.message : String(err)}`
1390
1416
  );
1391
1417
  }
1418
+ },
1419
+ // ------------------------------------------------------------------
1420
+ // experimental.chat.system.transform — capture system prompt (read-only)
1421
+ // ------------------------------------------------------------------
1422
+ "experimental.chat.system.transform": async (input, output) => {
1423
+ try {
1424
+ if (!config.captureSystemPrompt) return;
1425
+ const sessionID = input.sessionID;
1426
+ if (!sessionID) return;
1427
+ let state = sessions.get(sessionID);
1428
+ if (!state) {
1429
+ state = createSessionState(sessionID);
1430
+ sessions.set(sessionID, state);
1431
+ }
1432
+ const MAX_SYSTEM_PROMPT_LENGTH = 32768;
1433
+ const TRUNCATION_MARKER = "\n...[truncated]";
1434
+ const joined = output.system.join("\n\n");
1435
+ state.currentSystemPrompt = joined.length > MAX_SYSTEM_PROMPT_LENGTH ? joined.slice(0, MAX_SYSTEM_PROMPT_LENGTH - TRUNCATION_MARKER.length) + TRUNCATION_MARKER : joined;
1436
+ } catch (err) {
1437
+ console.log(
1438
+ `[raindrop-ai/opencode-plugin] [error] Error in experimental.chat.system.transform hook: ${err instanceof Error ? err.message : String(err)}`
1439
+ );
1440
+ }
1392
1441
  }
1393
1442
  };
1394
1443
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/opencode-plugin",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Raindrop observability plugin for OpenCode — automatic session/event/span tracing",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -24,8 +24,8 @@
24
24
  "test": "cd tests && pnpm test"
25
25
  },
26
26
  "peerDependencies": {
27
- "@opencode-ai/plugin": ">=1.2.0",
28
- "@opencode-ai/sdk": ">=1.2.0"
27
+ "@opencode-ai/plugin": ">=1.3.0",
28
+ "@opencode-ai/sdk": ">=1.3.0"
29
29
  },
30
30
  "peerDependenciesMeta": {
31
31
  "@opencode-ai/sdk": {
@@ -34,8 +34,8 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@raindrop-ai/core": "workspace:*",
37
- "@opencode-ai/plugin": "^1.2.0",
38
- "@opencode-ai/sdk": "^1.2.0",
37
+ "@opencode-ai/plugin": "^1.3.3",
38
+ "@opencode-ai/sdk": "^1.3.3",
39
39
  "@types/node": "^20.11.17",
40
40
  "tsup": "^8.4.0",
41
41
  "typescript": "^5.3.3"