@langchain/langgraph 0.1.1 → 0.1.3
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 +2 -2
- package/dist/constants.cjs +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/graph/annotation.cjs +78 -4
- package/dist/graph/annotation.d.ts +82 -5
- package/dist/graph/annotation.js +77 -2
- package/dist/graph/graph.cjs +14 -8
- package/dist/graph/graph.d.ts +14 -5
- package/dist/graph/graph.js +14 -8
- package/dist/graph/message.cjs +6 -0
- package/dist/graph/message.d.ts +6 -0
- package/dist/graph/message.js +6 -0
- package/dist/graph/messages_annotation.cjs +5 -0
- package/dist/graph/messages_annotation.d.ts +5 -0
- package/dist/graph/messages_annotation.js +5 -0
- package/dist/graph/state.cjs +84 -3
- package/dist/graph/state.d.ts +75 -5
- package/dist/graph/state.js +86 -5
- package/dist/prebuilt/agent_executor.cjs +1 -0
- package/dist/prebuilt/agent_executor.d.ts +2 -0
- package/dist/prebuilt/agent_executor.js +1 -0
- package/dist/prebuilt/chat_agent_executor.cjs +1 -0
- package/dist/prebuilt/chat_agent_executor.d.ts +2 -0
- package/dist/prebuilt/chat_agent_executor.js +1 -0
- package/dist/prebuilt/react_agent_executor.cjs +1 -1
- package/dist/prebuilt/react_agent_executor.js +2 -2
- package/dist/pregel/algo.cjs +3 -41
- package/dist/pregel/algo.d.ts +0 -5
- package/dist/pregel/algo.js +2 -39
- package/dist/pregel/debug.d.ts +1 -1
- package/dist/pregel/index.cjs +17 -30
- package/dist/pregel/index.d.ts +2 -0
- package/dist/pregel/index.js +18 -31
- package/dist/pregel/loop.cjs +5 -2
- package/dist/pregel/loop.js +5 -2
- package/dist/pregel/read.cjs +19 -1
- package/dist/pregel/read.d.ts +5 -0
- package/dist/pregel/read.js +19 -1
- package/dist/pregel/retry.cjs +147 -0
- package/dist/pregel/retry.d.ts +11 -0
- package/dist/pregel/retry.js +143 -0
- package/dist/pregel/types.d.ts +4 -2
- package/dist/pregel/utils.d.ts +26 -0
- package/dist/web.d.ts +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { GraphInterrupt } from "../errors.js";
|
|
2
|
+
export const DEFAULT_INITIAL_INTERVAL = 500;
|
|
3
|
+
export const DEFAULT_BACKOFF_FACTOR = 2;
|
|
4
|
+
export const DEFAULT_MAX_INTERVAL = 128000;
|
|
5
|
+
export const DEFAULT_MAX_RETRIES = 3;
|
|
6
|
+
const DEFAULT_STATUS_NO_RETRY = [
|
|
7
|
+
400,
|
|
8
|
+
401,
|
|
9
|
+
402,
|
|
10
|
+
403,
|
|
11
|
+
404,
|
|
12
|
+
405,
|
|
13
|
+
406,
|
|
14
|
+
407,
|
|
15
|
+
409, // Conflict
|
|
16
|
+
];
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
const DEFAULT_RETRY_ON_HANDLER = (error) => {
|
|
19
|
+
if (error.message.startsWith("Cancel") ||
|
|
20
|
+
error.message.startsWith("AbortError") ||
|
|
21
|
+
error.name === "AbortError") {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
if (error?.code === "ECONNABORTED") {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const status =
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
error?.response?.status ?? error?.status;
|
|
31
|
+
if (status && DEFAULT_STATUS_NO_RETRY.includes(+status)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
if (error?.error?.code === "insufficient_quota") {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
export async function* executeTasksWithRetry(
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
tasks, options
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
) {
|
|
45
|
+
const { stepTimeout, retryPolicy } = options ?? {};
|
|
46
|
+
let signal = options?.signal;
|
|
47
|
+
// Start tasks
|
|
48
|
+
const executingTasksMap = Object.fromEntries(tasks.map((pregelTask) => {
|
|
49
|
+
return [pregelTask.id, _runWithRetry(pregelTask, retryPolicy)];
|
|
50
|
+
}));
|
|
51
|
+
if (stepTimeout && signal) {
|
|
52
|
+
if ("any" in AbortSignal) {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
signal = AbortSignal.any([
|
|
55
|
+
signal,
|
|
56
|
+
AbortSignal.timeout(stepTimeout),
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (stepTimeout) {
|
|
61
|
+
signal = AbortSignal.timeout(stepTimeout);
|
|
62
|
+
}
|
|
63
|
+
// Abort if signal is aborted
|
|
64
|
+
signal?.throwIfAborted();
|
|
65
|
+
let listener;
|
|
66
|
+
const signalPromise = new Promise((_resolve, reject) => {
|
|
67
|
+
listener = () => reject(new Error("Abort"));
|
|
68
|
+
signal?.addEventListener("abort", listener);
|
|
69
|
+
}).finally(() => signal?.removeEventListener("abort", listener));
|
|
70
|
+
while (Object.keys(executingTasksMap).length > 0) {
|
|
71
|
+
const { task, error } = await Promise.race([
|
|
72
|
+
...Object.values(executingTasksMap),
|
|
73
|
+
signalPromise,
|
|
74
|
+
]);
|
|
75
|
+
if (error !== undefined) {
|
|
76
|
+
// TODO: don't stop others if exception is interrupt
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
yield task;
|
|
80
|
+
delete executingTasksMap[task.id];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function _runWithRetry(
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
pregelTask, retryPolicy) {
|
|
86
|
+
const resolvedRetryPolicy = pregelTask.retry_policy ?? retryPolicy;
|
|
87
|
+
let interval = resolvedRetryPolicy !== undefined
|
|
88
|
+
? resolvedRetryPolicy.initialInterval ?? DEFAULT_INITIAL_INTERVAL
|
|
89
|
+
: 0;
|
|
90
|
+
let attempts = 0;
|
|
91
|
+
let error;
|
|
92
|
+
let result;
|
|
93
|
+
// eslint-disable-next-line no-constant-condition
|
|
94
|
+
while (true) {
|
|
95
|
+
// Modify writes in place to clear any previous retries
|
|
96
|
+
while (pregelTask.writes.length > 0) {
|
|
97
|
+
pregelTask.writes.pop();
|
|
98
|
+
}
|
|
99
|
+
error = undefined;
|
|
100
|
+
try {
|
|
101
|
+
result = await pregelTask.proc.invoke(pregelTask.input, pregelTask.config);
|
|
102
|
+
break;
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
error = e;
|
|
107
|
+
error.pregelTaskId = pregelTask.id;
|
|
108
|
+
if (error.name === GraphInterrupt.unminifiable_name) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (resolvedRetryPolicy === undefined) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
attempts += 1;
|
|
115
|
+
// check if we should give up
|
|
116
|
+
if (attempts >= (resolvedRetryPolicy.maxAttempts ?? DEFAULT_MAX_RETRIES)) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
const retryOn = resolvedRetryPolicy.retryOn ?? DEFAULT_RETRY_ON_HANDLER;
|
|
120
|
+
if (!retryOn(error)) {
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
interval = Math.min(resolvedRetryPolicy.maxInterval ?? DEFAULT_MAX_INTERVAL, interval * (resolvedRetryPolicy.backoffFactor ?? DEFAULT_BACKOFF_FACTOR));
|
|
124
|
+
const intervalWithJitter = resolvedRetryPolicy.jitter
|
|
125
|
+
? Math.floor(interval + Math.random() * 1000)
|
|
126
|
+
: interval;
|
|
127
|
+
// sleep before retrying
|
|
128
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
129
|
+
await new Promise((resolve) => setTimeout(resolve, intervalWithJitter));
|
|
130
|
+
// log the retry
|
|
131
|
+
const errorName = error.name ??
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
|
+
error.constructor.unminifiable_name ??
|
|
134
|
+
error.constructor.name;
|
|
135
|
+
console.log(`Retrying task "${pregelTask.name}" after ${interval.toFixed(2)} seconds (attempt ${attempts}) after ${errorName}: ${error}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
task: pregelTask,
|
|
140
|
+
result,
|
|
141
|
+
error,
|
|
142
|
+
};
|
|
143
|
+
}
|
package/dist/pregel/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Runnable, RunnableConfig } from "@langchain/core/runnables";
|
|
|
2
2
|
import type { PendingWrite, CheckpointMetadata, BaseCheckpointSaver } from "@langchain/langgraph-checkpoint";
|
|
3
3
|
import type { BaseChannel } from "../channels/base.js";
|
|
4
4
|
import type { PregelNode } from "./read.js";
|
|
5
|
+
import { RetryPolicy } from "./utils.js";
|
|
5
6
|
export type StreamMode = "values" | "updates" | "debug";
|
|
6
7
|
/**
|
|
7
8
|
* Construct a type with a set of properties K of type T
|
|
@@ -41,6 +42,7 @@ export interface PregelInterface<Nn extends StrRecord<string, PregelNode>, Cc ex
|
|
|
41
42
|
*/
|
|
42
43
|
debug?: boolean;
|
|
43
44
|
checkpointer?: BaseCheckpointSaver;
|
|
45
|
+
retryPolicy?: RetryPolicy;
|
|
44
46
|
}
|
|
45
47
|
export type PregelParams<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>> = Omit<PregelInterface<Nn, Cc>, "streamChannelsAsIs">;
|
|
46
48
|
export interface PregelTaskDescription {
|
|
@@ -53,9 +55,9 @@ export interface PregelExecutableTask<N extends PropertyKey, C extends PropertyK
|
|
|
53
55
|
readonly input: unknown;
|
|
54
56
|
readonly proc: Runnable;
|
|
55
57
|
readonly writes: PendingWrite<C>[];
|
|
56
|
-
readonly config
|
|
58
|
+
readonly config?: RunnableConfig;
|
|
57
59
|
readonly triggers: Array<string>;
|
|
58
|
-
readonly retry_policy?:
|
|
60
|
+
readonly retry_policy?: RetryPolicy;
|
|
59
61
|
readonly id: string;
|
|
60
62
|
}
|
|
61
63
|
export interface StateSnapshot {
|
package/dist/pregel/utils.d.ts
CHANGED
|
@@ -8,3 +8,29 @@ export declare function _getIdMetadata(metadata: Record<string, unknown>): {
|
|
|
8
8
|
langgraph_triggers: unknown;
|
|
9
9
|
langgraph_task_idx: unknown;
|
|
10
10
|
};
|
|
11
|
+
export type RetryPolicy = {
|
|
12
|
+
/**
|
|
13
|
+
* Amount of time that must elapse before the first retry occurs in milliseconds.
|
|
14
|
+
* @default 500
|
|
15
|
+
*/
|
|
16
|
+
initialInterval?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Multiplier by which the interval increases after each retry.
|
|
19
|
+
* @default 2
|
|
20
|
+
*/
|
|
21
|
+
backoffFactor?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Maximum amount of time that may elapse between retries in milliseconds.
|
|
24
|
+
* @default 128000
|
|
25
|
+
*/
|
|
26
|
+
maxInterval?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Maximum amount of time that may elapse between retries.
|
|
29
|
+
* @default 3
|
|
30
|
+
*/
|
|
31
|
+
maxAttempts?: number;
|
|
32
|
+
/** Whether to add random jitter to the interval between retries. */
|
|
33
|
+
jitter?: boolean;
|
|
34
|
+
/** A function that returns True for exceptions that should trigger a retry. */
|
|
35
|
+
retryOn?: (e: any) => boolean;
|
|
36
|
+
};
|
package/dist/web.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { END, Graph, type StateGraphArgs, START, StateGraph, type CompiledStateGraph, MessageGraph, messagesStateReducer, Annotation, type StateType, type UpdateType, type CompiledGraph, } from "./graph/index.js";
|
|
2
2
|
export { GraphRecursionError, GraphValueError, InvalidUpdateError, EmptyChannelError, } from "./errors.js";
|
|
3
|
+
export { type RetryPolicy } from "./pregel/utils.js";
|
|
3
4
|
export { Send } from "./constants.js";
|
|
4
5
|
export { MemorySaver, type Checkpoint, type CheckpointMetadata, type CheckpointTuple, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "@langchain/langgraph-checkpoint";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/langgraph",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "LangGraph",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "yarn turbo:command build:internal --filter=@langchain/langgraph",
|
|
17
|
-
"build:internal": "yarn lc_build --create-entrypoints --pre --tree-shaking",
|
|
17
|
+
"build:internal": "yarn clean && yarn lc_build --create-entrypoints --pre --tree-shaking",
|
|
18
|
+
"clean": "rm -rf dist/ dist-cjs/ .turbo/",
|
|
18
19
|
"lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
|
|
19
20
|
"lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
|
|
20
21
|
"lint": "yarn lint:eslint && yarn lint:dpdm",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"license": "MIT",
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"@langchain/core": ">=0.2.20 <0.3.0",
|
|
34
|
-
"@langchain/langgraph-checkpoint": "~0.0.
|
|
35
|
+
"@langchain/langgraph-checkpoint": "~0.0.3",
|
|
35
36
|
"@langchain/langgraph-checkpoint-sqlite": "~0.0.1",
|
|
36
37
|
"double-ended-queue": "^2.1.0-0",
|
|
37
38
|
"uuid": "^10.0.0",
|
|
@@ -49,8 +50,9 @@
|
|
|
49
50
|
"@jest/globals": "^29.5.0",
|
|
50
51
|
"@langchain/anthropic": "^0.2.12",
|
|
51
52
|
"@langchain/community": "^0.2.25",
|
|
53
|
+
"@langchain/core": "^0.2.29",
|
|
52
54
|
"@langchain/openai": "^0.2.4",
|
|
53
|
-
"@langchain/scripts": ">=0.1.
|
|
55
|
+
"@langchain/scripts": ">=0.1.2 <0.2.0",
|
|
54
56
|
"@swc/core": "^1.3.90",
|
|
55
57
|
"@swc/jest": "^0.2.29",
|
|
56
58
|
"@tsconfig/recommended": "^1.0.3",
|