@raindrop-ai/pi-agent 0.0.2 → 0.0.3

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.
@@ -25,147 +25,7 @@ __export(extension_exports, {
25
25
  });
26
26
  module.exports = __toCommonJS(extension_exports);
27
27
 
28
- // src/internal/config.ts
29
- var import_node_fs = require("fs");
30
- var import_node_os = require("os");
31
- var import_node_path = require("path");
32
- function getPiAgentDirectory() {
33
- var _a;
34
- return (_a = process.env["PI_CODING_AGENT_DIR"]) != null ? _a : (0, import_node_path.join)((0, import_node_os.homedir)(), ".pi", "agent");
35
- }
36
- function loadConfig(projectDirectory) {
37
- var _a, _b, _c, _d, _e, _f, _g;
38
- let merged = {};
39
- const configPaths = [
40
- (0, import_node_path.join)(getPiAgentDirectory(), "raindrop.json"),
41
- (0, import_node_path.join)(projectDirectory, ".pi", "raindrop.json")
42
- ];
43
- for (const configPath of configPaths) {
44
- try {
45
- if ((0, import_node_fs.existsSync)(configPath)) {
46
- const content = (0, import_node_fs.readFileSync)(configPath, "utf-8");
47
- const parsed = JSON.parse(content);
48
- merged = { ...merged, ...parsed };
49
- }
50
- } catch (e) {
51
- }
52
- }
53
- let eventMetadata;
54
- const envMeta = process.env["RAINDROP_EVENT_METADATA"];
55
- if (envMeta) {
56
- try {
57
- eventMetadata = JSON.parse(envMeta);
58
- } catch (e) {
59
- }
60
- }
61
- return {
62
- writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
63
- endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
64
- eventName: (_e = merged.event_name) != null ? _e : "pi_session",
65
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
66
- captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
67
- eventMetadata
68
- };
69
- }
70
-
71
- // package.json
72
- var package_default = {
73
- name: "@raindrop-ai/pi-agent",
74
- version: "0.0.2",
75
- description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
76
- type: "module",
77
- license: "MIT",
78
- repository: {
79
- type: "git",
80
- url: "git+https://github.com/raindrop-ai/raindrop-js.git",
81
- directory: "packages/pi-agent"
82
- },
83
- homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/pi-agent#readme",
84
- bugs: {
85
- url: "https://github.com/raindrop-ai/raindrop-js/issues"
86
- },
87
- keywords: [
88
- "pi-package",
89
- "raindrop",
90
- "pi-agent",
91
- "observability",
92
- "tracing"
93
- ],
94
- exports: {
95
- ".": {
96
- types: "./dist/index.d.ts",
97
- import: "./dist/index.js",
98
- require: "./dist/index.cjs"
99
- },
100
- "./extension": {
101
- types: "./dist/extension.d.ts",
102
- import: "./dist/extension.js",
103
- require: "./dist/extension.cjs"
104
- }
105
- },
106
- pi: {
107
- extensions: [
108
- "./dist/extension.js"
109
- ]
110
- },
111
- sideEffects: false,
112
- files: [
113
- "dist/**",
114
- "README.md"
115
- ],
116
- scripts: {
117
- build: "tsup",
118
- dev: "tsup --watch",
119
- clean: "rm -rf dist",
120
- test: "vitest run",
121
- "test:watch": "vitest"
122
- },
123
- peerDependencies: {
124
- "@mariozechner/pi-agent-core": ">=0.60.0",
125
- "@mariozechner/pi-coding-agent": ">=0.65.2"
126
- },
127
- peerDependenciesMeta: {
128
- "@mariozechner/pi-coding-agent": {
129
- optional: true
130
- }
131
- },
132
- devDependencies: {
133
- "@raindrop-ai/core": "workspace:*",
134
- "@mariozechner/pi-agent-core": "^0.66.0",
135
- "@mariozechner/pi-coding-agent": "^0.66.0",
136
- "@types/node": "^20.11.17",
137
- msw: "^2.12.7",
138
- tsup: "^8.5.1",
139
- typescript: "^5.7.3",
140
- vitest: "^2.1.9"
141
- },
142
- tsup: {
143
- entry: [
144
- "src/index.ts",
145
- "src/extension.ts"
146
- ],
147
- format: [
148
- "cjs",
149
- "esm"
150
- ],
151
- dts: {
152
- resolve: true
153
- },
154
- clean: true,
155
- noExternal: [
156
- "@raindrop-ai/core"
157
- ]
158
- },
159
- publishConfig: {
160
- access: "public"
161
- }
162
- };
163
-
164
- // src/version.ts
165
- var libraryName = package_default.name;
166
- var libraryVersion = package_default.version;
167
-
168
- // ../core/dist/chunk-4UCYIEH4.js
28
+ // ../core/dist/chunk-OLYXZCOK.js
169
29
  function getCrypto() {
170
30
  const c = globalThis.crypto;
171
31
  return c;
@@ -358,6 +218,91 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
358
218
  ]
