@raindrop-ai/opencode-plugin 0.0.13 → 0.0.14

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
@@ -24,7 +24,7 @@ __export(index_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
26
 
27
- // ../core/dist/chunk-U5HUTMR5.js
27
+ // ../core/dist/chunk-SK6EJEO7.js
28
28
  function getCrypto() {
29
29
  const c = globalThis.crypto;
30
30
  return c;
@@ -368,6 +368,25 @@ function mirrorPartialEventToLocalDebugger(event, options = {}) {
368
368
  }).catch(() => {
369
369
  });
370
370
  }
371
+ var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
372
+ var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
373
+ function isValidProjectIdSlug(value) {
374
+ return PROJECT_ID_SLUG_PATTERN.test(value);
375
+ }
376
+ function normalizeProjectId(raw, opts) {
377
+ if (typeof raw !== "string") return void 0;
378
+ const trimmed = raw.trim();
379
+ if (!trimmed) return void 0;
380
+ if (!isValidProjectIdSlug(trimmed) && opts.debug) {
381
+ console.warn(
382
+ `${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
383
+ );
384
+ }
385
+ return trimmed;
386
+ }
387
+ function projectIdHeaders(projectId) {
388
+ return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
389
+ }
371
390
  var SHUTDOWN_DEADLINE_MS = 1e4;
372
391
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
373
392
  function mergePatches(target, source) {
@@ -402,6 +421,10 @@ var EventShipper = class {
402
421
  if (this.debug && this.localDebuggerUrl) {
403
422
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
404
423
  }
424
+ this.projectId = normalizeProjectId(opts.projectId, {
425
+ debug: this.debug,
426
+ prefix: this.prefix
427
+ });
405
428
  const isNode = typeof process !== "undefined" && typeof process.version === "string";
406
429
  this.context = {
407
430
  library: {
@@ -420,6 +443,9 @@ var EventShipper = class {
420
443
  authHeaders() {
421
444
  return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
422
445
  }
446
+ requestHeaders() {
447
+ return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
448
+ }
423
449
  /**
424
450
  * Build the retry/timeout options for one POST, honoring the shutdown
425
451
  * deadline. Returns `null` when the shutdown drain window is exhausted —
@@ -549,7 +575,7 @@ var EventShipper = class {
549
575
  return;
550
576
  }
551
577
  try {
552
- await postJson(url, body, this.authHeaders(), opts);
578
+ await postJson(url, body, this.requestHeaders(), opts);
553
579
  } catch (err) {
554
580
  const msg = err instanceof Error ? err.message : String(err);
555
581
  rateLimitedLog(
@@ -585,7 +611,7 @@ var EventShipper = class {
585
611
  return;
586
612
  }
587
613
  try {
588
- await postJson(url, body, this.authHeaders(), opts);
614
+ await postJson(url, body, this.requestHeaders(), opts);
589
615
  } catch (err) {
590
616
  const msg = err instanceof Error ? err.message : String(err);
591
617
  rateLimitedLog(
@@ -681,7 +707,7 @@ var EventShipper = class {
681
707
  if (!isPending) this.sticky.delete(eventId);
682
708
  return;
683
709
  }
684
- const p = postJson(url, payload, this.authHeaders(), opts);
710
+ const p = postJson(url, payload, this.requestHeaders(), opts);
685
711
  this.inFlight.add(p);
686
712
  try {
687
713
  try {
@@ -828,6 +854,10 @@ var TraceShipper = class {
828
854
  if (this.debug && this.localDebuggerUrl) {
829
855
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
830
856
  }
857
+ this.projectId = normalizeProjectId(opts.projectId, {
858
+ debug: this.debug,
859
+ prefix: this.prefix
860
+ });
831
861
  this.transformSpanHook = opts.transformSpan;
832
862
  this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
833
863
  this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
@@ -904,6 +934,9 @@ var TraceShipper = class {
904
934
  authHeaders() {
905
935
  return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
906
936
  }
937
+ requestHeaders() {
938
+ return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
939
+ }
907
940
  startSpan(args) {
908
941
  var _a, _b;
909
942
  const ids = createSpanIds(args.parent);
@@ -1035,7 +1068,7 @@ var TraceShipper = class {
1035
1068
  endpoint: url
1036
1069
  });
1037
1070
  }
1038
- const p = postJson(url, body, this.authHeaders(), opts);
1071
+ const p = postJson(url, body, this.requestHeaders(), opts);
1039
1072
  this.inFlight.add(p);
1040
1073
  try {
1041
1074
  try {
@@ -1110,7 +1143,7 @@ var import_node_fs = require("fs");
1110
1143
  var import_node_os = require("os");
1111
1144
  var import_node_path = require("path");
1112
1145
  function loadConfig(projectDirectory) {
1113
- var _a, _b, _c, _d, _e, _f, _g;
1146
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1114
1147
  let merged = {};
1115
1148
  const configPaths = [
1116
1149
  (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "opencode", "raindrop.json"),
@@ -1137,9 +1170,10 @@ function loadConfig(projectDirectory) {
1137
1170
  return {
1138
1171
  writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
1139
1172
  endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
1140
- eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
1141
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
1142
- captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
1173
+ projectId: (_e = process.env["RAINDROP_PROJECT_ID"]) != null ? _e : merged.project_id,
1174
+ eventName: (_f = merged.event_name) != null ? _f : "opencode_session",
1175
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_g = merged.debug) != null ? _g : false,
1176
+ captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_h = merged.capture_system_prompt) != null ? _h : false,
1143
1177
  eventMetadata,
1144
1178
  localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
1145
1179
  };
@@ -1158,7 +1192,7 @@ function resolveLocalWorkshopUrl(fileValue) {
1158
1192
  // package.json
1159
1193
  var package_default = {
1160
1194
  name: "@raindrop-ai/opencode-plugin",
1161
- version: "0.0.13",
1195
+ version: "0.0.14",
1162
1196
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
1163
1197
  type: "module",
1164
1198
  main: "dist/index.js",
@@ -2199,12 +2233,14 @@ async function plugin(input) {
2199
2233
  writeKey: config.writeKey,
2200
2234
  endpoint: config.endpoint,
2201
2235
  debug: config.debug,
2236
+ projectId: config.projectId,
2202
2237
  localDebuggerUrl: config.localWorkshopUrl
2203
2238
  });
2204
2239
  const traceShipper = new TraceShipper2({
2205
2240
  writeKey: config.writeKey,
2206
2241
  endpoint: config.endpoint,
2207
2242
  debug: config.debug,
2243
+ projectId: config.projectId,
2208
2244
  localDebuggerUrl: config.localWorkshopUrl
2209
2245
  });
2210
2246
  const worktree = (_a = input.worktree) != null ? _a : input.directory;
package/dist/index.js CHANGED
@@ -5,7 +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
- // ../core/dist/chunk-U5HUTMR5.js
8
+ // ../core/dist/chunk-SK6EJEO7.js
9
9
  function getCrypto() {
10
10
  const c = globalThis.crypto;
11
11
  return c;
@@ -349,6 +349,25 @@ function mirrorPartialEventToLocalDebugger(event, options = {}) {
349
349
  }).catch(() => {
350
350
  });
351
351
  }
352
+ var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
353
+ var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
354
+ function isValidProjectIdSlug(value) {
355
+ return PROJECT_ID_SLUG_PATTERN.test(value);
356
+ }
357
+ function normalizeProjectId(raw, opts) {
358
+ if (typeof raw !== "string") return void 0;
359
+ const trimmed = raw.trim();
360
+ if (!trimmed) return void 0;
361
+ if (!isValidProjectIdSlug(trimmed) && opts.debug) {
362
+ console.warn(
363
+ `${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
364
+ );
365
+ }
366
+ return trimmed;
367
+ }
368
+ function projectIdHeaders(projectId) {
369
+ return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
370
+ }
352
371
  var SHUTDOWN_DEADLINE_MS = 1e4;
353
372
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
354
373
  function mergePatches(target, source) {
@@ -383,6 +402,10 @@ var EventShipper = class {
383
402
  if (this.debug && this.localDebuggerUrl) {
384
403
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
385
404
  }
405
+ this.projectId = normalizeProjectId(opts.projectId, {
406
+ debug: this.debug,
407
+ prefix: this.prefix
408
+ });
386
409
  const isNode = typeof process !== "undefined" && typeof process.version === "string";
387
410
  this.context = {
388
411
  library: {
@@ -401,6 +424,9 @@ var EventShipper = class {
401
424
  authHeaders() {
402
425
  return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
403
426
  }
427
+ requestHeaders() {
428
+ return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
429
+ }
404
430
  /**
405
431
  * Build the retry/timeout options for one POST, honoring the shutdown
406
432
  * deadline. Returns `null` when the shutdown drain window is exhausted —
@@ -530,7 +556,7 @@ var EventShipper = class {
530
556
  return;
531
557
  }
532
558
  try {
533
- await postJson(url, body, this.authHeaders(), opts);
559
+ await postJson(url, body, this.requestHeaders(), opts);
534
560
  } catch (err) {
535
561
  const msg = err instanceof Error ? err.message : String(err);
536
562
  rateLimitedLog(
@@ -566,7 +592,7 @@ var EventShipper = class {
566
592
  return;
567
593
  }
568
594
  try {
569
- await postJson(url, body, this.authHeaders(), opts);
595
+ await postJson(url, body, this.requestHeaders(), opts);
570
596
  } catch (err) {
571
597
  const msg = err instanceof Error ? err.message : String(err);
572
598
  rateLimitedLog(
@@ -662,7 +688,7 @@ var EventShipper = class {
662
688
  if (!isPending) this.sticky.delete(eventId);
663
689
  return;
664
690
  }
665
- const p = postJson(url, payload, this.authHeaders(), opts);
691
+ const p = postJson(url, payload, this.requestHeaders(), opts);
666
692
  this.inFlight.add(p);
667
693
  try {
668
694
  try {
@@ -809,6 +835,10 @@ var TraceShipper = class {
809
835
  if (this.debug && this.localDebuggerUrl) {
810
836
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
811
837
  }
838
+ this.projectId = normalizeProjectId(opts.projectId, {
839
+ debug: this.debug,
840
+ prefix: this.prefix
841
+ });
812
842
  this.transformSpanHook = opts.transformSpan;
813
843
  this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
814
844
  this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
@@ -885,6 +915,9 @@ var TraceShipper = class {
885
915
  authHeaders() {
886
916
  return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
887
917
  }
918
+ requestHeaders() {
919
+ return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
920
+ }
888
921
  startSpan(args) {
889
922
  var _a, _b;
890
923
  const ids = createSpanIds(args.parent);
@@ -1016,7 +1049,7 @@ var TraceShipper = class {
1016
1049
  endpoint: url
1017
1050
  });
1018
1051
  }
1019
- const p = postJson(url, body, this.authHeaders(), opts);
1052
+ const p = postJson(url, body, this.requestHeaders(), opts);
1020
1053
  this.inFlight.add(p);
1021
1054
  try {
1022
1055
  try {
@@ -1091,7 +1124,7 @@ import { existsSync, readFileSync } from "fs";
1091
1124
  import { homedir } from "os";
1092
1125
  import { join } from "path";
1093
1126
  function loadConfig(projectDirectory) {
1094
- var _a, _b, _c, _d, _e, _f, _g;
1127
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1095
1128
  let merged = {};
1096
1129
  const configPaths = [
1097
1130
  join(homedir(), ".config", "opencode", "raindrop.json"),
@@ -1118,9 +1151,10 @@ function loadConfig(projectDirectory) {
1118
1151
  return {
1119
1152
  writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
1120
1153
  endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
1121
- eventName: (_e = merged.event_name) != null ? _e : "opencode_session",
1122
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
1123
- captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
1154
+ projectId: (_e = process.env["RAINDROP_PROJECT_ID"]) != null ? _e : merged.project_id,
1155
+ eventName: (_f = merged.event_name) != null ? _f : "opencode_session",
1156
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_g = merged.debug) != null ? _g : false,
1157
+ captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_h = merged.capture_system_prompt) != null ? _h : false,
1124
1158
  eventMetadata,
1125
1159
  localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
1126
1160
  };
@@ -1139,7 +1173,7 @@ function resolveLocalWorkshopUrl(fileValue) {
1139
1173
  // package.json
1140
1174
  var package_default = {
1141
1175
  name: "@raindrop-ai/opencode-plugin",
1142
- version: "0.0.13",
1176
+ version: "0.0.14",
1143
1177
  description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
1144
1178
  type: "module",
1145
1179
  main: "dist/index.js",
@@ -2180,12 +2214,14 @@ async function plugin(input) {
2180
2214
  writeKey: config.writeKey,
2181
2215
  endpoint: config.endpoint,
2182
2216
  debug: config.debug,
2217
+ projectId: config.projectId,
2183
2218
  localDebuggerUrl: config.localWorkshopUrl
2184
2219
  });
2185
2220
  const traceShipper = new TraceShipper2({
2186
2221
  writeKey: config.writeKey,
2187
2222
  endpoint: config.endpoint,
2188
2223
  debug: config.debug,
2224
+ projectId: config.projectId,
2189
2225
  localDebuggerUrl: config.localWorkshopUrl
2190
2226
  });
2191
2227
  const worktree = (_a = input.worktree) != null ? _a : input.directory;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/opencode-plugin",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Raindrop observability plugin for OpenCode — automatic session/event/span tracing",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,7 +42,7 @@
42
42
  "@types/node": "^20.11.17",
43
43
  "tsup": "^8.4.0",
44
44
  "typescript": "^5.3.3",
45
- "@raindrop-ai/core": "0.0.3"
45
+ "@raindrop-ai/core": "0.0.4"
46
46
  },
47
47
  "tsup": {
48
48
  "entry": [