@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.
Files changed (86) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -15
  3. package/dist/channels/any_value.cjs +3 -1
  4. package/dist/channels/any_value.d.ts +1 -1
  5. package/dist/channels/any_value.js +3 -1
  6. package/dist/channels/base.cjs +28 -15
  7. package/dist/channels/base.d.ts +14 -4
  8. package/dist/channels/base.js +26 -13
  9. package/dist/channels/binop.cjs +2 -1
  10. package/dist/channels/binop.d.ts +1 -1
  11. package/dist/channels/binop.js +2 -1
  12. package/dist/channels/dynamic_barrier_value.cjs +30 -18
  13. package/dist/channels/dynamic_barrier_value.d.ts +2 -1
  14. package/dist/channels/dynamic_barrier_value.js +30 -18
  15. package/dist/channels/ephemeral_value.cjs +3 -1
  16. package/dist/channels/ephemeral_value.d.ts +1 -1
  17. package/dist/channels/ephemeral_value.js +3 -1
  18. package/dist/channels/last_value.cjs +3 -2
  19. package/dist/channels/last_value.d.ts +1 -1
  20. package/dist/channels/last_value.js +3 -2
  21. package/dist/channels/named_barrier_value.cjs +14 -6
  22. package/dist/channels/named_barrier_value.d.ts +2 -1
  23. package/dist/channels/named_barrier_value.js +15 -7
  24. package/dist/channels/topic.cjs +10 -11
  25. package/dist/channels/topic.d.ts +1 -1
  26. package/dist/channels/topic.js +10 -11
  27. package/dist/checkpoint/sqlite.cjs +14 -170
  28. package/dist/checkpoint/sqlite.d.ts +1 -14
  29. package/dist/checkpoint/sqlite.js +1 -166
  30. package/dist/constants.cjs +17 -1
  31. package/dist/constants.d.ts +7 -0
  32. package/dist/constants.js +16 -0
  33. package/dist/errors.cjs +21 -1
  34. package/dist/errors.d.ts +8 -0
  35. package/dist/errors.js +18 -0
  36. package/dist/graph/graph.cjs +6 -3
  37. package/dist/graph/graph.d.ts +7 -3
  38. package/dist/graph/graph.js +7 -4
  39. package/dist/graph/index.d.ts +1 -1
  40. package/dist/graph/state.cjs +9 -8
  41. package/dist/graph/state.d.ts +1 -1
  42. package/dist/graph/state.js +9 -8
  43. package/dist/prebuilt/react_agent_executor.d.ts +1 -1
  44. package/dist/pregel/algo.cjs +391 -0
  45. package/dist/pregel/algo.d.ts +35 -0
  46. package/dist/pregel/algo.js +381 -0
  47. package/dist/pregel/debug.cjs +155 -9
  48. package/dist/pregel/debug.d.ts +40 -2
  49. package/dist/pregel/debug.js +147 -7
  50. package/dist/pregel/index.cjs +286 -512
  51. package/dist/pregel/index.d.ts +66 -65
  52. package/dist/pregel/index.js +285 -506
  53. package/dist/pregel/io.cjs +2 -2
  54. package/dist/pregel/io.d.ts +5 -4
  55. package/dist/pregel/io.js +2 -2
  56. package/dist/pregel/loop.cjs +432 -0
  57. package/dist/pregel/loop.d.ts +83 -0
  58. package/dist/pregel/loop.js +425 -0
  59. package/dist/pregel/types.d.ts +56 -4
  60. package/dist/pregel/utils.cjs +48 -0
  61. package/dist/pregel/utils.d.ts +10 -0
  62. package/dist/pregel/utils.js +41 -0
  63. package/dist/pregel/write.cjs +3 -1
  64. package/dist/pregel/write.js +3 -1
  65. package/dist/utils.cjs +21 -1
  66. package/dist/utils.d.ts +4 -0
  67. package/dist/utils.js +18 -0
  68. package/dist/web.cjs +6 -7
  69. package/dist/web.d.ts +2 -4
  70. package/dist/web.js +1 -2
  71. package/package.json +6 -12
  72. package/dist/checkpoint/base.cjs +0 -66
  73. package/dist/checkpoint/base.d.ts +0 -73
  74. package/dist/checkpoint/base.js +0 -57
  75. package/dist/checkpoint/id.cjs +0 -8
  76. package/dist/checkpoint/id.d.ts +0 -1
  77. package/dist/checkpoint/id.js +0 -4
  78. package/dist/checkpoint/index.cjs +0 -9
  79. package/dist/checkpoint/index.d.ts +0 -2
  80. package/dist/checkpoint/index.js +0 -2
  81. package/dist/checkpoint/memory.cjs +0 -82
  82. package/dist/checkpoint/memory.d.ts +0 -10
  83. package/dist/checkpoint/memory.js +0 -78
  84. package/dist/serde/base.cjs +0 -8
  85. package/dist/serde/base.d.ts +0 -12
  86. package/dist/serde/base.js +0 -5
