@langchain/langgraph 0.2.45 → 0.2.47
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/func/index.cjs +0 -15
- package/dist/func/index.d.ts +0 -40
- package/dist/func/index.js +0 -15
- package/dist/graph/annotation.cjs +0 -1
- package/dist/graph/annotation.d.ts +0 -1
- package/dist/graph/annotation.js +0 -1
- package/dist/graph/graph.cjs +2 -1
- package/dist/graph/graph.d.ts +2 -1
- package/dist/graph/graph.js +2 -1
- package/dist/graph/state.cjs +2 -1
- package/dist/graph/state.d.ts +2 -1
- package/dist/graph/state.js +2 -1
- package/dist/prebuilt/index.cjs +2 -1
- package/dist/prebuilt/index.d.ts +1 -1
- package/dist/prebuilt/index.js +1 -1
- package/dist/prebuilt/react_agent_executor.cjs +104 -44
- package/dist/prebuilt/react_agent_executor.d.ts +21 -49
- package/dist/prebuilt/react_agent_executor.js +104 -44
- package/dist/pregel/index.cjs +315 -33
- package/dist/pregel/index.d.ts +374 -61
- package/dist/pregel/index.js +315 -33
- package/dist/pregel/io.cjs +49 -24
- package/dist/pregel/io.d.ts +8 -1
- package/dist/pregel/io.js +49 -24
- package/dist/pregel/loop.cjs +11 -0
- package/dist/pregel/loop.d.ts +1 -0
- package/dist/pregel/loop.js +12 -1
- package/dist/pregel/messages.cjs +27 -15
- package/dist/pregel/messages.d.ts +2 -1
- package/dist/pregel/messages.js +27 -15
- package/dist/pregel/remote.cjs +8 -9
- package/dist/pregel/remote.js +8 -9
- package/dist/pregel/runner.cjs +24 -22
- package/dist/pregel/runner.d.ts +0 -3
- package/dist/pregel/runner.js +25 -23
- package/dist/pregel/types.d.ts +154 -30
- package/dist/web.d.ts +2 -2
- package/package.json +4 -4
package/dist/pregel/io.cjs
CHANGED
|
@@ -157,10 +157,15 @@ function* mapOutputValues(outputChannels, pendingWrites, channels
|
|
|
157
157
|
exports.mapOutputValues = mapOutputValues;
|
|
158
158
|
/**
|
|
159
159
|
* Map pending writes (a sequence of tuples (channel, value)) to output chunk.
|
|
160
|
+
* @internal
|
|
161
|
+
*
|
|
162
|
+
* @param outputChannels - The channels to output.
|
|
163
|
+
* @param tasks - The tasks to output.
|
|
164
|
+
* @param cached - Whether the output is cached.
|
|
165
|
+
*
|
|
166
|
+
* @returns A generator that yields the output chunk (if any).
|
|
160
167
|
*/
|
|
161
|
-
function* mapOutputUpdates(outputChannels, tasks, cached
|
|
162
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
163
|
-
) {
|
|
168
|
+
function* mapOutputUpdates(outputChannels, tasks, cached) {
|
|
164
169
|
const outputTasks = tasks.filter(([task, ww]) => {
|
|
165
170
|
return ((task.config === undefined || !task.config.tags?.includes(constants_js_1.TAG_HIDDEN)) &&
|
|
166
171
|
ww[0][0] !== constants_js_1.ERROR &&
|
|
@@ -169,47 +174,67 @@ function* mapOutputUpdates(outputChannels, tasks, cached
|
|
|
169
174
|
if (!outputTasks.length) {
|
|
170
175
|
return;
|
|
171
176
|
}
|
|
172
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
173
177
|
let updated;
|
|
174
178
|
if (outputTasks.some(([task]) => task.writes.some(([chan, _]) => chan === constants_js_1.RETURN))) {
|
|
179
|
+
// TODO: probably should assert that RETURN is the only "non-special" channel (starts with "__")
|
|
175
180
|
updated = outputTasks.flatMap(([task]) => task.writes
|
|
176
181
|
.filter(([chan, _]) => chan === constants_js_1.RETURN)
|
|
177
182
|
.map(([_, value]) => [task.name, value]));
|
|
178
183
|
}
|
|
179
184
|
else if (!Array.isArray(outputChannels)) {
|
|
185
|
+
// special case where graph state is a single channel (MessageGraph)
|
|
186
|
+
// probably using this in functional API, too
|
|
180
187
|
updated = outputTasks.flatMap(([task]) => task.writes
|
|
181
188
|
.filter(([chan, _]) => chan === outputChannels)
|
|
182
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
183
189
|
.map(([_, value]) => [task.name, value]));
|
|
184
190
|
}
|
|
185
191
|
else {
|
|
186
|
-
updated = outputTasks
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
updated = outputTasks.flatMap(([task]) => {
|
|
193
|
+
const { writes } = task;
|
|
194
|
+
const counts = {};
|
|
195
|
+
for (const [chan] of writes) {
|
|
196
|
+
if (outputChannels.includes(chan)) {
|
|
197
|
+
counts[chan] = (counts[chan] || 0) + 1;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (Object.values(counts).some((count) => count > 1)) {
|
|
201
|
+
// Multiple writes to the same channel: create separate entries
|
|
202
|
+
return writes
|
|
203
|
+
.filter(([chan]) => outputChannels.includes(chan))
|
|
204
|
+
.map(([chan, value]) => [task.name, { [chan]: value }]);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// Single write to each channel: create a single combined entry
|
|
208
|
+
return [
|
|
209
|
+
[
|
|
210
|
+
task.name,
|
|
211
|
+
Object.fromEntries(writes.filter(([chan]) => outputChannels.includes(chan))),
|
|
212
|
+
],
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
const grouped = {};
|
|
196
218
|
for (const [node, value] of updated) {
|
|
219
|
+
if (!(node in grouped)) {
|
|
220
|
+
grouped[node] = [];
|
|
221
|
+
}
|
|
197
222
|
grouped[node].push(value);
|
|
198
223
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
224
|
+
const flattened = {};
|
|
225
|
+
for (const node in grouped) {
|
|
226
|
+
if (grouped[node].length === 1) {
|
|
227
|
+
const [write] = grouped[node];
|
|
228
|
+
flattened[node] = write;
|
|
202
229
|
}
|
|
203
|
-
else
|
|
204
|
-
|
|
205
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
206
|
-
grouped[node] = value[0];
|
|
230
|
+
else {
|
|
231
|
+
flattened[node] = grouped[node];
|
|
207
232
|
}
|
|
208
233
|
}
|
|
209
234
|
if (cached) {
|
|
210
|
-
|
|
235
|
+
flattened["__metadata__"] = { cached };
|
|
211
236
|
}
|
|
212
|
-
yield
|
|
237
|
+
yield flattened;
|
|
213
238
|
}
|
|
214
239
|
exports.mapOutputUpdates = mapOutputUpdates;
|
|
215
240
|
function single(iter) {
|
package/dist/pregel/io.d.ts
CHANGED
|
@@ -18,6 +18,13 @@ export declare function mapInput<C extends PropertyKey>(inputChannels: C | Array
|
|
|
18
18
|
export declare function mapOutputValues<C extends PropertyKey>(outputChannels: C | Array<C>, pendingWrites: readonly PendingWrite<C>[] | true, channels: Record<C, BaseChannel>): Generator<Record<string, any>, any>;
|
|
19
19
|
/**
|
|
20
20
|
* Map pending writes (a sequence of tuples (channel, value)) to output chunk.
|
|
21
|
+
* @internal
|
|
22
|
+
*
|
|
23
|
+
* @param outputChannels - The channels to output.
|
|
24
|
+
* @param tasks - The tasks to output.
|
|
25
|
+
* @param cached - Whether the output is cached.
|
|
26
|
+
*
|
|
27
|
+
* @returns A generator that yields the output chunk (if any).
|
|
21
28
|
*/
|
|
22
|
-
export declare function mapOutputUpdates<N extends PropertyKey, C extends PropertyKey>(outputChannels: C | Array<C>, tasks: readonly [PregelExecutableTask<N, C>, PendingWrite<C>[]][], cached?: boolean): Generator<Record<N, Record<string,
|
|
29
|
+
export declare function mapOutputUpdates<N extends PropertyKey, C extends PropertyKey>(outputChannels: C | Array<C>, tasks: readonly [PregelExecutableTask<N, C>, PendingWrite<C>[]][], cached?: boolean): Generator<Record<N, Record<string, unknown> | unknown>>;
|
|
23
30
|
export declare function single<T>(iter: IterableIterator<T>): T | null;
|
package/dist/pregel/io.js
CHANGED
|
@@ -149,10 +149,15 @@ export function* mapOutputValues(outputChannels, pendingWrites, channels
|
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
151
151
|
* Map pending writes (a sequence of tuples (channel, value)) to output chunk.
|
|
152
|
+
* @internal
|
|
153
|
+
*
|
|
154
|
+
* @param outputChannels - The channels to output.
|
|
155
|
+
* @param tasks - The tasks to output.
|
|
156
|
+
* @param cached - Whether the output is cached.
|
|
157
|
+
*
|
|
158
|
+
* @returns A generator that yields the output chunk (if any).
|
|
152
159
|
*/
|
|
153
|
-
export function* mapOutputUpdates(outputChannels, tasks, cached
|
|
154
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
155
|
-
) {
|
|
160
|
+
export function* mapOutputUpdates(outputChannels, tasks, cached) {
|
|
156
161
|
const outputTasks = tasks.filter(([task, ww]) => {
|
|
157
162
|
return ((task.config === undefined || !task.config.tags?.includes(TAG_HIDDEN)) &&
|
|
158
163
|
ww[0][0] !== ERROR &&
|
|
@@ -161,47 +166,67 @@ export function* mapOutputUpdates(outputChannels, tasks, cached
|
|
|
161
166
|
if (!outputTasks.length) {
|
|
162
167
|
return;
|
|
163
168
|
}
|
|
164
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
165
169
|
let updated;
|
|
166
170
|
if (outputTasks.some(([task]) => task.writes.some(([chan, _]) => chan === RETURN))) {
|
|
171
|
+
// TODO: probably should assert that RETURN is the only "non-special" channel (starts with "__")
|
|
167
172
|
updated = outputTasks.flatMap(([task]) => task.writes
|
|
168
173
|
.filter(([chan, _]) => chan === RETURN)
|
|
169
174
|
.map(([_, value]) => [task.name, value]));
|
|
170
175
|
}
|
|
171
176
|
else if (!Array.isArray(outputChannels)) {
|
|
177
|
+
// special case where graph state is a single channel (MessageGraph)
|
|
178
|
+
// probably using this in functional API, too
|
|
172
179
|
updated = outputTasks.flatMap(([task]) => task.writes
|
|
173
180
|
.filter(([chan, _]) => chan === outputChannels)
|
|
174
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
181
|
.map(([_, value]) => [task.name, value]));
|
|
176
182
|
}
|
|
177
183
|
else {
|
|
178
|
-
updated = outputTasks
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
updated = outputTasks.flatMap(([task]) => {
|
|
185
|
+
const { writes } = task;
|
|
186
|
+
const counts = {};
|
|
187
|
+
for (const [chan] of writes) {
|
|
188
|
+
if (outputChannels.includes(chan)) {
|
|
189
|
+
counts[chan] = (counts[chan] || 0) + 1;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (Object.values(counts).some((count) => count > 1)) {
|
|
193
|
+
// Multiple writes to the same channel: create separate entries
|
|
194
|
+
return writes
|
|
195
|
+
.filter(([chan]) => outputChannels.includes(chan))
|
|
196
|
+
.map(([chan, value]) => [task.name, { [chan]: value }]);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// Single write to each channel: create a single combined entry
|
|
200
|
+
return [
|
|
201
|
+
[
|
|
202
|
+
task.name,
|
|
203
|
+
Object.fromEntries(writes.filter(([chan]) => outputChannels.includes(chan))),
|
|
204
|
+
],
|
|
205
|
+
];
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
const grouped = {};
|
|
188
210
|
for (const [node, value] of updated) {
|
|
211
|
+
if (!(node in grouped)) {
|
|
212
|
+
grouped[node] = [];
|
|
213
|
+
}
|
|
189
214
|
grouped[node].push(value);
|
|
190
215
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
216
|
+
const flattened = {};
|
|
217
|
+
for (const node in grouped) {
|
|
218
|
+
if (grouped[node].length === 1) {
|
|
219
|
+
const [write] = grouped[node];
|
|
220
|
+
flattened[node] = write;
|
|
194
221
|
}
|
|
195
|
-
else
|
|
196
|
-
|
|
197
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
198
|
-
grouped[node] = value[0];
|
|
222
|
+
else {
|
|
223
|
+
flattened[node] = grouped[node];
|
|
199
224
|
}
|
|
200
225
|
}
|
|
201
226
|
if (cached) {
|
|
202
|
-
|
|
227
|
+
flattened["__metadata__"] = { cached };
|
|
203
228
|
}
|
|
204
|
-
yield
|
|
229
|
+
yield flattened;
|
|
205
230
|
}
|
|
206
231
|
export function single(iter) {
|
|
207
232
|
// eslint-disable-next-line no-unreachable-loop
|
package/dist/pregel/loop.cjs
CHANGED
|
@@ -527,6 +527,7 @@ class PregelLoop {
|
|
|
527
527
|
return true;
|
|
528
528
|
}
|
|
529
529
|
async finishAndHandleError(error) {
|
|
530
|
+
this._syncStateOnParentCommand(error);
|
|
530
531
|
const suppress = this._suppressInterrupt(error);
|
|
531
532
|
if (suppress || error === undefined) {
|
|
532
533
|
this.output = (0, io_js_1.readChannels)(this.channels, this.outputKeys);
|
|
@@ -751,5 +752,15 @@ class PregelLoop {
|
|
|
751
752
|
}
|
|
752
753
|
}
|
|
753
754
|
}
|
|
755
|
+
_syncStateOnParentCommand(error) {
|
|
756
|
+
if ((0, errors_js_1.isParentCommand)(error)) {
|
|
757
|
+
const state = Object.entries((0, io_js_1.readChannels)(this.channels, typeof this.outputKeys === "string"
|
|
758
|
+
? [this.outputKeys]
|
|
759
|
+
: this.outputKeys));
|
|
760
|
+
const update = [...state, ...error.command._updateAsTuples()];
|
|
761
|
+
// eslint-disable-next-line no-param-reassign
|
|
762
|
+
error.command.update = update;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
754
765
|
}
|
|
755
766
|
exports.PregelLoop = PregelLoop;
|
package/dist/pregel/loop.d.ts
CHANGED
|
@@ -116,5 +116,6 @@ export declare class PregelLoop {
|
|
|
116
116
|
protected _emit(values: [StreamMode, unknown][]): void;
|
|
117
117
|
protected _putCheckpoint(inputMetadata: Omit<CheckpointMetadata, "step" | "parents">): Promise<void>;
|
|
118
118
|
protected _matchWrites(tasks: Record<string, PregelExecutableTask<string, string>>): void;
|
|
119
|
+
_syncStateOnParentCommand(error: unknown): void;
|
|
119
120
|
}
|
|
120
121
|
export {};
|
package/dist/pregel/loop.js
CHANGED
|
@@ -4,7 +4,7 @@ import { isCommand, CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINT_MAP, C
|
|
|
4
4
|
import { _applyWrites, _prepareNextTasks, _prepareSingleTask, increment, shouldInterrupt, } from "./algo.js";
|
|
5
5
|
import { gatherIterator, gatherIteratorSync, prefixGenerator, } from "../utils.js";
|
|
6
6
|
import { mapCommand, mapInput, mapOutputUpdates, mapOutputValues, readChannels, } from "./io.js";
|
|
7
|
-
import { getSubgraphsSeenSet, EmptyInputError, GraphInterrupt, isGraphInterrupt, MultipleSubgraphsError, } from "../errors.js";
|
|
7
|
+
import { getSubgraphsSeenSet, EmptyInputError, GraphInterrupt, isGraphInterrupt, MultipleSubgraphsError, isParentCommand, } from "../errors.js";
|
|
8
8
|
import { getNewChannelVersions, patchConfigurable } from "./utils/index.js";
|
|
9
9
|
import { mapDebugTasks, mapDebugCheckpoint, mapDebugTaskResults, printStepTasks, } from "./debug.js";
|
|
10
10
|
import { IterableReadableWritableStream } from "./stream.js";
|
|
@@ -524,6 +524,7 @@ export class PregelLoop {
|
|
|
524
524
|
return true;
|
|
525
525
|
}
|
|
526
526
|
async finishAndHandleError(error) {
|
|
527
|
+
this._syncStateOnParentCommand(error);
|
|
527
528
|
const suppress = this._suppressInterrupt(error);
|
|
528
529
|
if (suppress || error === undefined) {
|
|
529
530
|
this.output = readChannels(this.channels, this.outputKeys);
|
|
@@ -748,4 +749,14 @@ export class PregelLoop {
|
|
|
748
749
|
}
|
|
749
750
|
}
|
|
750
751
|
}
|
|
752
|
+
_syncStateOnParentCommand(error) {
|
|
753
|
+
if (isParentCommand(error)) {
|
|
754
|
+
const state = Object.entries(readChannels(this.channels, typeof this.outputKeys === "string"
|
|
755
|
+
? [this.outputKeys]
|
|
756
|
+
: this.outputKeys));
|
|
757
|
+
const update = [...state, ...error.command._updateAsTuples()];
|
|
758
|
+
// eslint-disable-next-line no-param-reassign
|
|
759
|
+
error.command.update = update;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
751
762
|
}
|
package/dist/pregel/messages.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StreamMessagesHandler = void 0;
|
|
4
|
-
const uuid_1 = require("uuid");
|
|
5
4
|
const base_1 = require("@langchain/core/callbacks/base");
|
|
6
5
|
const messages_1 = require("@langchain/core/messages");
|
|
7
6
|
const constants_js_1 = require("../constants.cjs");
|
|
@@ -47,6 +46,12 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
47
46
|
writable: true,
|
|
48
47
|
value: {}
|
|
49
48
|
});
|
|
49
|
+
Object.defineProperty(this, "stableMessageIdMap", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: {}
|
|
54
|
+
});
|
|
50
55
|
Object.defineProperty(this, "lc_prefer_streaming", {
|
|
51
56
|
enumerable: true,
|
|
52
57
|
configurable: true,
|
|
@@ -55,18 +60,26 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
55
60
|
});
|
|
56
61
|
this.streamFn = streamFn;
|
|
57
62
|
}
|
|
58
|
-
_emit(meta, message, dedupe = false) {
|
|
63
|
+
_emit(meta, message, runId, dedupe = false) {
|
|
59
64
|
if (dedupe &&
|
|
60
65
|
message.id !== undefined &&
|
|
61
66
|
this.seen[message.id] !== undefined) {
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
// For instance in ChatAnthropic, the first chunk has an message ID
|
|
70
|
+
// but the subsequent chunks do not. To avoid clients seeing two messages
|
|
71
|
+
// we rename the message ID if it's being auto-set to `run-${runId}`
|
|
72
|
+
// (see https://github.com/langchain-ai/langchainjs/pull/6646).
|
|
73
|
+
let messageId = message.id;
|
|
74
|
+
if (messageId == null || messageId === `run-${runId}`) {
|
|
75
|
+
messageId = this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;
|
|
76
|
+
}
|
|
77
|
+
this.stableMessageIdMap[runId] ??= messageId;
|
|
78
|
+
if (messageId !== message.id) {
|
|
66
79
|
// eslint-disable-next-line no-param-reassign
|
|
67
|
-
message.id =
|
|
80
|
+
message.id = messageId;
|
|
68
81
|
// eslint-disable-next-line no-param-reassign
|
|
69
|
-
message.lc_kwargs.id =
|
|
82
|
+
message.lc_kwargs.id = messageId;
|
|
70
83
|
}
|
|
71
84
|
this.seen[message.id] = message;
|
|
72
85
|
this.streamFn([meta[0], "messages", [message, meta[1]]]);
|
|
@@ -86,12 +99,10 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
86
99
|
this.emittedChatModelRunIds[runId] = true;
|
|
87
100
|
if (this.metadatas[runId] !== undefined) {
|
|
88
101
|
if (isChatGenerationChunk(chunk)) {
|
|
89
|
-
this._emit(this.metadatas[runId], chunk.message);
|
|
102
|
+
this._emit(this.metadatas[runId], chunk.message, runId);
|
|
90
103
|
}
|
|
91
104
|
else {
|
|
92
|
-
this._emit(this.metadatas[runId], new messages_1.AIMessageChunk({
|
|
93
|
-
content: token,
|
|
94
|
-
}));
|
|
105
|
+
this._emit(this.metadatas[runId], new messages_1.AIMessageChunk({ content: token }), runId);
|
|
95
106
|
}
|
|
96
107
|
}
|
|
97
108
|
}
|
|
@@ -100,11 +111,12 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
100
111
|
if (!this.emittedChatModelRunIds[runId]) {
|
|
101
112
|
const chatGeneration = output.generations?.[0]?.[0];
|
|
102
113
|
if ((0, messages_1.isBaseMessage)(chatGeneration?.message)) {
|
|
103
|
-
this._emit(this.metadatas[runId], chatGeneration?.message, true);
|
|
114
|
+
this._emit(this.metadatas[runId], chatGeneration?.message, runId, true);
|
|
104
115
|
}
|
|
105
116
|
delete this.emittedChatModelRunIds[runId];
|
|
106
117
|
}
|
|
107
118
|
delete this.metadatas[runId];
|
|
119
|
+
delete this.stableMessageIdMap[runId];
|
|
108
120
|
}
|
|
109
121
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
122
|
handleLLMError(_err, runId) {
|
|
@@ -125,24 +137,24 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
125
137
|
delete this.metadatas[runId];
|
|
126
138
|
if (metadata !== undefined) {
|
|
127
139
|
if ((0, messages_1.isBaseMessage)(outputs)) {
|
|
128
|
-
this._emit(metadata, outputs, true);
|
|
140
|
+
this._emit(metadata, outputs, runId, true);
|
|
129
141
|
}
|
|
130
142
|
else if (Array.isArray(outputs)) {
|
|
131
143
|
for (const value of outputs) {
|
|
132
144
|
if ((0, messages_1.isBaseMessage)(value)) {
|
|
133
|
-
this._emit(metadata, value, true);
|
|
145
|
+
this._emit(metadata, value, runId, true);
|
|
134
146
|
}
|
|
135
147
|
}
|
|
136
148
|
}
|
|
137
149
|
else if (outputs != null && typeof outputs === "object") {
|
|
138
150
|
for (const value of Object.values(outputs)) {
|
|
139
151
|
if ((0, messages_1.isBaseMessage)(value)) {
|
|
140
|
-
this._emit(metadata, value, true);
|
|
152
|
+
this._emit(metadata, value, runId, true);
|
|
141
153
|
}
|
|
142
154
|
else if (Array.isArray(value)) {
|
|
143
155
|
for (const item of value) {
|
|
144
156
|
if ((0, messages_1.isBaseMessage)(item)) {
|
|
145
|
-
this._emit(metadata, item, true);
|
|
157
|
+
this._emit(metadata, item, runId, true);
|
|
146
158
|
}
|
|
147
159
|
}
|
|
148
160
|
}
|
|
@@ -15,9 +15,10 @@ export declare class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
15
15
|
metadatas: Record<string, Meta>;
|
|
16
16
|
seen: Record<string, BaseMessage>;
|
|
17
17
|
emittedChatModelRunIds: Record<string, boolean>;
|
|
18
|
+
stableMessageIdMap: Record<string, string>;
|
|
18
19
|
lc_prefer_streaming: boolean;
|
|
19
20
|
constructor(streamFn: (streamChunk: StreamChunk) => void);
|
|
20
|
-
_emit(meta: Meta, message: BaseMessage, dedupe?: boolean): void;
|
|
21
|
+
_emit(meta: Meta, message: BaseMessage, runId: string, dedupe?: boolean): void;
|
|
21
22
|
handleChatModelStart(_llm: Serialized, _messages: BaseMessage[][], runId: string, _parentRunId?: string, _extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, name?: string): void;
|
|
22
23
|
handleLLMNewToken(token: string, _idx: NewTokenIndices, runId: string, _parentRunId?: string, _tags?: string[], fields?: HandleLLMNewTokenCallbackFields): void;
|
|
23
24
|
handleLLMEnd(output: LLMResult, runId: string): void;
|
package/dist/pregel/messages.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { v4 } from "uuid";
|
|
2
1
|
import { BaseCallbackHandler, } from "@langchain/core/callbacks/base";
|
|
3
2
|
import { AIMessageChunk, isBaseMessage, } from "@langchain/core/messages";
|
|
4
3
|
import { TAG_HIDDEN, TAG_NOSTREAM } from "../constants.js";
|
|
@@ -44,6 +43,12 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
44
43
|
writable: true,
|
|
45
44
|
value: {}
|
|
46
45
|
});
|
|
46
|
+
Object.defineProperty(this, "stableMessageIdMap", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: {}
|
|
51
|
+
});
|
|
47
52
|
Object.defineProperty(this, "lc_prefer_streaming", {
|
|
48
53
|
enumerable: true,
|
|
49
54
|
configurable: true,
|
|
@@ -52,18 +57,26 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
52
57
|
});
|
|
53
58
|
this.streamFn = streamFn;
|
|
54
59
|
}
|
|
55
|
-
_emit(meta, message, dedupe = false) {
|
|
60
|
+
_emit(meta, message, runId, dedupe = false) {
|
|
56
61
|
if (dedupe &&
|
|
57
62
|
message.id !== undefined &&
|
|
58
63
|
this.seen[message.id] !== undefined) {
|
|
59
64
|
return;
|
|
60
65
|
}
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
// For instance in ChatAnthropic, the first chunk has an message ID
|
|
67
|
+
// but the subsequent chunks do not. To avoid clients seeing two messages
|
|
68
|
+
// we rename the message ID if it's being auto-set to `run-${runId}`
|
|
69
|
+
// (see https://github.com/langchain-ai/langchainjs/pull/6646).
|
|
70
|
+
let messageId = message.id;
|
|
71
|
+
if (messageId == null || messageId === `run-${runId}`) {
|
|
72
|
+
messageId = this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;
|
|
73
|
+
}
|
|
74
|
+
this.stableMessageIdMap[runId] ??= messageId;
|
|
75
|
+
if (messageId !== message.id) {
|
|
63
76
|
// eslint-disable-next-line no-param-reassign
|
|
64
|
-
message.id =
|
|
77
|
+
message.id = messageId;
|
|
65
78
|
// eslint-disable-next-line no-param-reassign
|
|
66
|
-
message.lc_kwargs.id =
|
|
79
|
+
message.lc_kwargs.id = messageId;
|
|
67
80
|
}
|
|
68
81
|
this.seen[message.id] = message;
|
|
69
82
|
this.streamFn([meta[0], "messages", [message, meta[1]]]);
|
|
@@ -83,12 +96,10 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
83
96
|
this.emittedChatModelRunIds[runId] = true;
|
|
84
97
|
if (this.metadatas[runId] !== undefined) {
|
|
85
98
|
if (isChatGenerationChunk(chunk)) {
|
|
86
|
-
this._emit(this.metadatas[runId], chunk.message);
|
|
99
|
+
this._emit(this.metadatas[runId], chunk.message, runId);
|
|
87
100
|
}
|
|
88
101
|
else {
|
|
89
|
-
this._emit(this.metadatas[runId], new AIMessageChunk({
|
|
90
|
-
content: token,
|
|
91
|
-
}));
|
|
102
|
+
this._emit(this.metadatas[runId], new AIMessageChunk({ content: token }), runId);
|
|
92
103
|
}
|
|
93
104
|
}
|
|
94
105
|
}
|
|
@@ -97,11 +108,12 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
97
108
|
if (!this.emittedChatModelRunIds[runId]) {
|
|
98
109
|
const chatGeneration = output.generations?.[0]?.[0];
|
|
99
110
|
if (isBaseMessage(chatGeneration?.message)) {
|
|
100
|
-
this._emit(this.metadatas[runId], chatGeneration?.message, true);
|
|
111
|
+
this._emit(this.metadatas[runId], chatGeneration?.message, runId, true);
|
|
101
112
|
}
|
|
102
113
|
delete this.emittedChatModelRunIds[runId];
|
|
103
114
|
}
|
|
104
115
|
delete this.metadatas[runId];
|
|
116
|
+
delete this.stableMessageIdMap[runId];
|
|
105
117
|
}
|
|
106
118
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
119
|
handleLLMError(_err, runId) {
|
|
@@ -122,24 +134,24 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
122
134
|
delete this.metadatas[runId];
|
|
123
135
|
if (metadata !== undefined) {
|
|
124
136
|
if (isBaseMessage(outputs)) {
|
|
125
|
-
this._emit(metadata, outputs, true);
|
|
137
|
+
this._emit(metadata, outputs, runId, true);
|
|
126
138
|
}
|
|
127
139
|
else if (Array.isArray(outputs)) {
|
|
128
140
|
for (const value of outputs) {
|
|
129
141
|
if (isBaseMessage(value)) {
|
|
130
|
-
this._emit(metadata, value, true);
|
|
142
|
+
this._emit(metadata, value, runId, true);
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
}
|
|
134
146
|
else if (outputs != null && typeof outputs === "object") {
|
|
135
147
|
for (const value of Object.values(outputs)) {
|
|
136
148
|
if (isBaseMessage(value)) {
|
|
137
|
-
this._emit(metadata, value, true);
|
|
149
|
+
this._emit(metadata, value, runId, true);
|
|
138
150
|
}
|
|
139
151
|
else if (Array.isArray(value)) {
|
|
140
152
|
for (const item of value) {
|
|
141
153
|
if (isBaseMessage(item)) {
|
|
142
|
-
this._emit(metadata, item, true);
|
|
154
|
+
this._emit(metadata, item, runId, true);
|
|
143
155
|
}
|
|
144
156
|
}
|
|
145
157
|
}
|
package/dist/pregel/remote.cjs
CHANGED
|
@@ -41,18 +41,13 @@ const getStreamModes = (streamMode, defaultStreamMode = "updates") => {
|
|
|
41
41
|
if (streamMode !== undefined &&
|
|
42
42
|
(typeof streamMode === "string" ||
|
|
43
43
|
(Array.isArray(streamMode) && streamMode.length > 0))) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
else {
|
|
48
|
-
reqSingle = false;
|
|
49
|
-
updatedStreamModes.push(...streamMode);
|
|
50
|
-
}
|
|
44
|
+
reqSingle = typeof streamMode === "string";
|
|
45
|
+
const mapped = Array.isArray(streamMode) ? streamMode : [streamMode];
|
|
46
|
+
updatedStreamModes.push(...mapped);
|
|
51
47
|
}
|
|
52
48
|
else {
|
|
53
49
|
updatedStreamModes.push(defaultStreamMode);
|
|
54
50
|
}
|
|
55
|
-
// TODO: Map messages to messages-tuple
|
|
56
51
|
if (updatedStreamModes.includes("updates")) {
|
|
57
52
|
reqUpdates = true;
|
|
58
53
|
}
|
|
@@ -303,7 +298,11 @@ class RemoteGraph extends runnables_1.Runnable {
|
|
|
303
298
|
...updatedStreamModes,
|
|
304
299
|
...(streamProtocolInstance?.modes ?? new Set()),
|
|
305
300
|
]),
|
|
306
|
-
]
|
|
301
|
+
].map((mode) => {
|
|
302
|
+
if (mode === "messages")
|
|
303
|
+
return "messages-tuple";
|
|
304
|
+
return mode;
|
|
305
|
+
});
|
|
307
306
|
let command;
|
|
308
307
|
let serializedInput;
|
|
309
308
|
if ((0, constants_js_1.isCommand)(input)) {
|
package/dist/pregel/remote.js
CHANGED
|
@@ -38,18 +38,13 @@ const getStreamModes = (streamMode, defaultStreamMode = "updates") => {
|
|
|
38
38
|
if (streamMode !== undefined &&
|
|
39
39
|
(typeof streamMode === "string" ||
|
|
40
40
|
(Array.isArray(streamMode) && streamMode.length > 0))) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
else {
|
|
45
|
-
reqSingle = false;
|
|
46
|
-
updatedStreamModes.push(...streamMode);
|
|
47
|
-
}
|
|
41
|
+
reqSingle = typeof streamMode === "string";
|
|
42
|
+
const mapped = Array.isArray(streamMode) ? streamMode : [streamMode];
|
|
43
|
+
updatedStreamModes.push(...mapped);
|
|
48
44
|
}
|
|
49
45
|
else {
|
|
50
46
|
updatedStreamModes.push(defaultStreamMode);
|
|
51
47
|
}
|
|
52
|
-
// TODO: Map messages to messages-tuple
|
|
53
48
|
if (updatedStreamModes.includes("updates")) {
|
|
54
49
|
reqUpdates = true;
|
|
55
50
|
}
|
|
@@ -300,7 +295,11 @@ export class RemoteGraph extends Runnable {
|
|
|
300
295
|
...updatedStreamModes,
|
|
301
296
|
...(streamProtocolInstance?.modes ?? new Set()),
|
|
302
297
|
]),
|
|
303
|
-
]
|
|
298
|
+
].map((mode) => {
|
|
299
|
+
if (mode === "messages")
|
|
300
|
+
return "messages-tuple";
|
|
301
|
+
return mode;
|
|
302
|
+
});
|
|
304
303
|
let command;
|
|
305
304
|
let serializedInput;
|
|
306
305
|
if (isCommand(input)) {
|