359
219
  };
360
220
  }
221
+ var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
222
+ var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
223
+ var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
224
+ function readEnvVar(name) {
225
+ var _a;
226
+ try {
227
+ const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
228
+ if (env && typeof env[name] === "string" && env[name].length > 0) {
229
+ return env[name];
230
+ }
231
+ } catch (e) {
232
+ }
233
+ return void 0;
234
+ }
235
+ function readWorkshopEnv() {
236
+ const raw = readEnvVar(WORKSHOP_ENV_VAR);
237
+ if (raw === void 0) return void 0;
238
+ const trimmed = raw.trim();
239
+ if (trimmed.length === 0) return void 0;
240
+ if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
241
+ if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
242
+ if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
243
+ return void 0;
244
+ }
245
+ function isLocalDevHost(hostname2) {
246
+ if (!hostname2) return false;
247
+ if (hostname2 === "localhost" || hostname2 === "127.0.0.1" || hostname2 === "0.0.0.0" || hostname2 === "::1") {
248
+ return true;
249
+ }
250
+ if (hostname2.endsWith(".localhost")) return true;
251
+ return false;
252
+ }
253
+ function readRuntimeHostname() {
254
+ try {
255
+ const loc = globalThis == null ? void 0 : globalThis.location;
256
+ if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
257
+ return loc.hostname;
258
+ }
259
+ } catch (e) {
260
+ }
261
+ return void 0;
262
+ }
263
+ function shouldAutoEnableLocalWorkshop() {
264
+ if (isLocalDevHost(readRuntimeHostname())) return true;
265
+ if (readEnvVar("NODE_ENV") === "development") return true;
266
+ return false;
267
+ }
268
+ function resolveLocalDebuggerBaseUrl(baseUrl) {
269
+ var _a, _b, _c;
270
+ if (baseUrl === null) return null;
271
+ if (typeof baseUrl === "string" && baseUrl.length > 0) {
272
+ return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
273
+ }
274
+ const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
275
+ if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
276
+ const workshopEnv = readWorkshopEnv();
277
+ if (workshopEnv === "disable") return null;
278
+ if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
279
+ if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
280
+ if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
281
+ return null;
282
+ }
283
+ function mirrorTraceExportToLocalDebugger(body, options = {}) {
284
+ var _a;
285
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
286
+ if (!baseUrl) return;
287
+ void postJson(`${baseUrl}traces`, body, {}, {
288
+ maxAttempts: 1,
289
+ debug: (_a = options.debug) != null ? _a : false,
290
+ sdkName: options.sdkName
291
+ }).catch(() => {
292
+ });
293
+ }
294
+ function mirrorPartialEventToLocalDebugger(event, options = {}) {
295
+ var _a;
296
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
297
+ if (!baseUrl) return;
298
+ const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
299
+ void postJson(`${baseUrl}events/track_partial`, event, headers, {
300
+ maxAttempts: 1,
301
+ debug: (_a = options.debug) != null ? _a : false,
302
+ sdkName: options.sdkName
303
+ }).catch(() => {
304
+ });
305
+ }
361
306
  function mergePatches(target, source) {
362
307
  var _a, _b, _c, _d;
363
308
  const out = { ...target, ...source };
@@ -375,7 +320,7 @@ var EventShipper = class {
375
320
  this.sticky = /* @__PURE__ */ new Map();
376
321
  this.timers = /* @__PURE__ */ new Map();
377
322
  this.inFlight = /* @__PURE__ */ new Set();
378
- var _a, _b, _c, _d, _e, _f, _g;
323
+ var _a, _b, _c, _d, _e, _f, _g, _h;
379
324
  this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
380
325
  this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
381
326
  this.enabled = opts.enabled !== false;
@@ -384,11 +329,15 @@ var EventShipper = class {
384
329
  this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
385
330
  this.prefix = `[raindrop-ai/${this.sdkName}]`;
386
331
  this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
332
+ this.localDebuggerUrl = (_f = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _f : void 0;
333
+ if (this.debug && this.localDebuggerUrl) {
334
+ console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
335
+ }
387
336
  const isNode = typeof process !== "undefined" && typeof process.version === "string";
388
337
  this.context = {
389
338
  library: {
390
- name: (_f = opts.libraryName) != null ? _f : "@raindrop-ai/core",
391
- version: (_g = opts.libraryVersion) != null ? _g : "0.0.0"
339
+ name: (_g = opts.libraryName) != null ? _g : "@raindrop-ai/core",
340
+ version: (_h = opts.libraryVersion) != null ? _h : "0.0.0"
392
341
  },
393
342
  metadata: {
394
343
  jsRuntime: isNode ? "node" : "web",
@@ -474,6 +423,7 @@ var EventShipper = class {
474
423
  }
475
424
  }
476
425
  ];
426
+ if (!this.writeKey) return;
477
427
  const url = `${this.baseUrl}signals/track`;
478
428
  try {
479
429
  await postJson(url, body, this.authHeaders(), {
@@ -504,6 +454,7 @@ var EventShipper = class {
504
454
  traits: (_a = user.traits) != null ? _a : {}
505
455
  };
506
456
  });
457
+ if (!this.writeKey) return;
507
458
  if (body.length === 0) return;
508
459
  const url = `${this.baseUrl}users/identify`;
509
460
  try {
@@ -580,6 +531,18 @@ var EventShipper = class {
580
531
  endpoint: url
581
532
  });
582
533
  }
534
+ if (this.localDebuggerUrl) {
535
+ mirrorPartialEventToLocalDebugger(payload, {
536
+ baseUrl: this.localDebuggerUrl,
537
+ writeKey: this.writeKey,
538
+ debug: this.debug,
539
+ sdkName: this.sdkName
540
+ });
541
+ }
542
+ if (!this.writeKey) {
543
+ if (!isPending) this.sticky.delete(eventId);
544
+ return;
545
+ }
583
546
  const p = postJson(url, payload, this.authHeaders(), {
584
547
  maxAttempts: 3,
585
548
  debug: this.debug,
@@ -604,28 +567,11 @@ var EventShipper = class {
604
567
  }
605
568
  }
606
569
  };
607
- var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
608
- function resolveLocalDebuggerBaseUrl(baseUrl) {
609
- var _a, _b, _c;
610
- 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;
611
- return resolved ? (_c = formatEndpoint(resolved)) != null ? _c : null : null;
612
- }
613
- function mirrorTraceExportToLocalDebugger(body, options = {}) {
614
- var _a;
615
- const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
616
- if (!baseUrl) return;
617
- void postJson(`${baseUrl}traces`, body, {}, {
618
- maxAttempts: 1,
619
- debug: (_a = options.debug) != null ? _a : false,
620
- sdkName: options.sdkName
621
- }).catch(() => {
622
- });
623
- }
624
570
  var TraceShipper = class {
625
571
  constructor(opts) {
626
572
  this.queue = [];
627
573
  this.inFlight = /* @__PURE__ */ new Set();
628
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
574
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
629
575
  this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
630
576
  this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
631
577
  this.enabled = opts.enabled !== false;
@@ -638,12 +584,9 @@ var TraceShipper = class {
638
584
  this.prefix = `[raindrop-ai/${this.sdkName}]`;
639
585
  this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
640
586
  this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
641
- const localDebugger = typeof process !== "undefined" ? (_i = process.env) == null ? void 0 : _i.RAINDROP_LOCAL_DEBUGGER : void 0;
642
- if (localDebugger) {
643
- this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(localDebugger)) != null ? _j : void 0;
644
- if (this.debug) {
645
- console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
646
- }
587
+ this.localDebuggerUrl = (_i = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _i : void 0;
588
+ if (this.debug && this.localDebuggerUrl) {
589
+ console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
647
590
  }
648
591
  }
649
592
  isDebugEnabled() {
@@ -771,6 +714,7 @@ var TraceShipper = class {
771
714
  }
772
715
  while (this.queue.length > 0) {
773
716
  const batch = this.queue.splice(0, this.maxBatchSize);
717
+ if (!this.writeKey) continue;
774
718
  const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
775
719
  const url = `${this.baseUrl}traces`;
776
720
  if (this.debug) {
@@ -813,6 +757,157 @@ var TraceShipper = class {
813
757
  var import_async_hooks = require("async_hooks");
814
758
  globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
815
759
 
760
+ // src/internal/config.ts
761
+ var import_node_fs = require("fs");
762
+ var import_node_os = require("os");
763
+ var import_node_path = require("path");
764
+ function getPiAgentDirectory() {
765
+ var _a;
766
+ return (_a = process.env["PI_CODING_AGENT_DIR"]) != null ? _a : (0, import_node_path.join)((0, import_node_os.homedir)(), ".pi", "agent");
767
+ }
768
+ function loadConfig(projectDirectory) {
769
+ var _a, _b, _c, _d, _e, _f, _g;
770
+ let merged = {};
771
+ const configPaths = [
772
+ (0, import_node_path.join)(getPiAgentDirectory(), "raindrop.json"),
773
+ (0, import_node_path.join)(projectDirectory, ".pi", "raindrop.json")
774
+ ];
775
+ for (const configPath of configPaths) {
776
+ try {
777
+ if ((0, import_node_fs.existsSync)(configPath)) {
778
+ const content = (0, import_node_fs.readFileSync)(configPath, "utf-8");
779
+ const parsed = JSON.parse(content);
780
+ merged = { ...merged, ...parsed };
781
+ }
782
+ } catch (e) {
783
+ }
784
+ }
785
+ let eventMetadata;
786
+ const envMeta = process.env["RAINDROP_EVENT_METADATA"];
787
+ if (envMeta) {
788
+ try {
789
+ eventMetadata = JSON.parse(envMeta);
790
+ } catch (e) {
791
+ }
792
+ }
793
+ return {
794
+ writeKey: (_b = (_a = process.env["RAINDROP_WRITE_KEY"]) != null ? _a : merged.write_key) != null ? _b : "",
795
+ endpoint: (_d = (_c = process.env["RAINDROP_API_URL"]) != null ? _c : merged.api_url) != null ? _d : "https://api.raindrop.ai/v1",
796
+ eventName: (_e = merged.event_name) != null ? _e : "pi_session",
797
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
798
+ captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
799
+ eventMetadata,
800
+ localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
801
+ };
802
+ }
803
+ function resolveLocalWorkshopUrl(fileValue) {
804
+ const envValue = process.env["RAINDROP_LOCAL_WORKSHOP_URL"];
805
+ if (envValue !== void 0) {
806
+ if (envValue === "" || envValue.toLowerCase() === "null" || envValue.toLowerCase() === "false") {
807
+ return null;
808
+ }
809
+ return envValue;
810
+ }
811
+ return fileValue;
812
+ }
813
+
814
+ // package.json
815
+ var package_default = {
816
+ name: "@raindrop-ai/pi-agent",
817
+ version: "0.0.3",
818
+ description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
819
+ type: "module",
820
+ license: "MIT",
821
+ repository: {
822
+ type: "git",
823
+ url: "git+https://github.com/raindrop-ai/raindrop-js.git",
824
+ directory: "packages/pi-agent"
825
+ },
826
+ homepage: "https://github.com/raindrop-ai/raindrop-js/tree/main/packages/pi-agent#readme",
827
+ bugs: {
828
+ url: "https://github.com/raindrop-ai/raindrop-js/issues"
829
+ },
830
+ keywords: [
831
+ "pi-package",
832
+ "raindrop",
833
+ "pi-agent",
834
+ "observability",
835
+ "tracing"
836
+ ],
837
+ exports: {
838
+ ".": {
839
+ types: "./dist/index.d.ts",
840
+ import: "./dist/index.js",
841
+ require: "./dist/index.cjs"
842
+ },
843
+ "./extension": {
844
+ types: "./dist/extension.d.ts",
845
+ import: "./dist/extension.js",
846
+ require: "./dist/extension.cjs"
847
+ }
848
+ },
849
+ pi: {
850
+ extensions: [
851
+ "./dist/extension.js"
852
+ ]
853
+ },
854
+ sideEffects: false,
855
+ files: [
856
+ "dist/**",
857
+ "README.md"
858
+ ],
859
+ scripts: {
860
+ build: "tsup",
861
+ dev: "tsup --watch",
862
+ clean: "rm -rf dist",
863
+ test: "vitest run",
864
+ "test:watch": "vitest"
865
+ },
866
+ peerDependencies: {
867
+ "@mariozechner/pi-agent-core": ">=0.60.0",
868
+ "@mariozechner/pi-coding-agent": ">=0.65.2"
869
+ },
870
+ peerDependenciesMeta: {
871
+ "@mariozechner/pi-coding-agent": {
872
+ optional: true
873
+ }
874
+ },
875
+ devDependencies: {
876
+ "@raindrop-ai/core": "workspace:*",
877
+ "@mariozechner/pi-agent-core": "^0.66.0",
878
+ "@mariozechner/pi-coding-agent": "^0.66.0",
879
+ "@types/node": "^20.11.17",
880
+ msw: "^2.12.7",
881
+ tsup: "^8.5.1",
882
+ typescript: "^5.7.3",
883
+ vitest: "^2.1.9"
884
+ },
885
+ tsup: {
886
+ entry: [
887
+ "src/index.ts",
888
+ "src/extension.ts"
889
+ ],
890
+ format: [
891
+ "cjs",
892
+ "esm"
893
+ ],
894
+ dts: {
895
+ resolve: true
896
+ },
897
+ clean: true,
898
+ noExternal: [
899
+ "@raindrop-ai/core"
900
+ ]
901
+ },
902
+ publishConfig: {
903
+ access: "public"
904
+ }
905
+ };
906
+
907
+ // src/version.ts
908
+ var libraryName = package_default.name;
909
+ var libraryVersion = package_default.version;
910
+
816
911
  // src/internal/shipper.ts
817
912
  var EventShipper2 = class extends EventShipper {
818
913
  constructor(opts) {
@@ -1283,25 +1378,33 @@ function extension(pi) {
1283
1378
  console.log(`[raindrop-ai/pi-agent] [${level}] ${message}`);
1284
1379
  }
1285
1380
  appLog("info", `Loading ${PLUGIN_NAME} v${libraryVersion}`);
1286
- if (!config.writeKey) {
1381
+ const resolvedLocalUrl = resolveLocalDebuggerBaseUrl(config.localWorkshopUrl);
1382
+ const hasLocalDestination = resolvedLocalUrl !== null;
1383
+ if (!config.writeKey && !hasLocalDestination) {
1287
1384
  appLog(
1288
1385
  "warn",
1289
- "RAINDROP_WRITE_KEY not set \u2014 Raindrop tracing disabled. Set it in your environment or in ~/.pi/agent/raindrop.json."
1386
+ "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."
1290
1387
  );
1291
1388
  return;
1292
1389
  }
1293
1390
  if (config.debug) {
1294
- appLog("info", `Raindrop tracing enabled (endpoint: ${config.endpoint})`);
1391
+ const destinations = [
1392
+ config.writeKey ? `cloud (${config.endpoint})` : null,
1393
+ resolvedLocalUrl ? `local Workshop (${resolvedLocalUrl})` : null
1394
+ ].filter(Boolean);
1395
+ appLog("info", `Raindrop tracing enabled \u2014 destinations: ${destinations.join(", ")}`);
1295
1396
  }
1296
1397
  const eventShipper = new EventShipper2({
1297
1398
  writeKey: config.writeKey,
1298
1399
  endpoint: config.endpoint,
1299
- debug: config.debug
1400
+ debug: config.debug,
1401
+ localDebuggerUrl: config.localWorkshopUrl
1300
1402
  });
1301
1403
  const traceShipper = new TraceShipper2({
1302
1404
  writeKey: config.writeKey,
1303
1405
  endpoint: config.endpoint,
1304
- debug: config.debug
1406
+ debug: config.debug,
1407
+ localDebuggerUrl: config.localWorkshopUrl
1305
1408
  });
1306
1409
  registerTracing(pi, config, eventShipper, traceShipper);
1307
1410
  }
@@ -1,5 +1,5 @@
1
1
  import { ExtensionAPI } from '@mariozechner/pi-coding-agent';
2
- import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-npTVS9Mf.cjs';
2
+ import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-CtwaEReY.cjs';
3
3
 
4
4
  interface EventMetadata {
5
5
  userId?: string;
@@ -13,6 +13,13 @@ interface RaindropExtensionConfig {
13
13
  debug: boolean;
14
14
  captureSystemPrompt: boolean;
15
15
  eventMetadata?: EventMetadata;
16
+ /**
17
+ * Explicit Workshop / local debugger URL forwarded to both shippers as their
18
+ * `localDebuggerUrl`. `null` opts out (overrides `RAINDROP_LOCAL_DEBUGGER` /
19
+ * `RAINDROP_WORKSHOP` env vars and auto-detect). `undefined` falls through to
20
+ * the env / auto-detect resolution in `@raindrop-ai/core`.
21
+ */
22
+ localWorkshopUrl?: string | null;
16
23
  }
17
24
 
18
25
  declare class EventShipper extends EventShipper$1 {
@@ -49,6 +56,9 @@ declare function registerTracing(pi: ExtensionAPI, config: RaindropExtensionConf
49
56
  * RAINDROP_API_URL — custom endpoint (default: https://api.raindrop.ai/v1)
50
57
  * RAINDROP_DEBUG — enable debug logging
51
58
  * RAINDROP_CAPTURE_SYSTEM_PROMPT — capture system prompts in traces
59
+ * RAINDROP_LOCAL_WORKSHOP_URL — mirror to a local Raindrop Workshop daemon
60
+ * in addition to the cloud endpoint. Pass `null`, `""`, or `"false"` to
61
+ * opt out of all auto-detection.
52
62
  *
53
63
  * Config file locations:
54
64
  * ~/.pi/agent/raindrop.json (global)
@@ -1,5 +1,5 @@
1
1
  import { ExtensionAPI } from '@mariozechner/pi-coding-agent';
2
- import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-npTVS9Mf.js';
2
+ import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-CtwaEReY.js';
3
3
 
4
4
  interface EventMetadata {
5
5
  userId?: string;
@@ -13,6 +13,13 @@ interface RaindropExtensionConfig {
13
13
  debug: boolean;
14
14
  captureSystemPrompt: boolean;
15
15
  eventMetadata?: EventMetadata;
16
+ /**
17
+ * Explicit Workshop / local debugger URL forwarded to both shippers as their
18
+ * `localDebuggerUrl`. `null` opts out (overrides `RAINDROP_LOCAL_DEBUGGER` /
19
+ * `RAINDROP_WORKSHOP` env vars and auto-detect). `undefined` falls through to
20
+ * the env / auto-detect resolution in `@raindrop-ai/core`.
21
+ */
22
+ localWorkshopUrl?: string | null;
16
23
  }
17
24
 
18
25
  declare class EventShipper extends EventShipper$1 {
@@ -49,6 +56,9 @@ declare function registerTracing(pi: ExtensionAPI, config: RaindropExtensionConf
49
56
  * RAINDROP_API_URL — custom endpoint (default: https://api.raindrop.ai/v1)
50
57
  * RAINDROP_DEBUG — enable debug logging
51
58
  * RAINDROP_CAPTURE_SYSTEM_PROMPT — capture system prompts in traces
59
+ * RAINDROP_LOCAL_WORKSHOP_URL — mirror to a local Raindrop Workshop daemon
60
+ * in addition to the cloud endpoint. Pass `null`, `""`, or `"false"` to
61
+ * opt out of all auto-detection.
52
62
  *
53
63
  * Config file locations:
54
64
  * ~/.pi/agent/raindrop.json (global)
package/dist/extension.js CHANGED
@@ -10,9 +10,10 @@ import {
10
10
  getUsername,
11
11
  libraryVersion,
12
12
  nowUnixNanoString,
13
+ resolveLocalDebuggerBaseUrl,
13
14
  safeStringify,
14
15
  truncate
15
- } from "./chunk-LZIGXU2D.js";
16
+ } from "./chunk-MHIMKMK7.js";
16
17
 
17
18
  // src/internal/config.ts
18
19
  import { existsSync, readFileSync } from "fs";
@@ -53,9 +54,20 @@ function loadConfig(projectDirectory) {
53
54
  eventName: (_e = merged.event_name) != null ? _e : "pi_session",
54
55
  debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_f = merged.debug) != null ? _f : false,
55
56
  captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_g = merged.capture_system_prompt) != null ? _g : false,
56
- eventMetadata
57
+ eventMetadata,
58
+ localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
57
59
  };
58
60
  }
61
+ function resolveLocalWorkshopUrl(fileValue) {
62
+ const envValue = process.env["RAINDROP_LOCAL_WORKSHOP_URL"];
63
+ if (envValue !== void 0) {
64
+ if (envValue === "" || envValue.toLowerCase() === "null" || envValue.toLowerCase() === "false") {
65
+ return null;
66
+ }
67
+ return envValue;
68
+ }
69
+ return fileValue;
70
+ }
59
71
 
60
72
  // src/internal/extension-tracing.ts
61
73
  function safeParsArgs(argsStr) {
@@ -424,25 +436,33 @@ function extension(pi) {
424
436
  console.log(`[raindrop-ai/pi-agent] [${level}] ${message}`);
425
437
  }
426
438
  appLog("info", `Loading ${PLUGIN_NAME} v${libraryVersion}`);
427
- if (!config.writeKey) {
439
+ const resolvedLocalUrl = resolveLocalDebuggerBaseUrl(config.localWorkshopUrl);
440
+ const hasLocalDestination = resolvedLocalUrl !== null;
441
+ if (!config.writeKey && !hasLocalDestination) {
428
442
  appLog(
429
443
  "warn",
430
- "RAINDROP_WRITE_KEY not set \u2014 Raindrop tracing disabled. Set it in your environment or in ~/.pi/agent/raindrop.json."
444
+ "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."
431
445
  );
432
446
  return;
433
447
  }
434
448
  if (config.debug) {
435
- appLog("info", `Raindrop tracing enabled (endpoint: ${config.endpoint})`);
449
+ const destinations = [
450
+ config.writeKey ? `cloud (${config.endpoint})` : null,
451
+ resolvedLocalUrl ? `local Workshop (${resolvedLocalUrl})` : null
452
+ ].filter(Boolean);
453
+ appLog("info", `Raindrop tracing enabled \u2014 destinations: ${destinations.join(", ")}`);
436
454
  }
437
455
  const eventShipper = new EventShipper({
438
456
  writeKey: config.writeKey,
439
457
  endpoint: config.endpoint,
440
- debug: config.debug
458
+ debug: config.debug,
459
+ localDebuggerUrl: config.localWorkshopUrl
441
460
  });
442
461
  const traceShipper = new TraceShipper({
443
462
  writeKey: config.writeKey,
444
463
  endpoint: config.endpoint,
445
- debug: config.debug
464
+ debug: config.debug,
465
+ localDebuggerUrl: config.localWorkshopUrl
446
466
  });
447
467
  registerTracing(pi, config, eventShipper, traceShipper);
448
468
  }