@langchain/langgraph 0.0.34 → 0.1.0-rc.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/LICENSE +1 -1
- package/README.md +11 -15
- package/dist/channels/any_value.cjs +3 -1
- package/dist/channels/any_value.d.ts +1 -1
- package/dist/channels/any_value.js +3 -1
- package/dist/channels/base.cjs +28 -15
- package/dist/channels/base.d.ts +14 -4
- package/dist/channels/base.js +26 -13
- package/dist/channels/binop.cjs +2 -1
- package/dist/channels/binop.d.ts +1 -1
- package/dist/channels/binop.js +2 -1
- package/dist/channels/dynamic_barrier_value.cjs +30 -18
- package/dist/channels/dynamic_barrier_value.d.ts +2 -1
- package/dist/channels/dynamic_barrier_value.js +30 -18
- package/dist/channels/ephemeral_value.cjs +3 -1
- package/dist/channels/ephemeral_value.d.ts +1 -1
- package/dist/channels/ephemeral_value.js +3 -1
- package/dist/channels/last_value.cjs +3 -2
- package/dist/channels/last_value.d.ts +1 -1
- package/dist/channels/last_value.js +3 -2
- package/dist/channels/named_barrier_value.cjs +14 -6
- package/dist/channels/named_barrier_value.d.ts +2 -1
- package/dist/channels/named_barrier_value.js +15 -7
- package/dist/channels/topic.cjs +10 -11
- package/dist/channels/topic.d.ts +1 -1
- package/dist/channels/topic.js +10 -11
- package/dist/checkpoint/sqlite.cjs +14 -170
- package/dist/checkpoint/sqlite.d.ts +1 -14
- package/dist/checkpoint/sqlite.js +1 -166
- package/dist/constants.cjs +17 -1
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +16 -0
- package/dist/errors.cjs +21 -1
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +18 -0
- package/dist/graph/graph.cjs +6 -3
- package/dist/graph/graph.d.ts +7 -3
- package/dist/graph/graph.js +7 -4
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/state.cjs +9 -8
- package/dist/graph/state.d.ts +1 -1
- package/dist/graph/state.js +9 -8
- package/dist/prebuilt/react_agent_executor.d.ts +1 -1
- package/dist/pregel/algo.cjs +391 -0
- package/dist/pregel/algo.d.ts +35 -0
- package/dist/pregel/algo.js +381 -0
- package/dist/pregel/debug.cjs +155 -9
- package/dist/pregel/debug.d.ts +40 -2
- package/dist/pregel/debug.js +147 -7
- package/dist/pregel/index.cjs +286 -512
- package/dist/pregel/index.d.ts +66 -65
- package/dist/pregel/index.js +285 -506
- package/dist/pregel/io.cjs +2 -2
- package/dist/pregel/io.d.ts +5 -4
- package/dist/pregel/io.js +2 -2
- package/dist/pregel/loop.cjs +432 -0
- package/dist/pregel/loop.d.ts +83 -0
- package/dist/pregel/loop.js +425 -0
- package/dist/pregel/types.d.ts +56 -4
- package/dist/pregel/utils.cjs +48 -0
- package/dist/pregel/utils.d.ts +10 -0
- package/dist/pregel/utils.js +41 -0
- package/dist/pregel/write.cjs +3 -1
- package/dist/pregel/write.js +3 -1
- package/dist/utils.cjs +21 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +18 -0
- package/dist/web.cjs +6 -7
- package/dist/web.d.ts +2 -4
- package/dist/web.js +1 -2
- package/package.json +6 -12
- package/dist/checkpoint/base.cjs +0 -66
- package/dist/checkpoint/base.d.ts +0 -73
- package/dist/checkpoint/base.js +0 -57
- package/dist/checkpoint/id.cjs +0 -8
- package/dist/checkpoint/id.d.ts +0 -1
- package/dist/checkpoint/id.js +0 -4
- package/dist/checkpoint/index.cjs +0 -9
- package/dist/checkpoint/index.d.ts +0 -2
- package/dist/checkpoint/index.js +0 -2
- package/dist/checkpoint/memory.cjs +0 -82
- package/dist/checkpoint/memory.d.ts +0 -10
- package/dist/checkpoint/memory.js +0 -78
- package/dist/serde/base.cjs +0 -8
- package/dist/serde/base.d.ts +0 -12
- package/dist/serde/base.js +0 -5
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -60,20 +60,15 @@ import { tool } from "@langchain/core/tools";
|
|
|
60
60
|
import { z } from "zod";
|
|
61
61
|
import { ChatAnthropic } from "@langchain/anthropic";
|
|
62
62
|
import { StateGraph, StateGraphArgs } from "@langchain/langgraph";
|
|
63
|
-
import { MemorySaver } from "@langchain/langgraph";
|
|
63
|
+
import { MemorySaver, Annotation } from "@langchain/langgraph";
|
|
64
64
|
import { ToolNode } from "@langchain/langgraph/prebuilt";
|
|
65
65
|
|
|
66
|
-
// Define the state interface
|
|
67
|
-
interface AgentState {
|
|
68
|
-
messages: BaseMessage[];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
66
|
// Define the graph state
|
|
72
|
-
const
|
|
73
|
-
messages: {
|
|
74
|
-
reducer: (x
|
|
75
|
-
}
|
|
76
|
-
}
|
|
67
|
+
const GraphState = Annotation.Root({
|
|
68
|
+
messages: Annotation<BaseMessage[]>({
|
|
69
|
+
reducer: (x, y) => x.concat(y),
|
|
70
|
+
})
|
|
71
|
+
})
|
|
77
72
|
|
|
78
73
|
// Define the tools for the agent to use
|
|
79
74
|
const weatherTool = tool(async ({ query }) => {
|
|
@@ -92,7 +87,8 @@ const weatherTool = tool(async ({ query }) => {
|
|
|
92
87
|
});
|
|
93
88
|
|
|
94
89
|
const tools = [weatherTool];
|
|
95
|
-
|
|
90
|
+
// We can extract the state typing via `GraphState.State`
|
|
91
|
+
const toolNode = new ToolNode<typeof GraphState.State>(tools);
|
|
96
92
|
|
|
97
93
|
const model = new ChatAnthropic({
|
|
98
94
|
model: "claude-3-5-sonnet-20240620",
|
|
@@ -100,7 +96,7 @@ const model = new ChatAnthropic({
|
|
|
100
96
|
}).bindTools(tools);
|
|
101
97
|
|
|
102
98
|
// Define the function that determines whether to continue or not
|
|
103
|
-
function shouldContinue(state:
|
|
99
|
+
function shouldContinue(state: typeof GraphState.State) {
|
|
104
100
|
const messages = state.messages;
|
|
105
101
|
const lastMessage = messages[messages.length - 1] as AIMessage;
|
|
106
102
|
|
|
@@ -113,7 +109,7 @@ function shouldContinue(state: AgentState) {
|
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
// Define the function that calls the model
|
|
116
|
-
async function callModel(state:
|
|
112
|
+
async function callModel(state: typeof GraphState.State) {
|
|
117
113
|
const messages = state.messages;
|
|
118
114
|
const response = await model.invoke(messages);
|
|
119
115
|
|
|
@@ -122,7 +118,7 @@ async function callModel(state: AgentState) {
|
|
|
122
118
|
}
|
|
123
119
|
|
|
124
120
|
// Define a new graph
|
|
125
|
-
const workflow = new StateGraph
|
|
121
|
+
const workflow = new StateGraph(GraphState)
|
|
126
122
|
.addNode("agent", callModel)
|
|
127
123
|
.addNode("tools", toolNode)
|
|
128
124
|
.addEdge("__start__", "agent")
|
|
@@ -35,11 +35,13 @@ class AnyValue extends index_js_1.BaseChannel {
|
|
|
35
35
|
}
|
|
36
36
|
update(values) {
|
|
37
37
|
if (values.length === 0) {
|
|
38
|
+
const updated = this.value !== undefined;
|
|
38
39
|
this.value = undefined;
|
|
39
|
-
return;
|
|
40
|
+
return updated;
|
|
40
41
|
}
|
|
41
42
|
// eslint-disable-next-line prefer-destructuring
|
|
42
43
|
this.value = values[values.length - 1];
|
|
44
|
+
return false;
|
|
43
45
|
}
|
|
44
46
|
get() {
|
|
45
47
|
if (this.value === undefined) {
|
|
@@ -10,7 +10,7 @@ export declare class AnyValue<Value> extends BaseChannel<Value, Value, Value> {
|
|
|
10
10
|
value: Value | undefined;
|
|
11
11
|
constructor();
|
|
12
12
|
fromCheckpoint(checkpoint?: Value): this;
|
|
13
|
-
update(values: Value[]):
|
|
13
|
+
update(values: Value[]): boolean;
|
|
14
14
|
get(): Value;
|
|
15
15
|
checkpoint(): Value;
|
|
16
16
|
}
|
|
@@ -32,11 +32,13 @@ export class AnyValue extends BaseChannel {
|
|
|
32
32
|
}
|
|
33
33
|
update(values) {
|
|
34
34
|
if (values.length === 0) {
|
|
35
|
+
const updated = this.value !== undefined;
|
|
35
36
|
this.value = undefined;
|
|
36
|
-
return;
|
|
37
|
+
return updated;
|
|
37
38
|
}
|
|
38
39
|
// eslint-disable-next-line prefer-destructuring
|
|
39
40
|
this.value = values[values.length - 1];
|
|
41
|
+
return false;
|
|
40
42
|
}
|
|
41
43
|
get() {
|
|
42
44
|
if (this.value === undefined) {
|
package/dist/channels/base.cjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createCheckpoint = exports.emptyChannels = exports.BaseChannel = void 0;
|
|
4
|
-
const
|
|
5
|
-
const id_js_1 = require("../checkpoint/id.cjs");
|
|
4
|
+
const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
|
|
6
5
|
const errors_js_1 = require("../errors.cjs");
|
|
7
6
|
class BaseChannel {
|
|
8
7
|
constructor() {
|
|
@@ -19,6 +18,14 @@ class BaseChannel {
|
|
|
19
18
|
value: void 0
|
|
20
19
|
});
|
|
21
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Mark the current value of the channel as consumed. By default, no-op.
|
|
23
|
+
* This is called by Pregel before the start of the next step, for all
|
|
24
|
+
* channels that triggered a node. If the channel was updated, return true.
|
|
25
|
+
*/
|
|
26
|
+
consume() {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
22
29
|
}
|
|
23
30
|
exports.BaseChannel = BaseChannel;
|
|
24
31
|
function emptyChannels(channels, checkpoint) {
|
|
@@ -34,28 +41,34 @@ function emptyChannels(channels, checkpoint) {
|
|
|
34
41
|
exports.emptyChannels = emptyChannels;
|
|
35
42
|
function createCheckpoint(checkpoint, channels, step) {
|
|
36
43
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
let values;
|
|
45
|
+
if (channels === undefined) {
|
|
46
|
+
values = checkpoint.channel_values;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
values = {};
|
|
50
|
+
for (const k of Object.keys(channels)) {
|
|
51
|
+
try {
|
|
52
|
+
values[k] = channels[k].checkpoint();
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
54
|
}
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (error.name === errors_js_1.EmptyChannelError.unminifiable_name) {
|
|
57
|
+
// no-op
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
throw error; // Rethrow unexpected errors
|
|
61
|
+
}
|
|
49
62
|
}
|
|
50
63
|
}
|
|
51
64
|
}
|
|
52
65
|
return {
|
|
53
66
|
v: 1,
|
|
54
|
-
id: (0,
|
|
67
|
+
id: (0, langgraph_checkpoint_1.uuid6)(step),
|
|
55
68
|
ts: new Date().toISOString(),
|
|
56
69
|
channel_values: values,
|
|
57
70
|
channel_versions: { ...checkpoint.channel_versions },
|
|
58
|
-
versions_seen: (0,
|
|
71
|
+
versions_seen: (0, langgraph_checkpoint_1.deepCopy)(checkpoint.versions_seen),
|
|
59
72
|
pending_sends: checkpoint.pending_sends ?? [],
|
|
60
73
|
};
|
|
61
74
|
}
|
package/dist/channels/base.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ReadonlyCheckpoint } from "
|
|
2
|
-
import { Checkpoint } from "../checkpoint/index.js";
|
|
1
|
+
import { ReadonlyCheckpoint, Checkpoint } from "@langchain/langgraph-checkpoint";
|
|
3
2
|
export declare abstract class BaseChannel<ValueType = unknown, UpdateType = unknown, CheckpointType = unknown> {
|
|
4
3
|
ValueType: ValueType;
|
|
5
4
|
UpdateType: UpdateType;
|
|
@@ -19,12 +18,17 @@ export declare abstract class BaseChannel<ValueType = unknown, UpdateType = unkn
|
|
|
19
18
|
/**
|
|
20
19
|
* Update the channel's value with the given sequence of updates.
|
|
21
20
|
* The order of the updates in the sequence is arbitrary.
|
|
21
|
+
* This method is called by Pregel for all channels at the end of each step.
|
|
22
|
+
* If there are no updates, it is called with an empty sequence.
|
|
23
|
+
*
|
|
24
|
+
* Raises InvalidUpdateError if the sequence of updates is invalid.
|
|
25
|
+
* Returns True if the channel was updated, False otherwise.
|
|
22
26
|
*
|
|
23
27
|
* @throws {InvalidUpdateError} if the sequence of updates is invalid.
|
|
24
28
|
* @param {Array<UpdateType>} values
|
|
25
29
|
* @returns {void}
|
|
26
30
|
*/
|
|
27
|
-
abstract update(values: UpdateType[]):
|
|
31
|
+
abstract update(values: UpdateType[]): boolean;
|
|
28
32
|
/**
|
|
29
33
|
* Return the current value of the channel.
|
|
30
34
|
*
|
|
@@ -39,6 +43,12 @@ export declare abstract class BaseChannel<ValueType = unknown, UpdateType = unkn
|
|
|
39
43
|
* @returns {CheckpointType | undefined}
|
|
40
44
|
*/
|
|
41
45
|
abstract checkpoint(): CheckpointType | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Mark the current value of the channel as consumed. By default, no-op.
|
|
48
|
+
* This is called by Pregel before the start of the next step, for all
|
|
49
|
+
* channels that triggered a node. If the channel was updated, return true.
|
|
50
|
+
*/
|
|
51
|
+
consume(): boolean;
|
|
42
52
|
}
|
|
43
53
|
export declare function emptyChannels<Cc extends Record<string, BaseChannel>>(channels: Cc, checkpoint: ReadonlyCheckpoint): Cc;
|
|
44
|
-
export declare function createCheckpoint<ValueType>(checkpoint: ReadonlyCheckpoint, channels: Record<string, BaseChannel<ValueType
|
|
54
|
+
export declare function createCheckpoint<ValueType>(checkpoint: ReadonlyCheckpoint, channels: Record<string, BaseChannel<ValueType>> | undefined, step: number): Checkpoint;
|
package/dist/channels/base.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { deepCopy } from "
|
|
2
|
-
import { uuid6 } from "../checkpoint/id.js";
|
|
1
|
+
import { deepCopy, uuid6, } from "@langchain/langgraph-checkpoint";
|
|
3
2
|
import { EmptyChannelError } from "../errors.js";
|
|
4
3
|
export class BaseChannel {
|
|
5
4
|
constructor() {
|
|
@@ -16,6 +15,14 @@ export class BaseChannel {
|
|
|
16
15
|
value: void 0
|
|
17
16
|
});
|
|
18
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Mark the current value of the channel as consumed. By default, no-op.
|
|
20
|
+
* This is called by Pregel before the start of the next step, for all
|
|
21
|
+
* channels that triggered a node. If the channel was updated, return true.
|
|
22
|
+
*/
|
|
23
|
+
consume() {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
19
26
|
}
|
|
20
27
|
export function emptyChannels(channels, checkpoint) {
|
|
21
28
|
const newChannels = {};
|
|
@@ -29,18 +36,24 @@ export function emptyChannels(channels, checkpoint) {
|
|
|
29
36
|
}
|
|
30
37
|
export function createCheckpoint(checkpoint, channels, step) {
|
|
31
38
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
let values;
|
|
40
|
+
if (channels === undefined) {
|
|
41
|
+
values = checkpoint.channel_values;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
values = {};
|
|
45
|
+
for (const k of Object.keys(channels)) {
|
|
46
|
+
try {
|
|
47
|
+
values[k] = channels[k].checkpoint();
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
49
|
}
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (error.name === EmptyChannelError.unminifiable_name) {
|
|
52
|
+
// no-op
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw error; // Rethrow unexpected errors
|
|
56
|
+
}
|
|
44
57
|
}
|
|
45
58
|
}
|
|
46
59
|
}
|
package/dist/channels/binop.cjs
CHANGED
|
@@ -47,7 +47,7 @@ class BinaryOperatorAggregate extends index_js_1.BaseChannel {
|
|
|
47
47
|
update(values) {
|
|
48
48
|
let newValues = values;
|
|
49
49
|
if (!newValues.length)
|
|
50
|
-
return;
|
|
50
|
+
return false;
|
|
51
51
|
if (this.value === undefined) {
|
|
52
52
|
[this.value] = newValues;
|
|
53
53
|
newValues = newValues.slice(1);
|
|
@@ -57,6 +57,7 @@ class BinaryOperatorAggregate extends index_js_1.BaseChannel {
|
|
|
57
57
|
this.value = this.operator(this.value, value);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
return true;
|
|
60
61
|
}
|
|
61
62
|
get() {
|
|
62
63
|
if (this.value === undefined) {
|
package/dist/channels/binop.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare class BinaryOperatorAggregate<ValueType, UpdateType = ValueType>
|
|
|
10
10
|
initialValueFactory?: () => ValueType;
|
|
11
11
|
constructor(operator: BinaryOperator<ValueType, UpdateType>, initialValueFactory?: () => ValueType);
|
|
12
12
|
fromCheckpoint(checkpoint?: ValueType): this;
|
|
13
|
-
update(values: UpdateType[]):
|
|
13
|
+
update(values: UpdateType[]): boolean;
|
|
14
14
|
get(): ValueType;
|
|
15
15
|
checkpoint(): ValueType;
|
|
16
16
|
}
|
package/dist/channels/binop.js
CHANGED
|
@@ -44,7 +44,7 @@ export class BinaryOperatorAggregate extends BaseChannel {
|
|
|
44
44
|
update(values) {
|
|
45
45
|
let newValues = values;
|
|
46
46
|
if (!newValues.length)
|
|
47
|
-
return;
|
|
47
|
+
return false;
|
|
48
48
|
if (this.value === undefined) {
|
|
49
49
|
[this.value] = newValues;
|
|
50
50
|
newValues = newValues.slice(1);
|
|
@@ -54,6 +54,7 @@ export class BinaryOperatorAggregate extends BaseChannel {
|
|
|
54
54
|
this.value = this.operator(this.value, value);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
return true;
|
|
57
58
|
}
|
|
58
59
|
get() {
|
|
59
60
|
if (this.value === undefined) {
|
|
@@ -4,6 +4,9 @@ exports.DynamicBarrierValue = void 0;
|
|
|
4
4
|
const errors_js_1 = require("../errors.cjs");
|
|
5
5
|
const index_js_1 = require("./index.cjs");
|
|
6
6
|
const named_barrier_value_js_1 = require("./named_barrier_value.cjs");
|
|
7
|
+
function isWaitForNames(v) {
|
|
8
|
+
return v.__names !== undefined;
|
|
9
|
+
}
|
|
7
10
|
/**
|
|
8
11
|
A channel that switches between two states
|
|
9
12
|
|
|
@@ -46,32 +49,41 @@ class DynamicBarrierValue extends index_js_1.BaseChannel {
|
|
|
46
49
|
return empty;
|
|
47
50
|
}
|
|
48
51
|
update(values) {
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"__names" in v &&
|
|
57
|
-
Object.keys(v).join(",") === "__names" &&
|
|
58
|
-
Array.isArray(v.__names));
|
|
59
|
-
if (newNames.length > 1) {
|
|
60
|
-
throw new errors_js_1.InvalidUpdateError(`Expected at most one WaitForNames object, got ${newNames.length}`);
|
|
61
|
-
}
|
|
62
|
-
else if (newNames.length === 1) {
|
|
63
|
-
this.names = new Set(newNames[0].__names);
|
|
52
|
+
const waitForNames = values.filter(isWaitForNames);
|
|
53
|
+
if (waitForNames.length > 0) {
|
|
54
|
+
if (waitForNames.length > 1) {
|
|
55
|
+
throw new errors_js_1.InvalidUpdateError("Received multiple WaitForNames updates in the same step.");
|
|
56
|
+
}
|
|
57
|
+
this.names = new Set(waitForNames[0].__names);
|
|
58
|
+
return true;
|
|
64
59
|
}
|
|
65
|
-
else if (this.names) {
|
|
60
|
+
else if (this.names !== undefined) {
|
|
61
|
+
let updated = false;
|
|
66
62
|
for (const value of values) {
|
|
63
|
+
if (isWaitForNames(value)) {
|
|
64
|
+
throw new Error("Assertion Error: Received unexpected WaitForNames instance.");
|
|
65
|
+
}
|
|
67
66
|
if (this.names.has(value)) {
|
|
68
|
-
this.seen.
|
|
67
|
+
if (!this.seen.has(value)) {
|
|
68
|
+
this.seen.add(value);
|
|
69
|
+
updated = true;
|
|
70
|
+
}
|
|
69
71
|
}
|
|
70
72
|
else {
|
|
71
|
-
throw new errors_js_1.InvalidUpdateError(`Value ${value} not in
|
|
73
|
+
throw new errors_js_1.InvalidUpdateError(`Value ${value} not in ${[...this.names]}`);
|
|
72
74
|
}
|
|
73
75
|
}
|
|
76
|
+
return updated;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
consume() {
|
|
81
|
+
if (this.seen && this.names && (0, named_barrier_value_js_1.areSetsEqual)(this.seen, this.names)) {
|
|
82
|
+
this.seen = new Set();
|
|
83
|
+
this.names = undefined;
|
|
84
|
+
return true;
|
|
74
85
|
}
|
|
86
|
+
return false;
|
|
75
87
|
}
|
|
76
88
|
// If we have not yet seen all the node names we want to wait for,
|
|
77
89
|
// throw an error to prevent continuing.
|
|
@@ -20,7 +20,8 @@ export declare class DynamicBarrierValue<Value> extends BaseChannel<void, Value
|
|
|
20
20
|
seen: Set<Value>;
|
|
21
21
|
constructor();
|
|
22
22
|
fromCheckpoint(checkpoint?: [Value[] | undefined, Value[]]): this;
|
|
23
|
-
update(values: (Value | WaitForNames<Value>)[]):
|
|
23
|
+
update(values: (Value | WaitForNames<Value>)[]): boolean;
|
|
24
|
+
consume(): boolean;
|
|
24
25
|
get(): void;
|
|
25
26
|
checkpoint(): [Value[] | undefined, Value[]];
|
|
26
27
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { EmptyChannelError, InvalidUpdateError } from "../errors.js";
|
|
2
2
|
import { BaseChannel } from "./index.js";
|
|
3
3
|
import { areSetsEqual } from "./named_barrier_value.js";
|
|
4
|
+
function isWaitForNames(v) {
|
|
5
|
+
return v.__names !== undefined;
|
|
6
|
+
}
|
|
4
7
|
/**
|
|
5
8
|
A channel that switches between two states
|
|
6
9
|
|
|
@@ -43,32 +46,41 @@ export class DynamicBarrierValue extends BaseChannel {
|
|
|
43
46
|
return empty;
|
|
44
47
|
}
|
|
45
48
|
update(values) {
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"__names" in v &&
|
|
54
|
-
Object.keys(v).join(",") === "__names" &&
|
|
55
|
-
Array.isArray(v.__names));
|
|
56
|
-
if (newNames.length > 1) {
|
|
57
|
-
throw new InvalidUpdateError(`Expected at most one WaitForNames object, got ${newNames.length}`);
|
|
58
|
-
}
|
|
59
|
-
else if (newNames.length === 1) {
|
|
60
|
-
this.names = new Set(newNames[0].__names);
|
|
49
|
+
const waitForNames = values.filter(isWaitForNames);
|
|
50
|
+
if (waitForNames.length > 0) {
|
|
51
|
+
if (waitForNames.length > 1) {
|
|
52
|
+
throw new InvalidUpdateError("Received multiple WaitForNames updates in the same step.");
|
|
53
|
+
}
|
|
54
|
+
this.names = new Set(waitForNames[0].__names);
|
|
55
|
+
return true;
|
|
61
56
|
}
|
|
62
|
-
else if (this.names) {
|
|
57
|
+
else if (this.names !== undefined) {
|
|
58
|
+
let updated = false;
|
|
63
59
|
for (const value of values) {
|
|
60
|
+
if (isWaitForNames(value)) {
|
|
61
|
+
throw new Error("Assertion Error: Received unexpected WaitForNames instance.");
|
|
62
|
+
}
|
|
64
63
|
if (this.names.has(value)) {
|
|
65
|
-
this.seen.
|
|
64
|
+
if (!this.seen.has(value)) {
|
|
65
|
+
this.seen.add(value);
|
|
66
|
+
updated = true;
|
|
67
|
+
}
|
|
66
68
|
}
|
|
67
69
|
else {
|
|
68
|
-
throw new InvalidUpdateError(`Value ${value} not in
|
|
70
|
+
throw new InvalidUpdateError(`Value ${value} not in ${[...this.names]}`);
|
|
69
71
|
}
|
|
70
72
|
}
|
|
73
|
+
return updated;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
consume() {
|
|
78
|
+
if (this.seen && this.names && areSetsEqual(this.seen, this.names)) {
|
|
79
|
+
this.seen = new Set();
|
|
80
|
+
this.names = undefined;
|
|
81
|
+
return true;
|
|
71
82
|
}
|
|
83
|
+
return false;
|
|
72
84
|
}
|
|
73
85
|
// If we have not yet seen all the node names we want to wait for,
|
|
74
86
|
// throw an error to prevent continuing.
|
|
@@ -38,15 +38,17 @@ class EphemeralValue extends index_js_1.BaseChannel {
|
|
|
38
38
|
}
|
|
39
39
|
update(values) {
|
|
40
40
|
if (values.length === 0) {
|
|
41
|
+
const updated = this.value !== undefined;
|
|
41
42
|
// If there are no updates for this specific channel at the end of the step, wipe it.
|
|
42
43
|
this.value = undefined;
|
|
43
|
-
return;
|
|
44
|
+
return updated;
|
|
44
45
|
}
|
|
45
46
|
if (values.length !== 1 && this.guard) {
|
|
46
47
|
throw new errors_js_1.InvalidUpdateError("EphemeralValue can only receive one value per step.");
|
|
47
48
|
}
|
|
48
49
|
// eslint-disable-next-line prefer-destructuring
|
|
49
50
|
this.value = values[values.length - 1];
|
|
51
|
+
return true;
|
|
50
52
|
}
|
|
51
53
|
get() {
|
|
52
54
|
if (this.value === undefined) {
|
|
@@ -8,7 +8,7 @@ export declare class EphemeralValue<Value> extends BaseChannel<Value, Value, Val
|
|
|
8
8
|
value?: Value;
|
|
9
9
|
constructor(guard?: boolean);
|
|
10
10
|
fromCheckpoint(checkpoint?: Value): this;
|
|
11
|
-
update(values: Value[]):
|
|
11
|
+
update(values: Value[]): boolean;
|
|
12
12
|
get(): Value;
|
|
13
13
|
checkpoint(): Value;
|
|
14
14
|
}
|
|
@@ -35,15 +35,17 @@ export class EphemeralValue extends BaseChannel {
|
|
|
35
35
|
}
|
|
36
36
|
update(values) {
|
|
37
37
|
if (values.length === 0) {
|
|
38
|
+
const updated = this.value !== undefined;
|
|
38
39
|
// If there are no updates for this specific channel at the end of the step, wipe it.
|
|
39
40
|
this.value = undefined;
|
|
40
|
-
return;
|
|
41
|
+
return updated;
|
|
41
42
|
}
|
|
42
43
|
if (values.length !== 1 && this.guard) {
|
|
43
44
|
throw new InvalidUpdateError("EphemeralValue can only receive one value per step.");
|
|
44
45
|
}
|
|
45
46
|
// eslint-disable-next-line prefer-destructuring
|
|
46
47
|
this.value = values[values.length - 1];
|
|
48
|
+
return true;
|
|
47
49
|
}
|
|
48
50
|
get() {
|
|
49
51
|
if (this.value === undefined) {
|
|
@@ -35,13 +35,14 @@ class LastValue extends index_js_1.BaseChannel {
|
|
|
35
35
|
}
|
|
36
36
|
update(values) {
|
|
37
37
|
if (values.length === 0) {
|
|
38
|
-
return;
|
|
38
|
+
return false;
|
|
39
39
|
}
|
|
40
40
|
if (values.length !== 1) {
|
|
41
|
-
throw new errors_js_1.InvalidUpdateError();
|
|
41
|
+
throw new errors_js_1.InvalidUpdateError("LastValue can only receive one value per step.");
|
|
42
42
|
}
|
|
43
43
|
// eslint-disable-next-line prefer-destructuring
|
|
44
44
|
this.value = values[values.length - 1];
|
|
45
|
+
return true;
|
|
45
46
|
}
|
|
46
47
|
get() {
|
|
47
48
|
if (this.value === undefined) {
|
|
@@ -10,7 +10,7 @@ export declare class LastValue<Value> extends BaseChannel<Value, Value, Value> {
|
|
|
10
10
|
lc_graph_name: string;
|
|
11
11
|
value?: Value;
|
|
12
12
|
fromCheckpoint(checkpoint?: Value): this;
|
|
13
|
-
update(values: Value[]):
|
|
13
|
+
update(values: Value[]): boolean;
|
|
14
14
|
get(): Value;
|
|
15
15
|
checkpoint(): Value;
|
|
16
16
|
}
|
|
@@ -32,13 +32,14 @@ export class LastValue extends BaseChannel {
|
|
|
32
32
|
}
|
|
33
33
|
update(values) {
|
|
34
34
|
if (values.length === 0) {
|
|
35
|
-
return;
|
|
35
|
+
return false;
|
|
36
36
|
}
|
|
37
37
|
if (values.length !== 1) {
|
|
38
|
-
throw new InvalidUpdateError();
|
|
38
|
+
throw new InvalidUpdateError("LastValue can only receive one value per step.");
|
|
39
39
|
}
|
|
40
40
|
// eslint-disable-next-line prefer-destructuring
|
|
41
41
|
this.value = values[values.length - 1];
|
|
42
|
+
return true;
|
|
42
43
|
}
|
|
43
44
|
get() {
|
|
44
45
|
if (this.value === undefined) {
|
|
@@ -43,18 +43,19 @@ class NamedBarrierValue extends index_js_1.BaseChannel {
|
|
|
43
43
|
return empty;
|
|
44
44
|
}
|
|
45
45
|
update(values) {
|
|
46
|
-
|
|
47
|
-
if ((0, exports.areSetsEqual)(this.names, this.seen)) {
|
|
48
|
-
this.seen = new Set();
|
|
49
|
-
}
|
|
46
|
+
let updated = false;
|
|
50
47
|
for (const nodeName of values) {
|
|
51
48
|
if (this.names.has(nodeName)) {
|
|
52
|
-
this.seen.
|
|
49
|
+
if (!this.seen.has(nodeName)) {
|
|
50
|
+
this.seen.add(nodeName);
|
|
51
|
+
updated = true;
|
|
52
|
+
}
|
|
53
53
|
}
|
|
54
54
|
else {
|
|
55
|
-
throw new
|
|
55
|
+
throw new errors_js_1.InvalidUpdateError(`Value ${JSON.stringify(nodeName)} not in names ${JSON.stringify(this.names)}`);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
return updated;
|
|
58
59
|
}
|
|
59
60
|
// If we have not yet seen all the node names we want to wait for,
|
|
60
61
|
// throw an error to prevent continuing.
|
|
@@ -67,5 +68,12 @@ class NamedBarrierValue extends index_js_1.BaseChannel {
|
|
|
67
68
|
checkpoint() {
|
|
68
69
|
return [...this.seen];
|
|
69
70
|
}
|
|
71
|
+
consume() {
|
|
72
|
+
if (this.seen && this.names && (0, exports.areSetsEqual)(this.seen, this.names)) {
|
|
73
|
+
this.seen = new Set();
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
70
78
|
}
|
|
71
79
|
exports.NamedBarrierValue = NamedBarrierValue;
|
|
@@ -12,7 +12,8 @@ export declare class NamedBarrierValue<Value> extends BaseChannel<void, Value, V
|
|
|
12
12
|
seen: Set<Value>;
|
|
13
13
|
constructor(names: Set<Value>);
|
|
14
14
|
fromCheckpoint(checkpoint?: Value[]): this;
|
|
15
|
-
update(values: Value[]):
|
|
15
|
+
update(values: Value[]): boolean;
|
|
16
16
|
get(): void;
|
|
17
17
|
checkpoint(): Value[];
|
|
18
|
+
consume(): boolean;
|
|
18
19
|
}
|