@@ -0,0 +1,381 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import { mergeConfigs, patchConfig, } from "@langchain/core/runnables";
3
+ import { copyCheckpoint, uuid5, } from "@langchain/langgraph-checkpoint";
4
+ import { createCheckpoint, emptyChannels, } from "../channels/base.js";
5
+ import { readChannel, readChannels } from "./io.js";
6
+ import { _isSend, _isSendInterface, CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_READ, CONFIG_KEY_RESUMING, CONFIG_KEY_SEND, INTERRUPT, RESERVED, TAG_HIDDEN, TASKS, } from "../constants.js";
7
+ import { EmptyChannelError, InvalidUpdateError } from "../errors.js";
8
+ import { _getIdMetadata, getNullChannelVersion } from "./utils.js";
9
+ export const increment = (current) => {
10
+ return current !== undefined ? current + 1 : 1;
11
+ };
12
+ export async function* executeTasks(tasks, stepTimeout, signal
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ ) {
15
+ if (stepTimeout && signal) {
16
+ if ("any" in AbortSignal) {
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ signal = AbortSignal.any([
19
+ signal,
20
+ AbortSignal.timeout(stepTimeout),
21
+ ]);
22
+ }
23
+ }
24
+ else if (stepTimeout) {
25
+ signal = AbortSignal.timeout(stepTimeout);
26
+ }
27
+ // Abort if signal is aborted
28
+ signal?.throwIfAborted();
29
+ // Start all tasks
30
+ const executingTasks = Object.fromEntries(Object.entries(tasks).map(([taskId, task]) => {
31
+ return [taskId, task()];
32
+ }));
33
+ let listener;
34
+ const signalPromise = new Promise((_resolve, reject) => {
35
+ listener = () => reject(new Error("Abort"));
36
+ signal?.addEventListener("abort", listener);
37
+ }).finally(() => signal?.removeEventListener("abort", listener));
38
+ while (Object.keys(executingTasks).length > 0) {
39
+ const { task, error } = await Promise.race([
40
+ ...Object.values(executingTasks),
41
+ signalPromise,
42
+ ]);
43
+ if (error !== undefined) {
44
+ // TODO: don't stop others if exception is interrupt
45
+ throw error;
46
+ }
47
+ yield task;
48
+ delete executingTasks[task.id];
49
+ }
50
+ }
51
+ export function shouldInterrupt(checkpoint, interruptNodes, tasks) {
52
+ const versionValues = Object.values(checkpoint.channel_versions);
53
+ const versionType = versionValues.length > 0 ? typeof versionValues[0] : undefined;
54
+ let nullVersion;
55
+ if (versionType === "number") {
56
+ nullVersion = 0;
57
+ }
58
+ else if (versionType === "string") {
59
+ nullVersion = "";
60
+ }
61
+ const seen = checkpoint.versions_seen[INTERRUPT] ?? {};
62
+ const anyChannelUpdated = Object.entries(checkpoint.channel_versions).some(([chan, version]) => {
63
+ return version > (seen[chan] ?? nullVersion);
64
+ });
65
+ const anyTriggeredNodeInInterruptNodes = tasks.some((task) => interruptNodes === "*"
66
+ ? !task.config?.tags?.includes(TAG_HIDDEN)
67
+ : interruptNodes.includes(task.name));
68
+ return anyChannelUpdated && anyTriggeredNodeInInterruptNodes;
69
+ }
70
+ export function _localRead(checkpoint, channels, task, select, fresh = false) {
71
+ if (fresh) {
72
+ const newCheckpoint = createCheckpoint(checkpoint, channels, -1);
73
+ // create a new copy of channels
74
+ const newChannels = emptyChannels(channels, newCheckpoint);
75
+ // Note: _applyWrites contains side effects
76
+ _applyWrites(copyCheckpoint(newCheckpoint), newChannels, [task]);
77
+ return readChannels(newChannels, select);
78
+ }
79
+ else {
80
+ return readChannels(channels, select);
81
+ }
82
+ }
83
+ export function _localWrite(
84
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
+ commit, processes, channels,
86
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
+ writes) {
88
+ for (const [chan, value] of writes) {
89
+ if (chan === TASKS) {
90
+ if (!_isSend(value)) {
91
+ throw new InvalidUpdateError(`Invalid packet type, expected SendProtocol, got ${JSON.stringify(value)}`);
92
+ }
93
+ if (!(value.node in processes)) {
94
+ throw new InvalidUpdateError(`Invalid node name ${value.node} in packet`);
95
+ }
96
+ }
97
+ else if (!(chan in channels)) {
98
+ console.warn(`Skipping write for channel '${chan}' which has no readers`);
99
+ }
100
+ }
101
+ commit(writes);
102
+ }
103
+ export function _applyWrites(checkpoint, channels, tasks,
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ getNextVersion) {
106
+ // Update seen versions
107
+ for (const task of tasks) {
108
+ if (checkpoint.versions_seen[task.name] === undefined) {
109
+ checkpoint.versions_seen[task.name] = {};
110
+ }
111
+ for (const chan of task.triggers) {
112
+ if (chan in checkpoint.channel_versions) {
113
+ checkpoint.versions_seen[task.name][chan] =
114
+ checkpoint.channel_versions[chan];
115
+ }
116
+ }
117
+ }
118
+ // Find the highest version of all channels
119
+ let maxVersion;
120
+ if (Object.keys(checkpoint.channel_versions).length > 0) {
121
+ maxVersion = Math.max(...Object.values(checkpoint.channel_versions));
122
+ }
123
+ // Consume all channels that were read
124
+ const channelsToConsume = new Set(tasks
125
+ .flatMap((task) => task.triggers)
126
+ .filter((chan) => !RESERVED.includes(chan)));
127
+ for (const chan of channelsToConsume) {
128
+ if (channels[chan].consume()) {
129
+ if (getNextVersion !== undefined) {
130
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion, channels[chan]);
131
+ }
132
+ }
133
+ }
134
+ // Clear pending sends
135
+ if (checkpoint.pending_sends) {
136
+ checkpoint.pending_sends = [];
137
+ }
138
+ // Group writes by channel
139
+ const pendingWriteValuesByChannel = {};
140
+ for (const task of tasks) {
141
+ for (const [chan, val] of task.writes) {
142
+ if (chan === TASKS) {
143
+ checkpoint.pending_sends.push({
144
+ node: val.node,
145
+ args: val.args,
146
+ });
147
+ }
148
+ else {
149
+ if (chan in pendingWriteValuesByChannel) {
150
+ pendingWriteValuesByChannel[chan].push(val);
151
+ }
152
+ else {
153
+ pendingWriteValuesByChannel[chan] = [val];
154
+ }
155
+ }
156
+ }
157
+ }
158
+ // find the highest version of all channels
159
+ maxVersion = undefined;
160
+ if (Object.keys(checkpoint.channel_versions).length > 0) {
161
+ maxVersion = Math.max(...Object.values(checkpoint.channel_versions));
162
+ }
163
+ const updatedChannels = new Set();
164
+ // Apply writes to channels
165
+ for (const [chan, vals] of Object.entries(pendingWriteValuesByChannel)) {
166
+ if (chan in channels) {
167
+ let updated;
168
+ try {
169
+ updated = channels[chan].update(vals);
170
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
+ }
172
+ catch (e) {
173
+ if (e.name === InvalidUpdateError.unminifiable_name) {
174
+ throw new InvalidUpdateError(`Invalid update for channel ${chan} with values ${JSON.stringify(vals)}`);
175
+ }
176
+ else {
177
+ throw e;
178
+ }
179
+ }
180
+ if (updated && getNextVersion !== undefined) {
181
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion, channels[chan]);
182
+ }
183
+ updatedChannels.add(chan);
184
+ }
185
+ }
186
+ // Channels that weren't updated in this step are notified of a new step
187
+ for (const chan of Object.keys(channels)) {
188
+ if (!updatedChannels.has(chan)) {
189
+ const updated = channels[chan].update([]);
190
+ if (updated && getNextVersion !== undefined) {
191
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion, channels[chan]);
192
+ }
193
+ }
194
+ }
195
+ }
196
+ export function _prepareNextTasks(checkpoint, processes, channels, config, forExecution, extra) {
197
+ const parentNamespace = config.configurable?.checkpoint_ns ?? "";
198
+ const tasks = [];
199
+ const taskDescriptions = [];
200
+ const { step, isResuming = false, checkpointer, manager } = extra;
201
+ for (const packet of checkpoint.pending_sends) {
202
+ if (!_isSendInterface(packet)) {
203
+ console.warn(`Ignoring invalid packet ${JSON.stringify(packet)} in pending sends.`);
204
+ continue;
205
+ }
206
+ if (!(packet.node in processes)) {
207
+ console.warn(`Ignoring unknown node name ${packet.node} in pending sends.`);
208
+ continue;
209
+ }
210
+ const triggers = [TASKS];
211
+ const metadata = _getIdMetadata({
212
+ langgraph_step: step,
213
+ langgraph_node: packet.node,
214
+ langgraph_triggers: triggers,
215
+ langgraph_task_idx: forExecution ? tasks.length : taskDescriptions.length,
216
+ });
217
+ const checkpointNamespace = parentNamespace === ""
218
+ ? packet.node
219
+ : `${parentNamespace}${CHECKPOINT_NAMESPACE_SEPARATOR}${packet.node}`;
220
+ const taskId = uuid5(JSON.stringify([checkpointNamespace, metadata]), checkpoint.id);
221
+ if (forExecution) {
222
+ const proc = processes[packet.node];
223
+ const node = proc.getNode();
224
+ if (node !== undefined) {
225
+ const writes = [];
226
+ tasks.push({
227
+ name: packet.node,
228
+ input: packet.args,
229
+ proc: node,
230
+ writes,
231
+ triggers,
232
+ config: patchConfig(mergeConfigs(config, processes[packet.node].config, {
233
+ metadata,
234
+ }), {
235
+ runName: packet.node,
236
+ callbacks: manager?.getChild(`graph:step:${step}`),
237
+ configurable: {
238
+ [CONFIG_KEY_SEND]: _localWrite.bind(undefined, (items) => writes.push(...items), processes, channels),
239
+ [CONFIG_KEY_READ]: _localRead.bind(undefined, checkpoint, channels, {
240
+ name: packet.node,
241
+ writes: writes,
242
+ triggers,
243
+ }),
244
+ },
245
+ }),
246
+ id: taskId,
247
+ });
248
+ }
249
+ }
250
+ else {
251
+ taskDescriptions.push({ id: taskId, name: packet.node });
252
+ }
253
+ }
254
+ // Check if any processes should be run in next step
255
+ // If so, prepare the values to be passed to them
256
+ const nullVersion = getNullChannelVersion(checkpoint.channel_versions);
257
+ if (nullVersion === undefined) {
258
+ return forExecution ? tasks : taskDescriptions;
259
+ }
260
+ for (const [name, proc] of Object.entries(processes)) {
261
+ const seen = checkpoint.versions_seen[name] ?? {};
262
+ const triggers = proc.triggers
263
+ .filter((chan) => {
264
+ const result = readChannel(channels, chan, false, true);
265
+ const isEmptyChannelError =
266
+ // eslint-disable-next-line no-instanceof/no-instanceof
267
+ result instanceof Error &&
268
+ result.name === EmptyChannelError.unminifiable_name;
269
+ return (!isEmptyChannelError &&
270
+ (checkpoint.channel_versions[chan] ?? nullVersion) >
271
+ (seen[chan] ?? nullVersion));
272
+ })
273
+ .sort();
274
+ // If any of the channels read by this process were updated
275
+ if (triggers.length > 0) {
276
+ const val = _procInput(proc, channels, forExecution);
277
+ if (val === undefined) {
278
+ continue;
279
+ }
280
+ const metadata = _getIdMetadata({
281
+ langgraph_step: step,
282
+ langgraph_node: name,
283
+ langgraph_triggers: triggers,
284
+ langgraph_task_idx: forExecution
285
+ ? tasks.length
286
+ : taskDescriptions.length,
287
+ });
288
+ const checkpointNamespace = parentNamespace === ""
289
+ ? name
290
+ : `${parentNamespace}${CHECKPOINT_NAMESPACE_SEPARATOR}${name}`;
291
+ const taskId = uuid5(JSON.stringify([checkpointNamespace, metadata]), checkpoint.id);
292
+ if (forExecution) {
293
+ const node = proc.getNode();
294
+ if (node !== undefined) {
295
+ const writes = [];
296
+ tasks.push({
297
+ name,
298
+ input: val,
299
+ proc: node,
300
+ writes,
301
+ triggers,
302
+ config: patchConfig(mergeConfigs(config, proc.config, { metadata }), {
303
+ runName: name,
304
+ callbacks: manager?.getChild(`graph:step:${step}`),
305
+ configurable: {
306
+ [CONFIG_KEY_SEND]: _localWrite.bind(undefined, (items) => writes.push(...items), processes, channels),
307
+ [CONFIG_KEY_READ]: _localRead.bind(undefined, checkpoint, channels, {
308
+ name,
309
+ writes: writes,
310
+ triggers,
311
+ }),
312
+ [CONFIG_KEY_CHECKPOINTER]: checkpointer,
313
+ [CONFIG_KEY_RESUMING]: isResuming,
314
+ checkpoint_id: checkpoint.id,
315
+ checkpoint_ns: checkpointNamespace,
316
+ },
317
+ }),
318
+ id: taskId,
319
+ });
320
+ }
321
+ }
322
+ else {
323
+ taskDescriptions.push({ id: taskId, name });
324
+ }
325
+ }
326
+ }
327
+ return forExecution ? tasks : taskDescriptions;
328
+ }
329
+ function _procInput(proc, channels, forExecution) {
330
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
331
+ let val;
332
+ // If all trigger channels subscribed by this process are not empty
333
+ // then invoke the process with the values of all non-empty channels
334
+ if (Array.isArray(proc.channels)) {
335
+ let successfulRead = false;
336
+ for (const chan of proc.channels) {
337
+ try {
338
+ val = readChannel(channels, chan, false);
339
+ successfulRead = true;
340
+ break;
341
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
342
+ }
343
+ catch (e) {
344
+ if (e.name === EmptyChannelError.unminifiable_name) {
345
+ continue;
346
+ }
347
+ else {
348
+ throw e;
349
+ }
350
+ }
351
+ }
352
+ if (!successfulRead) {
353
+ return;
354
+ }
355
+ }
356
+ else if (typeof proc.channels === "object") {
357
+ val = {};
358
+ try {
359
+ for (const [k, chan] of Object.entries(proc.channels)) {
360
+ val[k] = readChannel(channels, chan, !proc.triggers.includes(chan));
361
+ }
362
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
363
+ }
364
+ catch (e) {
365
+ if (e.name === EmptyChannelError.unminifiable_name) {
366
+ return;
367
+ }
368
+ else {
369
+ throw e;
370
+ }
371
+ }
372
+ }
373
+ else {
374
+ throw new Error(`Invalid channels type, expected list or dict, got ${proc.channels}`);
375
+ }
376
+ // If the process has a mapper, apply it to the value
377
+ if (forExecution && proc.mapper !== undefined) {
378
+ val = proc.mapper(val);
379
+ }
380
+ return val;
381
+ }
@@ -1,26 +1,35 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.printCheckpoint = exports.printStepStart = void 0;
3
+ exports.printStepWrites = exports.printStepTasks = exports.printStepCheckpoint = exports.tasksWithWrites = exports.mapDebugCheckpoint = exports.mapDebugTaskResults = exports.mapDebugTasks = exports.printCheckpoint = void 0;
4
+ const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
5
+ const constants_js_1 = require("../constants.cjs");
4
6
  const errors_js_1 = require("../errors.cjs");
