@raindrop-ai/deep-agents 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,9 +53,23 @@ await raindrop.shutdown();
53
53
  | `endpoint` | `string` | `https://api.raindrop.ai/v1/` | API endpoint |
54
54
  | `userId` | `string` | - | Associate all events with a user |
55
55
  | `convoId` | `string` | - | Group events into a conversation |
56
+ | `projectId` | `string` | - | Route events to a specific project (slug); omit for the default **Production** project |
56
57
  | `debug` | `boolean` | `false` | Enable verbose logging |
57
58
  | `traceChains` | `boolean` | `true` | Create spans for chain execution |
58
59
 
60
+ ## Projects
61
+
62
+ If your org has multiple projects, route events to a specific one by passing its slug as `projectId`:
63
+
64
+ ```typescript
65
+ const raindrop = createRaindropDeepAgents({
66
+ writeKey: "your-write-key",
67
+ projectId: "support-prod",
68
+ });
69
+ ```
70
+
71
+ This sets the `X-Raindrop-Project-Id` header on every event. Omit it (or pass `"default"`) to use your org's default **Production** project — the existing behavior. Single-project orgs need nothing new.
72
+
59
73
  ## LangGraph Support
60
74
 
61
75
  Deep Agents is built on LangGraph. The handler automatically:
package/dist/index.d.mts CHANGED
@@ -364,6 +364,42 @@ declare class TraceShipper {
364
364
  shutdown(): Promise<void>;
365
365
  }
366
366
 
