@raindrop-ai/langchain 0.0.6 → 0.0.8
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 +14 -0
- package/dist/index.d.mts +36 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +52 -11
- package/dist/index.mjs +52 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -46,12 +46,26 @@ await raindrop.flush();
|
|
|
46
46
|
| `endpoint` | `string` | `https://api.raindrop.ai/v1/` | API endpoint |
|
|
47
47
|
| `userId` | `string` | - | Associate all events with a user |
|
|
48
48
|
| `convoId` | `string` | - | Group events into a conversation |
|
|
49
|
+
| `projectId` | `string` | - | Route events to a specific project (slug); omit for the default **Production** project |
|
|
49
50
|
| `debug` | `boolean` | `false` | Enable verbose logging |
|
|
50
51
|
| `traceChains` | `boolean` | `true` | Create spans for chain execution |
|
|
51
52
|
| `traceRetrievers` | `boolean` | `true` | Create spans for retriever calls |
|
|
52
53
|
| `filterLangGraphInternals` | `boolean` | `true` | Filter LangGraph-internal chain events and deduplicate LLM callbacks |
|
|
53
54
|
| `maxTextFieldChars` | `number` | `1000000` | Per-field cap for event input/output and serialized span payloads, enforced before/during serialization (truncated values end with `...[truncated by raindrop]`; a stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored) |
|
|
54
55
|
|
|
56
|
+
## Projects
|
|
57
|
+
|
|
58
|
+
If your org has multiple projects, route events to a specific one by passing its slug as `projectId`:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
const raindrop = createRaindropLangChain({
|
|
62
|
+
writeKey: "your-write-key",
|
|
63
|
+
projectId: "support-prod",
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
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.
|
|
68
|
+
|
|
55
69
|
## LangGraph Support
|
|
56
70
|
|
|
57
71
|
Works with LangGraph out of the box. The handler automatically:
|
package/dist/index.d.mts
CHANGED
|
@@ -365,6 +365,42 @@ declare class TraceShipper {
|
|
|
365
365
|
shutdown(): Promise<void>;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Run telemetry egress with OpenTelemetry tracing suppressed.
|
|
370
|
+
*
|
|
371
|
+
* Why this exists
|
|
372
|
+
* ---------------
|
|
373
|
+
* Raindrop integrations ship spans/events over HTTP with the global `fetch`
|
|
374
|
+
* (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
|
|
375
|
+
* fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
|
|
376
|
+
* every Eve agent installs — that instrumentation wraps *our own* telemetry
|
|
377
|
+
* POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
|
|
378
|
+
* very exporter that issued the request, so they get shipped right back to
|
|
379
|
+
* Raindrop and Workshop as standalone "runs" (and, because each export issues
|
|
380
|
+
* another fetch, they feed back on themselves). The result is a run list
|
|
381
|
+
* flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
|
|
382
|
+
* `.../live` entries that drown out the real agent turns — especially with
|
|
383
|
+
* sub-agents, where every sandbox runs its own instrumentation.
|
|
384
|
+
*
|
|
385
|
+
* The OTel-blessed fix is to mark the active context as "tracing suppressed"
|
|
386
|
+
* around the request; instrumentations check `isTracingSuppressed` and return
|
|
387
|
+
* a no-op span instead of recording one. We do this through a hook stashed on
|
|
388
|
+
* `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
|
|
389
|
+
* - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
|
|
390
|
+
* hard-depends on them, and the hook is simply absent when they (and thus
|
|
391
|
+
* any instrumentation to suppress) are not installed; and
|
|
392
|
+
* - the browser bundle never pulls in `node:module`, mirroring how core
|
|
393
|
+
* injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
|
|
394
|
+
*
|
|
395
|
+
* When no hook is present the callback runs unchanged, so suppression is a
|
|
396
|
+
* best-effort no-op rather than a hard requirement.
|
|
397
|
+
*/
|
|
398
|
+
/** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
|
|
399
|
+
type SuppressTracingHook = <T>(fn: () => T) => T;
|
|
400
|
+
declare global {
|
|
401
|
+
var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
|
|
402
|
+
}
|
|
403
|
+
|
|
368
404
|
type ParentSpanContext = {
|
|
369
405
|
traceIdB64: string;
|
|
370
406
|
spanIdB64: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -365,6 +365,42 @@ declare class TraceShipper {
|
|
|
365
365
|
shutdown(): Promise<void>;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Run telemetry egress with OpenTelemetry tracing suppressed.
|
|
370
|
+
*
|
|
371
|
+
* Why this exists
|
|
372
|
+
* ---------------
|
|
373
|
+
* Raindrop integrations ship spans/events over HTTP with the global `fetch`
|
|
374
|
+
* (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
|
|
375
|
+
* fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
|
|
376
|
+
* every Eve agent installs — that instrumentation wraps *our own* telemetry
|
|
377
|
+
* POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
|
|
378
|
+
* very exporter that issued the request, so they get shipped right back to
|
|
379
|
+
* Raindrop and Workshop as standalone "runs" (and, because each export issues
|
|
380
|
+
* another fetch, they feed back on themselves). The result is a run list
|
|
381
|
+
* flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
|
|
382
|
+
* `.../live` entries that drown out the real agent turns — especially with
|
|
383
|
+
* sub-agents, where every sandbox runs its own instrumentation.
|
|
384
|
+
*
|
|
385
|
+
* The OTel-blessed fix is to mark the active context as "tracing suppressed"
|
|
386
|
+
* around the request; instrumentations check `isTracingSuppressed` and return
|
|
387
|
+
* a no-op span instead of recording one. We do this through a hook stashed on
|
|
388
|
+
* `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
|
|
389
|
+
* - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
|
|
390
|
+
* hard-depends on them, and the hook is simply absent when they (and thus
|
|
391
|
+
* any instrumentation to suppress) are not installed; and
|
|
392
|
+
* - the browser bundle never pulls in `node:module`, mirroring how core
|
|
393
|
+
* injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
|
|
394
|
+
*
|
|
395
|
+
* When no hook is present the callback runs unchanged, so suppression is a
|
|
396
|
+
* best-effort no-op rather than a hard requirement.
|
|
397
|
+
*/
|
|
398
|
+
/** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
|
|
399
|
+
type SuppressTracingHook = <T>(fn: () => T) => T;
|
|
400
|
+
declare global {
|
|
401
|
+
var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
|
|
402
|
+
}
|
|
403
|
+
|
|
368
404
|
type ParentSpanContext = {
|
|
369
405
|
traceIdB64: string;
|
|
370
406
|
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-
|
|
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
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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/truncation.ts
|
|
1154
1195
|
var TRUNCATION_MARKER2 = "...[truncated by raindrop]";
|
|
@@ -1675,7 +1716,7 @@ function extractLLMMetadata(output) {
|
|
|
1675
1716
|
// package.json
|
|
1676
1717
|
var package_default = {
|
|
1677
1718
|
name: "@raindrop-ai/langchain",
|
|
1678
|
-
version: "0.0.
|
|
1719
|
+
version: "0.0.8",
|
|
1679
1720
|
description: "Raindrop integration for LangChain",
|
|
1680
1721
|
main: "dist/index.js",
|
|
1681
1722
|
module: "dist/index.mjs",
|
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-
|
|
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
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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/truncation.ts
|
|
1127
1168
|
var TRUNCATION_MARKER2 = "...[truncated by raindrop]";
|
|
@@ -1648,7 +1689,7 @@ function extractLLMMetadata(output) {
|
|
|
1648
1689
|
// package.json
|
|
1649
1690
|
var package_default = {
|
|
1650
1691
|
name: "@raindrop-ai/langchain",
|
|
1651
|
-
version: "0.0.
|
|
1692
|
+
version: "0.0.8",
|
|
1652
1693
|
description: "Raindrop integration for LangChain",
|
|
1653
1694
|
main: "dist/index.js",
|
|
1654
1695
|
module: "dist/index.mjs",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raindrop-ai/langchain",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Raindrop integration for LangChain",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"tsup": "^8.4.0",
|
|
32
32
|
"typescript": "^5.3.3",
|
|
33
33
|
"vitest": "^2.1.9",
|
|
34
|
-
"@raindrop-ai/core": "0.0.
|
|
34
|
+
"@raindrop-ai/core": "0.0.5"
|
|
35
35
|
},
|
|
36
36
|
"tsup": {
|
|
37
37
|
"entry": [
|