7
+ const io_js_1 = require("./io.cjs");
8
+ const utils_js_1 = require("./utils.cjs");
5
9
  const COLORS_MAP = {
6
10
  blue: {
7
11
  start: "\x1b[34m",
8
12
  end: "\x1b[0m",
9
13
  },
14
+ green: {
15
+ start: "\x1b[32m",
16
+ end: "\x1b[0m",
17
+ },
18
+ yellow: {
19
+ start: "\x1b[33;1m",
20
+ end: "\x1b[0m",
21
+ },
10
22
  };
11
23
  /**
12
24
  * Wrap some text in a color for printing to the console.
13
25
  */
14
26
  const wrap = (color, text) => `${color.start}${text}${color.end}`;
15
- function printStepStart(step, nextTasks) {
16
- const nTasks = nextTasks.length;
17
- console.log(`${wrap(COLORS_MAP.blue, "[langgraph/step]")}`, `Starting step ${step} with ${nTasks} task${nTasks === 1 ? "" : "s"}. Next tasks:\n`, `\n${nextTasks
18
- .map((task) => `${String(task.name)}(${JSON.stringify(task.input, null, 2)})`)
19
- .join("\n")}`);
20
- }
21
- exports.printStepStart = printStepStart;
22
27
  function printCheckpoint(step, channels) {
23
- console.log(`${wrap(COLORS_MAP.blue, "[langgraph/checkpoint]")}`, `Finishing step ${step}. Channel values:\n`, `\n${JSON.stringify(Object.fromEntries(_readChannels(channels)), null, 2)}`);
28
+ console.log([
29
+ `${wrap(COLORS_MAP.blue, "[langgraph/checkpoint]")}`,
30
+ `Finishing step ${step}. Channel values:\n`,
31
+ `\n${JSON.stringify(Object.fromEntries(_readChannels(channels)), null, 2)}`,
32
+ ].join(""));
24
33
  }