367
+ /**
368
+ * Run telemetry egress with OpenTelemetry tracing suppressed.
369
+ *
370
+ * Why this exists
371
+ * ---------------
372
+ * Raindrop integrations ship spans/events over HTTP with the global `fetch`
373
+ * (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
374
+ * fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
375
+ * every Eve agent installs — that instrumentation wraps *our own* telemetry
376
+ * POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
377
+ * very exporter that issued the request, so they get shipped right back to
378
+ * Raindrop and Workshop as standalone "runs" (and, because each export issues
379
+ * another fetch, they feed back on themselves). The result is a run list
380
+ * flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
381
+ * `.../live` entries that drown out the real agent turns — especially with
382
+ * sub-agents, where every sandbox runs its own instrumentation.
383
+ *
384
+ * The OTel-blessed fix is to mark the active context as "tracing suppressed"
385
+ * around the request; instrumentations check `isTracingSuppressed` and return
386
+ * a no-op span instead of recording one. We do this through a hook stashed on
387
+ * `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
388
+ * - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
389
+ * hard-depends on them, and the hook is simply absent when they (and thus
390
+ * any instrumentation to suppress) are not installed; and
391
+ * - the browser bundle never pulls in `node:module`, mirroring how core
392
+ * injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
393
+ *
394
+ * When no hook is present the callback runs unchanged, so suppression is a
395
+ * best-effort no-op rather than a hard requirement.
396
+ */
397
+ /** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
398
+ type SuppressTracingHook = <T>(fn: () => T) => T;
399
+ declare global {
400
+ var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
401
+ }
402
+
367
403
  type ParentSpanContext = {
368
404
  traceIdB64: string;
369
405
  spanIdB64: string;
package/dist/index.d.ts CHANGED
@@ -364,6 +364,42 @@ declare class TraceShipper {
364
364
  shutdown(): Promise<void>;
365
365
  }
366
366
 
367
+ /**
368
+ * Run telemetry egress with OpenTelemetry tracing suppressed.
369
+ *
370
+ * Why this exists
371
+ * ---------------
372
+ * Raindrop integrations ship spans/events over HTTP with the global `fetch`
373
+ * (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
374
+ * fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
375
+ * every Eve agent installs — that instrumentation wraps *our own* telemetry
376
+ * POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
377
+ * very exporter that issued the request, so they get shipped right back to
378
+ * Raindrop and Workshop as standalone "runs" (and, because each export issues
379
+ * another fetch, they feed back on themselves). The result is a run list
380
+ * flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
381
+ * `.../live` entries that drown out the real agent turns — especially with
382
+ * sub-agents, where every sandbox runs its own instrumentation.
383
+ *
384
+ * The OTel-blessed fix is to mark the active context as "tracing suppressed"
385
+ * around the request; instrumentations check `isTracingSuppressed` and return
386
+ * a no-op span instead of recording one. We do this through a hook stashed on
387
+ * `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
388
+ * - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
389
+ * hard-depends on them, and the hook is simply absent when they (and thus
390
+ * any instrumentation to suppress) are not installed; and
391
+ * - the browser bundle never pulls in `node:module`, mirroring how core
392
+ * injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
393
+ *
394
+ * When no hook is present the callback runs unchanged, so suppression is a
395
+ * best-effort no-op rather than a hard requirement.
396
+ */
397
+ /** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
398
+ type SuppressTracingHook = <T>(fn: () => T) => T;
399
+ declare global {
400
+ var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
401
+ }
402
+
367
403
  type ParentSpanContext = {
368
404
  traceIdB64: string;
369
405
  spanIdB64: string;
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ module.exports = __toCommonJS(index_exports);
28
28
  // src/callback-handler.ts
29
29
  var import_base = require("@langchain/core/callbacks/base");
30
30
 
31
- // ../core/dist/chunk-SK6EJEO7.js
31
+ // ../core/dist/chunk-WKRW55KX.js
32
32
  function getCrypto() {
33
33
  const c = globalThis.crypto;
34
34
  return c;
@@ -83,6 +83,20 @@ function base64Encode(bytes) {
83
83
  }
84
84
  return out;
85
85
  }
86
+ function runWithTracingSuppressed(fn) {
87
+ const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
88
+ if (typeof hook !== "function") return fn();
89
+ let started = false;
90
+ try {
91
+ return hook(() => {
92
+ started = true;
93
+ return fn();
94
+ });
95
+ } catch (err) {
96
+ if (started) throw err;
97
+ return fn();
98
+ }
99
+ }
86
100
  var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
87
101
  var MAX_RETRY_DELAY_MS = 3e4;
88
102
  function wait(ms) {
@@ -193,15 +207,17 @@ async function postJson(url, body, headers, opts) {
193
207
  const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
194
208
  await withRetry(
195
209
  async () => {
196
- const resp = await fetch(url, {
197
- method: "POST",
198
- headers: {
199
- "Content-Type": "application/json",
200
- ...headers
201
- },
202
- body: JSON.stringify(body),
203
- signal: AbortSignal.timeout(timeoutMs)
204
- });
210
+ const resp = await runWithTracingSuppressed(
211
+ () => fetch(url, {
212
+ method: "POST",
213
+ headers: {
214
+ "Content-Type": "application/json",
215
+ ...headers
216
+ },
217
+ body: JSON.stringify(body),
218
+ signal: AbortSignal.timeout(timeoutMs)
219
+ })
220
+ );
205
221
  if (!resp.ok) {
206
222
  const text = await resp.text().catch(() => "");
207
223
  const err = new Error(
@@ -1149,6 +1165,31 @@ var TraceShipper = class {
1149
1165
  // ../core/dist/index.node.js
1150
1166
  var import_async_hooks = require("async_hooks");
1151
1167
  globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
1168
+ var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
1169
+ "OpenTelemetry SDK Context Key SUPPRESS_TRACING"
1170
+ );
1171
+ function findOtelContextManager() {
1172
+ var _a;
1173
+ for (const sym of Object.getOwnPropertySymbols(globalThis)) {
1174
+ if (!((_a = sym.description) == null ? void 0 : _a.startsWith("opentelemetry.js.api."))) continue;
1175
+ const api = globalThis[sym];
1176
+ const cm = api == null ? void 0 : api.context;
1177
+ if (cm && typeof cm.with === "function" && typeof cm.active === "function") {
1178
+ return cm;
1179
+ }
1180
+ }
1181
+ return void 0;
1182
+ }
1183
+ function installTracingSuppressionHook() {
1184
+ if (typeof globalThis.RAINDROP_SUPPRESS_TRACING === "function") return;
1185
+ const hook = (fn) => {
1186
+ const cm = findOtelContextManager();
1187
+ if (!cm) return fn();
1188
+ return cm.with(cm.active().setValue(SUPPRESS_TRACING_KEY, true), fn);
1189
+ };
1190
+ globalThis.RAINDROP_SUPPRESS_TRACING = hook;
1191
+ }
1192
+ installTracingSuppressionHook();
1152
1193
 
1153
1194
  // src/callback-handler.ts
1154
1195
  function isInternalName(name) {
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/callback-handler.ts
2
2
  import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
3
3
 
4
- // ../core/dist/chunk-SK6EJEO7.js
4
+ // ../core/dist/chunk-WKRW55KX.js
5
5
  function getCrypto() {
6
6
  const c = globalThis.crypto;
7
7
  return c;
@@ -56,6 +56,20 @@ function base64Encode(bytes) {
56
56
  }
57
57
  return out;
58
58
  }
59
+ function runWithTracingSuppressed(fn) {
60
+ const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
61
+ if (typeof hook !== "function") return fn();
62
+ let started = false;
63
+ try {
64
+ return hook(() => {
65
+ started = true;
66
+ return fn();
67
+ });
68
+ } catch (err) {
69
+ if (started) throw err;
70
+ return fn();
71
+ }
72
+ }
59
73
  var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
60
74
  var MAX_RETRY_DELAY_MS = 3e4;
61
75
  function wait(ms) {
@@ -166,15 +180,17 @@ async function postJson(url, body, headers, opts) {
166
180
  const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
167
181
  await withRetry(
168
182
  async () => {
169
- const resp = await fetch(url, {
170
- method: "POST",
171
- headers: {
172
- "Content-Type": "application/json",
173
- ...headers
174
- },
175
- body: JSON.stringify(body),
176
- signal: AbortSignal.timeout(timeoutMs)
177
- });
183
+ const resp = await runWithTracingSuppressed(
184
+ () => fetch(url, {
185
+ method: "POST",
186
+ headers: {
187
+ "Content-Type": "application/json",
188
+ ...headers
189
+ },
190
+ body: JSON.stringify(body),
191
+ signal: AbortSignal.timeout(timeoutMs)
192
+ })
193
+ );
178
194
  if (!resp.ok) {
179
195
  const text = await resp.text().catch(() => "");
180
196
  const err = new Error(
@@ -1122,6 +1138,31 @@ var TraceShipper = class {
1122
1138
  // ../core/dist/index.node.js
1123
1139
  import { AsyncLocalStorage } from "async_hooks";
1124
1140
  globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
1141
+ var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
1142
+ "OpenTelemetry SDK Context Key SUPPRESS_TRACING"
1143
+ );
1144
+ function findOtelContextManager() {
1145
+ var _a;
1146
+ for (const sym of Object.getOwnPropertySymbols(globalThis)) {
1147
+ if (!((_a = sym.description) == null ? void 0 : _a.startsWith("opentelemetry.js.api."))) continue;
1148
+ const api = globalThis[sym];
1149
+ const cm = api == null ? void 0 : api.context;
1150
+ if (cm && typeof cm.with === "function" && typeof cm.active === "function") {
1151
+ return cm;
1152
+ }
1153
+ }
1154
+ return void 0;
1155
+ }
1156
+ function installTracingSuppressionHook() {
1157
+ if (typeof globalThis.RAINDROP_SUPPRESS_TRACING === "function") return;
1158
+ const hook = (fn) => {
1159
+ const cm = findOtelContextManager();
1160
+ if (!cm) return fn();
1161
+ return cm.with(cm.active().setValue(SUPPRESS_TRACING_KEY, true), fn);
1162
+ };
1163
+ globalThis.RAINDROP_SUPPRESS_TRACING = hook;
1164
+ }
1165
+ installTracingSuppressionHook();
1125
1166
 
1126
1167
  // src/callback-handler.ts
1127
1168
  function isInternalName(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/deep-agents",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Raindrop integration for LangChain Deep Agents",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -36,7 +36,7 @@
36
36
  "typescript": "^5.3.3",
37
37
  "vitest": "^2.1.9",
38
38
  "zod": "^3.23.0",
39
- "@raindrop-ai/core": "0.0.4"
39
+ "@raindrop-ai/core": "0.0.5"
40
40
  },
41
41
  "tsup": {
42
42
  "entry": [