@raindrop-ai/langchain 0.0.1
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 +76 -0
- package/dist/index.d.mts +320 -0
- package/dist/index.d.ts +320 -0
- package/dist/index.js +1147 -0
- package/dist/index.mjs +1119 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @raindrop-ai/langchain
|
|
2
|
+
|
|
3
|
+
Raindrop integration for LangChain. Automatically captures LLM calls, tool usage, chains, retrievers, and agent actions via LangChain's callback system.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @raindrop-ai/langchain @langchain/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createRaindropLangChain } from "@raindrop-ai/langchain";
|
|
15
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
16
|
+
import { HumanMessage } from "@langchain/core/messages";
|
|
17
|
+
|
|
18
|
+
const raindrop = createRaindropLangChain({
|
|
19
|
+
writeKey: "rk_...",
|
|
20
|
+
userId: "user-123",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const model = new ChatOpenAI({ model: "gpt-4o" });
|
|
24
|
+
|
|
25
|
+
const result = await model.invoke(
|
|
26
|
+
[new HumanMessage("Hello!")],
|
|
27
|
+
{ callbacks: [raindrop.handler] },
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
await raindrop.flush();
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## What gets captured
|
|
34
|
+
|
|
35
|
+
- **LLM calls**: model name, input, output, token usage
|
|
36
|
+
- **Tool calls**: tool name, input arguments, output
|
|
37
|
+
- **Chains**: execution spans with parent-child nesting
|
|
38
|
+
- **Retrievers**: query and document count
|
|
39
|
+
- **Errors**: captured with OTLP error status
|
|
40
|
+
|
|
41
|
+
## Options
|
|
42
|
+
|
|
43
|
+
| Option | Type | Default | Description |
|
|
44
|
+
|--------|------|---------|-------------|
|
|
45
|
+
| `writeKey` | `string` | - | Raindrop API write key (omit to disable telemetry) |
|
|
46
|
+
| `endpoint` | `string` | `https://api.raindrop.ai/v1/` | API endpoint |
|
|
47
|
+
| `userId` | `string` | - | Associate all events with a user |
|
|
48
|
+
| `convoId` | `string` | - | Group events into a conversation |
|
|
49
|
+
| `debug` | `boolean` | `false` | Enable verbose logging |
|
|
50
|
+
| `traceChains` | `boolean` | `true` | Create spans for chain execution |
|
|
51
|
+
| `traceRetrievers` | `boolean` | `true` | Create spans for retriever calls |
|
|
52
|
+
| `filterLangGraphInternals` | `boolean` | `true` | Filter LangGraph-internal chain events and deduplicate LLM callbacks |
|
|
53
|
+
|
|
54
|
+
## LangGraph Support
|
|
55
|
+
|
|
56
|
+
Works with LangGraph out of the box. The handler automatically:
|
|
57
|
+
- Filters LangGraph-internal chain events (graph executor, `__start__`, `__end__`, channel nodes)
|
|
58
|
+
- Deduplicates LLM callbacks that LangGraph fires multiple times with the same `runId`
|
|
59
|
+
|
|
60
|
+
Pass the handler both at `graph.invoke()` and inside your LLM node. See `examples/langchain-langgraph-basic/` for a full example.
|
|
61
|
+
|
|
62
|
+
**Best practices:**
|
|
63
|
+
- Pass callbacks to the **model inside your node**, not to `graph.invoke()` — this avoids duplicate events from LangGraph's internal callback propagation
|
|
64
|
+
- Create a new handler instance per request in server environments
|
|
65
|
+
|
|
66
|
+
## LangSmith Coexistence
|
|
67
|
+
|
|
68
|
+
Raindrop and LangSmith can run simultaneously — both receive the same LangChain callbacks independently. Set `LANGSMITH_TRACING=false` to disable LangSmith if you only want Raindrop.
|
|
69
|
+
|
|
70
|
+
## Testing
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm test
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Tests use MSW to intercept HTTP requests — no real LLM calls are made.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
2
|
+
import { Serialized } from '@langchain/core/load/serializable';
|
|
3
|
+
import { LLMResult } from '@langchain/core/outputs';
|
|
4
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
5
|
+
import { AgentAction, AgentFinish } from '@langchain/core/agents';
|
|
6
|
+
import { DocumentInterface } from '@langchain/core/documents';
|
|
7
|
+
import { ChainValues } from '@langchain/core/utils/types';
|
|
8
|
+
|
|
9
|
+
type OtlpAnyValue = {
|
|
10
|
+
stringValue?: string;
|
|
11
|
+
intValue?: string;
|
|
12
|
+
doubleValue?: number;
|
|
13
|
+
boolValue?: boolean;
|
|
14
|
+
arrayValue?: {
|
|
15
|
+
values: OtlpAnyValue[];
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type OtlpKeyValue = {
|
|
19
|
+
key: string;
|
|
20
|
+
value: OtlpAnyValue;
|
|
21
|
+
};
|
|
22
|
+
declare const SpanStatusCode: {
|
|
23
|
+
readonly UNSET: 0;
|
|
24
|
+
readonly OK: 1;
|
|
25
|
+
readonly ERROR: 2;
|
|
26
|
+
};
|
|
27
|
+
type OtlpSpanStatus = {
|
|
28
|
+
code: (typeof SpanStatusCode)[keyof typeof SpanStatusCode] | number;
|
|
29
|
+
message?: string;
|
|
30
|
+
};
|
|
31
|
+
type OtlpSpan = {
|
|
32
|
+
traceId: string;
|
|
33
|
+
spanId: string;
|
|
34
|
+
parentSpanId?: string;
|
|
35
|
+
name: string;
|
|
36
|
+
startTimeUnixNano: string;
|
|
37
|
+
endTimeUnixNano: string;
|
|
38
|
+
attributes?: OtlpKeyValue[];
|
|
39
|
+
status?: OtlpSpanStatus;
|
|
40
|
+
};
|
|
41
|
+
type SpanIds = {
|
|
42
|
+
traceIdB64: string;
|
|
43
|
+
spanIdB64: string;
|
|
44
|
+
parentSpanIdB64?: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type Attachment = {
|
|
48
|
+
type: string;
|
|
49
|
+
role: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
value: string;
|
|
52
|
+
};
|
|
53
|
+
type IdentifyInput = {
|
|
54
|
+
userId: string;
|
|
55
|
+
traits?: Record<string, unknown>;
|
|
56
|
+
};
|
|
57
|
+
type Patch = {
|
|
58
|
+
eventName?: string;
|
|
59
|
+
userId?: string;
|
|
60
|
+
convoId?: string;
|
|
61
|
+
input?: string;
|
|
62
|
+
output?: string;
|
|
63
|
+
model?: string;
|
|
64
|
+
properties?: Record<string, unknown>;
|
|
65
|
+
attachments?: Attachment[];
|
|
66
|
+
isPending?: boolean;
|
|
67
|
+
timestamp?: string;
|
|
68
|
+
};
|
|
69
|
+
type SignalInput = {
|
|
70
|
+
eventId: string;
|
|
71
|
+
name: string;
|
|
72
|
+
type?: "default" | "feedback" | "edit" | "standard" | "agent" | "agent_internal";
|
|
73
|
+
sentiment?: "POSITIVE" | "NEGATIVE";
|
|
74
|
+
timestamp?: string;
|
|
75
|
+
properties?: Record<string, unknown>;
|
|
76
|
+
attachmentId?: string;
|
|
77
|
+
comment?: string;
|
|
78
|
+
after?: string;
|
|
79
|
+
};
|
|
80
|
+
type EventShipperOptions = {
|
|
81
|
+
writeKey?: string;
|
|
82
|
+
endpoint?: string;
|
|
83
|
+
enabled?: boolean;
|
|
84
|
+
debug: boolean;
|
|
85
|
+
partialFlushMs?: number;
|
|
86
|
+
sdkName?: string;
|
|
87
|
+
libraryName?: string;
|
|
88
|
+
libraryVersion?: string;
|
|
89
|
+
defaultEventName?: string;
|
|
90
|
+
};
|
|
91
|
+
declare class EventShipper {
|
|
92
|
+
private baseUrl;
|
|
93
|
+
private writeKey?;
|
|
94
|
+
private enabled;
|
|
95
|
+
private debug;
|
|
96
|
+
private partialFlushMs;
|
|
97
|
+
private sdkName;
|
|
98
|
+
private prefix;
|
|
99
|
+
private defaultEventName;
|
|
100
|
+
private context;
|
|
101
|
+
private buffers;
|
|
102
|
+
private sticky;
|
|
103
|
+
private timers;
|
|
104
|
+
private inFlight;
|
|
105
|
+
constructor(opts: EventShipperOptions);
|
|
106
|
+
isDebugEnabled(): boolean;
|
|
107
|
+
private authHeaders;
|
|
108
|
+
patch(eventId: string, patch: Patch): Promise<void>;
|
|
109
|
+
finish(eventId: string, patch: {
|
|
110
|
+
output?: string;
|
|
111
|
+
model?: string;
|
|
112
|
+
properties?: Record<string, unknown>;
|
|
113
|
+
userId?: string;
|
|
114
|
+
}): Promise<void>;
|
|
115
|
+
flush(): Promise<void>;
|
|
116
|
+
shutdown(): Promise<void>;
|
|
117
|
+
trackSignal(signal: SignalInput): Promise<void>;
|
|
118
|
+
identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
|
|
119
|
+
private flushOne;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
type InternalSpan = {
|
|
123
|
+
ids: SpanIds;
|
|
124
|
+
name: string;
|
|
125
|
+
startTimeUnixNano: string;
|
|
126
|
+
endTimeUnixNano?: string;
|
|
127
|
+
attributes: Array<OtlpKeyValue | undefined>;
|
|
128
|
+
};
|
|
129
|
+
type TraceShipperOptions = {
|
|
130
|
+
writeKey?: string;
|
|
131
|
+
endpoint?: string;
|
|
132
|
+
enabled?: boolean;
|
|
133
|
+
debug: boolean;
|
|
134
|
+
debugSpans?: boolean;
|
|
135
|
+
flushIntervalMs?: number;
|
|
136
|
+
maxBatchSize?: number;
|
|
137
|
+
maxQueueSize?: number;
|
|
138
|
+
sdkName?: string;
|
|
139
|
+
serviceName?: string;
|
|
140
|
+
serviceVersion?: string;
|
|
141
|
+
};
|
|
142
|
+
declare class TraceShipper {
|
|
143
|
+
private baseUrl;
|
|
144
|
+
private writeKey?;
|
|
145
|
+
private enabled;
|
|
146
|
+
private debug;
|
|
147
|
+
private debugSpans;
|
|
148
|
+
private sdkName;
|
|
149
|
+
private prefix;
|
|
150
|
+
private serviceName;
|
|
151
|
+
private serviceVersion;
|
|
152
|
+
private flushIntervalMs;
|
|
153
|
+
private maxBatchSize;
|
|
154
|
+
private maxQueueSize;
|
|
155
|
+
private queue;
|
|
156
|
+
private timer;
|
|
157
|
+
private inFlight;
|
|
158
|
+
constructor(opts: TraceShipperOptions);
|
|
159
|
+
isDebugEnabled(): boolean;
|
|
160
|
+
private authHeaders;
|
|
161
|
+
startSpan(args: {
|
|
162
|
+
name: string;
|
|
163
|
+
parent?: {
|
|
164
|
+
traceIdB64: string;
|
|
165
|
+
spanIdB64: string;
|
|
166
|
+
};
|
|
167
|
+
eventId: string;
|
|
168
|
+
operationId?: string;
|
|
169
|
+
attributes?: Array<OtlpKeyValue | undefined>;
|
|
170
|
+
startTimeUnixNano?: string;
|
|
171
|
+
}): InternalSpan;
|
|
172
|
+
endSpan(span: InternalSpan, extra?: {
|
|
173
|
+
attributes?: InternalSpan["attributes"];
|
|
174
|
+
error?: unknown;
|
|
175
|
+
status?: OtlpSpanStatus;
|
|
176
|
+
endTimeUnixNano?: string;
|
|
177
|
+
}): void;
|
|
178
|
+
createSpan(args: {
|
|
179
|
+
name: string;
|
|
180
|
+
parent?: {
|
|
181
|
+
traceIdB64: string;
|
|
182
|
+
spanIdB64: string;
|
|
183
|
+
};
|
|
184
|
+
eventId: string;
|
|
185
|
+
startTimeUnixNano: string;
|
|
186
|
+
endTimeUnixNano: string;
|
|
187
|
+
attributes?: Array<OtlpKeyValue | undefined>;
|
|
188
|
+
status?: OtlpSpanStatus;
|
|
189
|
+
}): void;
|
|
190
|
+
enqueue(span: OtlpSpan): void;
|
|
191
|
+
flush(): Promise<void>;
|
|
192
|
+
shutdown(): Promise<void>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
type ParentSpanContext = {
|
|
196
|
+
traceIdB64: string;
|
|
197
|
+
spanIdB64: string;
|
|
198
|
+
eventId: string;
|
|
199
|
+
};
|
|
200
|
+
interface ContextSpan {
|
|
201
|
+
readonly traceIdB64: string;
|
|
202
|
+
readonly spanIdB64: string;
|
|
203
|
+
readonly eventId: string;
|
|
204
|
+
log?(data: Record<string, unknown>): void;
|
|
205
|
+
}
|
|
206
|
+
interface AsyncLocalStorageLike<T> {
|
|
207
|
+
getStore(): T | undefined;
|
|
208
|
+
run<R>(store: T, callback: () => R): R;
|
|
209
|
+
enterWith?(store: T): void;
|
|
210
|
+
}
|
|
211
|
+
declare abstract class ContextManager {
|
|
212
|
+
abstract getParentSpanIds(): ParentSpanContext | undefined;
|
|
213
|
+
abstract runInContext<R>(span: ContextSpan, callback: () => R): R;
|
|
214
|
+
abstract getCurrentSpan(): ContextSpan | undefined;
|
|
215
|
+
abstract isReady(): boolean;
|
|
216
|
+
}
|
|
217
|
+
declare global {
|
|
218
|
+
var RAINDROP_CONTEXT_MANAGER: (new () => ContextManager) | undefined;
|
|
219
|
+
var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => AsyncLocalStorageLike<T>) | undefined;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
interface RaindropCallbackHandlerOptions {
|
|
223
|
+
eventShipper: EventShipper;
|
|
224
|
+
traceShipper: TraceShipper;
|
|
225
|
+
userId?: string;
|
|
226
|
+
convoId?: string;
|
|
227
|
+
traceChains?: boolean;
|
|
228
|
+
traceRetrievers?: boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Filter out LangGraph-internal chain events (graph executor, `__start__`,
|
|
231
|
+
* `__end__`, node wrappers). When enabled, only user-defined chains produce
|
|
232
|
+
* spans. Also deduplicates LLM callbacks that LangGraph fires multiple
|
|
233
|
+
* times with the same runId. Defaults to `true`.
|
|
234
|
+
*/
|
|
235
|
+
filterLangGraphInternals?: boolean;
|
|
236
|
+
}
|
|
237
|
+
declare class RaindropCallbackHandler extends BaseCallbackHandler {
|
|
238
|
+
name: string;
|
|
239
|
+
private eventShipper;
|
|
240
|
+
private traceShipper;
|
|
241
|
+
private userId?;
|
|
242
|
+
private convoId?;
|
|
243
|
+
private traceChains;
|
|
244
|
+
private traceRetrievers;
|
|
245
|
+
private filterLangGraphInternals;
|
|
246
|
+
private spans;
|
|
247
|
+
private rootRunIds;
|
|
248
|
+
private eventIds;
|
|
249
|
+
constructor(opts: RaindropCallbackHandlerOptions);
|
|
250
|
+
private getEventId;
|
|
251
|
+
private getParent;
|
|
252
|
+
private cleanup;
|
|
253
|
+
private finalizeEventIfRoot;
|
|
254
|
+
/** Called at the start of an LLM run with string prompts. */
|
|
255
|
+
handleLLMStart(llm: Serialized, prompts: string[], runId: string, parentRunId?: string, _extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
256
|
+
/** Called at the start of a chat model run with structured messages. */
|
|
257
|
+
handleChatModelStart(llm: Serialized, messages: BaseMessage[][], runId: string, parentRunId?: string, _extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
258
|
+
handleLLMEnd(output: LLMResult, runId: string, _parentRunId?: string): Promise<void>;
|
|
259
|
+
/** Called when an LLM run encounters an error. */
|
|
260
|
+
handleLLMError(err: unknown, runId: string): Promise<void>;
|
|
261
|
+
handleChainStart(chain: Serialized, _inputs: ChainValues, runId: string, parentRunId?: string, _tags?: string[], _metadata?: Record<string, unknown>, _runType?: string, runName?: string): Promise<void>;
|
|
262
|
+
handleChainEnd(_outputs: ChainValues, runId: string): Promise<void>;
|
|
263
|
+
handleChainError(err: unknown, runId: string): Promise<void>;
|
|
264
|
+
handleToolStart(tool: Serialized, input: string, runId: string, parentRunId?: string, _tags?: string[], _metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
265
|
+
/** Called at the end of a tool run. */
|
|
266
|
+
handleToolEnd(output: unknown, runId: string): Promise<void>;
|
|
267
|
+
/** Called when a tool run encounters an error. */
|
|
268
|
+
handleToolError(err: unknown, runId: string): Promise<void>;
|
|
269
|
+
/** Called at the start of a retriever run. */
|
|
270
|
+
handleRetrieverStart(retriever: Serialized, query: string, runId: string, parentRunId?: string, _tags?: string[], _metadata?: Record<string, unknown>, name?: string): Promise<void>;
|
|
271
|
+
/** Called at the end of a retriever run. */
|
|
272
|
+
handleRetrieverEnd(documents: DocumentInterface[], runId: string): Promise<void>;
|
|
273
|
+
/** Called when a retriever run encounters an error. */
|
|
274
|
+
handleRetrieverError(err: unknown, runId: string): Promise<void>;
|
|
275
|
+
handleAgentAction(action: AgentAction, runId: string, parentRunId?: string): Promise<void>;
|
|
276
|
+
handleAgentEnd(_action: AgentFinish, runId: string): Promise<void>;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
interface LangChainOptions {
|
|
280
|
+
/**
|
|
281
|
+
* API write key. If omitted, telemetry shipping is disabled but the handler
|
|
282
|
+
* is still available for a consistent integration surface.
|
|
283
|
+
*/
|
|
284
|
+
writeKey?: string;
|
|
285
|
+
endpoint?: string;
|
|
286
|
+
debug?: boolean;
|
|
287
|
+
userId?: string;
|
|
288
|
+
convoId?: string;
|
|
289
|
+
traceChains?: boolean;
|
|
290
|
+
traceRetrievers?: boolean;
|
|
291
|
+
/**
|
|
292
|
+
* Filter out LangGraph-internal chain events and deduplicate LLM callbacks.
|
|
293
|
+
* Recommended when using LangGraph. Defaults to `true`.
|
|
294
|
+
*/
|
|
295
|
+
filterLangGraphInternals?: boolean;
|
|
296
|
+
}
|
|
297
|
+
type RaindropLangChainClient = {
|
|
298
|
+
handler: RaindropCallbackHandler;
|
|
299
|
+
events: {
|
|
300
|
+
patch(eventId: string, patch: Patch): Promise<void>;
|
|
301
|
+
finish(eventId: string, patch: {
|
|
302
|
+
output?: string;
|
|
303
|
+
model?: string;
|
|
304
|
+
properties?: Record<string, unknown>;
|
|
305
|
+
}): Promise<void>;
|
|
306
|
+
addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
|
|
307
|
+
setProperties(eventId: string, properties: Record<string, unknown>): Promise<void>;
|
|
308
|
+
};
|
|
309
|
+
users: {
|
|
310
|
+
identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
|
|
311
|
+
};
|
|
312
|
+
signals: {
|
|
313
|
+
track(signal: SignalInput): Promise<void>;
|
|
314
|
+
};
|
|
315
|
+
flush(): Promise<void>;
|
|
316
|
+
shutdown(): Promise<void>;
|
|
317
|
+
};
|
|
318
|
+
declare function createRaindropLangChain(opts: LangChainOptions): RaindropLangChainClient;
|
|
319
|
+
|
|
320
|
+
export { type LangChainOptions, RaindropCallbackHandler, type RaindropLangChainClient, createRaindropLangChain };
|