25
34
  exports.printCheckpoint = printCheckpoint;
26
35
  function* _readChannels(channels
@@ -42,3 +51,140 @@ function* _readChannels(channels
42
51
  }
43
52
  }
44
53
  }
54
+ function* mapDebugTasks(step, tasks) {
55
+ const ts = new Date().toISOString();
56
+ for (const { name, input, config, triggers } of tasks) {
57
+ if (config?.tags?.includes(constants_js_1.TAG_HIDDEN))
58
+ continue;
59
+ const metadata = { ...config?.metadata };
60
+ const idMetadata = (0, utils_js_1._getIdMetadata)({
61
+ langgraph_step: metadata.langgraph_step,
62
+ langgraph_node: metadata.langgraph_node,
63
+ langgraph_triggers: metadata.langgraph_triggers,
64
+ langgraph_task_idx: metadata.langgraph_task_idx,
65
+ });
66
+ yield {
67
+ type: "task",
68
+ timestamp: ts,
69
+ step,
70
+ payload: {
71
+ id: (0, langgraph_checkpoint_1.uuid5)(JSON.stringify([name, step, idMetadata]), constants_js_1.TASK_NAMESPACE),
72
+ name,
73
+ input,
74
+ triggers,
75
+ },
76
+ };
77
+ }
78
+ }
79
+ exports.mapDebugTasks = mapDebugTasks;
80
+ function* mapDebugTaskResults(step, tasks, streamChannelsList) {
81
+ const ts = new Date().toISOString();
82
+ for (const { name, writes, config } of tasks) {
83
+ if (config?.tags?.includes(constants_js_1.TAG_HIDDEN))
84
+ continue;
85
+ const metadata = { ...config?.metadata };
86
+ const idMetadata = (0, utils_js_1._getIdMetadata)(metadata);
87
+ yield {
88
+ type: "task_result",
89
+ timestamp: ts,
90
+ step,
91
+ payload: {
92
+ id: (0, langgraph_checkpoint_1.uuid5)(JSON.stringify([name, step, idMetadata]), constants_js_1.TASK_NAMESPACE),
93
+ name,
94
+ result: writes.filter(([channel]) => streamChannelsList.includes(channel)),
95
+ },
96
+ };
97
+ }
98
+ }
99
+ exports.mapDebugTaskResults = mapDebugTaskResults;
100
+ function* mapDebugCheckpoint(step, config, channels, streamChannels, metadata, tasks, pendingWrites) {
101
+ function formatConfig(config) {
102
+ // make sure the config is consistent with Python
103
+ const pyConfig = {};
104
+ if (config.callbacks != null)
105
+ pyConfig.callbacks = config.callbacks;
106
+ if (config.configurable != null)
107
+ pyConfig.configurable = config.configurable;
108
+ if (config.maxConcurrency != null)
109
+ pyConfig.max_concurrency = config.maxConcurrency;
110
+ if (config.metadata != null)
111
+ pyConfig.metadata = config.metadata;
112
+ if (config.recursionLimit != null)
113
+ pyConfig.recursion_limit = config.recursionLimit;
114
+ if (config.runId != null)
115
+ pyConfig.run_id = config.runId;
116
+ if (config.runName != null)
117
+ pyConfig.run_name = config.runName;
118
+ if (config.tags != null)
119
+ pyConfig.tags = config.tags;
120
+ return pyConfig;
121
+ }
122
+ function getCurrentUTC() {
123
+ const now = new Date();
124
+ return new Date(now.getTime() - now.getTimezoneOffset() * 60 * 1000);
125
+ }
126
+ const ts = getCurrentUTC().toISOString();
127
+ yield {
128
+ type: "checkpoint",
129
+ timestamp: ts,
130
+ step,
131
+ payload: {
132
+ config: formatConfig(config),
133
+ values: (0, io_js_1.readChannels)(channels, streamChannels),
134
+ metadata,
135
+ next: tasks.map((task) => task.name),
136
+ tasks: tasksWithWrites(tasks, pendingWrites),
137
+ },
138
+ };
139
+ }
140
+ exports.mapDebugCheckpoint = mapDebugCheckpoint;
141
+ function tasksWithWrites(tasks, pendingWrites) {
142
+ return tasks.map((task) => {
143
+ const error = pendingWrites.find(([id, n]) => id === task.id && n === constants_js_1.ERROR)?.[2];
144
+ if (error)
145
+ return { id: task.id, name: task.name, error };
146
+ return { id: task.id, name: task.name };
147
+ });
148
+ }
149
+ exports.tasksWithWrites = tasksWithWrites;
150
+ function printStepCheckpoint(step, channels, whitelist) {
151
+ console.log([
152
+ `${wrap(COLORS_MAP.blue, `[${step}:checkpoint]`)}`,
153
+ `\x1b[1m State at the end of step ${step}:\x1b[0m\n`,
154
+ JSON.stringify((0, io_js_1.readChannels)(channels, whitelist), null, 2),
155
+ ].join(""));
156
+ }
157
+ exports.printStepCheckpoint = printStepCheckpoint;
158
+ function printStepTasks(step, nextTasks) {
159
+ const nTasks = nextTasks.length;
160
+ console.log([
161
+ `${wrap(COLORS_MAP.blue, `[${step}:tasks]`)}`,
162
+ `\x1b[1m Starting step ${step} with ${nTasks} task${nTasks === 1 ? "" : "s"}:\x1b[0m\n`,
163
+ nextTasks
164
+ .map((task) => `- ${wrap(COLORS_MAP.green, String(task.name))} -> ${JSON.stringify(task.input, null, 2)}`)
165
+ .join("\n"),
166
+ ].join(""));
167
+ }
168
+ exports.printStepTasks = printStepTasks;
169
+ function printStepWrites(step, writes, whitelist) {
170
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
+ const byChannel = {};
172
+ for (const [channel, value] of writes) {
173
+ if (whitelist.includes(channel)) {
174
+ if (!byChannel[channel]) {
175
+ byChannel[channel] = [];
176
+ }
177
+ byChannel[channel].push(value);
178
+ }
179
+ }
180
+ console.log([
181
+ `${wrap(COLORS_MAP.blue, `[${step}:writes]`)}`,
182
+ `\x1b[1m Finished step ${step} with writes to ${Object.keys(byChannel).length} channel${Object.keys(byChannel).length !== 1 ? "s" : ""}:\x1b[0m\n`,
183
+ Object.entries(byChannel)
184
+ .map(([name, vals]) => `- ${wrap(COLORS_MAP.yellow, name)} -> ${vals
185
+ .map((v) => JSON.stringify(v))
186
+ .join(", ")}`)
187
+ .join("\n"),
188
+ ].join(""));
189
+ }
190
+ exports.printStepWrites = printStepWrites;
@@ -1,4 +1,42 @@
1
+ import { RunnableConfig } from "@langchain/core/runnables";
2
+ import { CheckpointMetadata, CheckpointPendingWrite, PendingWrite } from "@langchain/langgraph-checkpoint";
1
3
  import { BaseChannel } from "../channels/base.js";
2
- import { PregelExecutableTask } from "./types.js";
3
- export declare function printStepStart<N extends PropertyKey, C extends PropertyKey>(step: number, nextTasks: readonly PregelExecutableTask<N, C>[]): void;
4
+ import { PregelExecutableTask, PregelTaskDescription } from "./types.js";
4
5
  export declare function printCheckpoint<Value>(step: number, channels: Record<string, BaseChannel<Value>>): void;
6
+ export declare function mapDebugTasks<N extends PropertyKey, C extends PropertyKey>(step: number, tasks: readonly PregelExecutableTask<N, C>[]): Generator<{
7
+ type: string;
8
+ timestamp: string;
9
+ step: number;
10
+ payload: {
11
+ id: string;
12
+ name: N;
13
+ input: unknown;
14
+ triggers: string[];
15
+ };
16
+ }, void, unknown>;
17
+ export declare function mapDebugTaskResults<N extends PropertyKey, C extends PropertyKey>(step: number, tasks: readonly PregelExecutableTask<N, C>[], streamChannelsList: Array<PropertyKey>): Generator<{
18
+ type: string;
19
+ timestamp: string;
20
+ step: number;
21
+ payload: {
22
+ id: string;
23
+ name: N;
24
+ result: PendingWrite<C>[];
25
+ };
26
+ }, void, unknown>;
27
+ export declare function mapDebugCheckpoint<N extends PropertyKey, C extends PropertyKey>(step: number, config: RunnableConfig, channels: Record<string, BaseChannel>, streamChannels: string | string[], metadata: CheckpointMetadata, tasks: readonly PregelExecutableTask<N, C>[], pendingWrites: CheckpointPendingWrite[]): Generator<{
28
+ type: string;
29
+ timestamp: string;
30
+ step: number;
31
+ payload: {
32
+ config: Partial<Record<"tags" | "configurable" | "timeout" | "signal" | "metadata" | "callbacks" | "recursion_limit" | "max_concurrency" | "run_name" | "run_id", unknown>>;
33
+ values: any;
34
+ metadata: CheckpointMetadata;
35
+ next: N[];
36
+ tasks: PregelTaskDescription[];
37
+ };
38
+ }, void, unknown>;
39
+ export declare function tasksWithWrites<N extends PropertyKey, C extends PropertyKey>(tasks: PregelTaskDescription[] | readonly PregelExecutableTask<N, C>[], pendingWrites: CheckpointPendingWrite[]): PregelTaskDescription[];
40
+ export declare function printStepCheckpoint(step: number, channels: Record<string, BaseChannel<unknown>>, whitelist: string[]): void;
41
+ export declare function printStepTasks<N extends PropertyKey, C extends PropertyKey>(step: number, nextTasks: readonly PregelExecutableTask<N, C>[]): void;
42
+ export declare function printStepWrites(step: number, writes: PendingWrite[], whitelist: string[]): void;