@langchain/langgraph-checkpoint 0.0.0 → 0.0.2

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 CHANGED
@@ -81,7 +81,6 @@ const checkpoint = {
81
81
  }
82
82
  },
83
83
  pending_sends: [],
84
- current_tasks: {}
85
84
  }
86
85
 
87
86
  // store checkpoint
package/dist/base.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseCheckpointSaver = exports.copyCheckpoint = exports.emptyCheckpoint = exports.deepCopy = void 0;
4
- const base_js_1 = require("./serde/base.cjs");
5
4
  const id_js_1 = require("./id.cjs");
5
+ const jsonplus_js_1 = require("./serde/jsonplus.cjs");
6
6
  function deepCopy(obj) {
7
7
  if (typeof obj !== "object" || obj === null) {
8
8
  return obj;
@@ -16,6 +16,7 @@ function deepCopy(obj) {
16
16
  return newObj;
17
17
  }
18
18
  exports.deepCopy = deepCopy;
19
+ /** @hidden */
19
20
  function emptyCheckpoint() {
20
21
  return {
21
22
  v: 1,
@@ -28,6 +29,7 @@ function emptyCheckpoint() {
28
29
  };
29
30
  }
30
31
  exports.emptyCheckpoint = emptyCheckpoint;
32
+ /** @hidden */
31
33
  function copyCheckpoint(checkpoint) {
32
34
  return {
33
35
  v: checkpoint.v,
@@ -46,7 +48,7 @@ class BaseCheckpointSaver {
46
48
  enumerable: true,
47
49
  configurable: true,
48
50
  writable: true,
49
- value: base_js_1.DefaultSerializer
51
+ value: new jsonplus_js_1.JsonPlusSerializer()
50
52
  });
51
53
  this.serde = serde || this.serde;
52
54
  }
package/dist/base.d.ts CHANGED
@@ -40,7 +40,9 @@ export interface ReadonlyCheckpoint extends Readonly<Checkpoint> {
40
40
  readonly versions_seen: Readonly<Record<string, Readonly<Record<string, number>>>>;
41
41
  }
42
42
  export declare function deepCopy<T>(obj: T): T;
43
+ /** @hidden */
43
44
  export declare function emptyCheckpoint(): Checkpoint;
45
+ /** @hidden */
44
46
  export declare function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint;
45
47
  export interface CheckpointTuple {
46
48
  config: RunnableConfig;
@@ -55,8 +57,8 @@ export type CheckpointListOptions = {
55
57
  filter?: Record<string, any>;
56
58
  };
57
59
  export declare abstract class BaseCheckpointSaver<V = number> {
58
- serde: SerializerProtocol<unknown>;
59
- constructor(serde?: SerializerProtocol<unknown>);
60
+ serde: SerializerProtocol;
61
+ constructor(serde?: SerializerProtocol);
60
62
  get(config: RunnableConfig): Promise<Checkpoint | undefined>;
61
63
  abstract getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined>;
62
64
  abstract list(config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple>;
package/dist/base.js CHANGED
@@ -1,5 +1,5 @@
1
- import { DefaultSerializer } from "./serde/base.js";
2
1
  import { uuid6 } from "./id.js";
2
+ import { JsonPlusSerializer } from "./serde/jsonplus.js";
3
3
  export function deepCopy(obj) {
4
4
  if (typeof obj !== "object" || obj === null) {
5
5
  return obj;
@@ -12,6 +12,7 @@ export function deepCopy(obj) {
12
12
  }
13
13
  return newObj;
14
14
  }
15
+ /** @hidden */
15
16
  export function emptyCheckpoint() {
16
17
  return {
17
18
  v: 1,
@@ -23,6 +24,7 @@ export function emptyCheckpoint() {
23
24
  pending_sends: [],
24
25
  };
25
26
  }
27
+ /** @hidden */
26
28
  export function copyCheckpoint(checkpoint) {
27
29
  return {
28
30
  v: checkpoint.v,
@@ -40,7 +42,7 @@ export class BaseCheckpointSaver {
40
42
  enumerable: true,
41
43
  configurable: true,
42
44
  writable: true,
43
- value: DefaultSerializer
45
+ value: new JsonPlusSerializer()
44
46
  });
45
47
  this.serde = serde || this.serde;
46
48
  }
package/dist/memory.cjs CHANGED
@@ -33,24 +33,28 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
33
33
  const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
34
34
  [];
35
35
  const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
36
- return [taskId, channel, await this.serde.parse(value)];
36
+ return [
37
+ taskId,
38
+ channel,
39
+ await this.serde.loadsTyped("json", value),
40
+ ];
37
41
  }));
38
- const parentConfig = parentCheckpointId !== undefined
39
- ? {
42
+ const checkpointTuple = {
43
+ config,
44
+ checkpoint: (await this.serde.loadsTyped("json", checkpoint)),
45
+ metadata: (await this.serde.loadsTyped("json", metadata)),
46
+ pendingWrites,
47
+ };
48
+ if (parentCheckpointId !== undefined) {
49
+ checkpointTuple.parentConfig = {
40
50
  configurable: {
41
51
  thread_id,
42
52
  checkpoint_ns,
43
53
  checkpoint_id,
44
54
  },
45
- }
46
- : undefined;
47
- return {
48
- config,
49
- checkpoint: (await this.serde.parse(checkpoint)),
50
- metadata: (await this.serde.parse(metadata)),
51
- pendingWrites,
52
- parentConfig,
53
- };
55
+ };
56
+ }
57
+ return checkpointTuple;
54
58
  }
55
59
  }
56
60
  else {
@@ -63,18 +67,13 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
63
67
  const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
64
68
  [];
65
69
  const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
66
- return [taskId, channel, await this.serde.parse(value)];
70
+ return [
71
+ taskId,
72
+ channel,
73
+ await this.serde.loadsTyped("json", value),
74
+ ];
67
75
  }));
68
- const parentConfig = parentCheckpointId !== undefined
69
- ? {
70
- configurable: {
71
- thread_id,
72
- checkpoint_ns,
73
- checkpoint_id: parentCheckpointId,
74
- },
75
- }
76
- : undefined;
77
- return {
76
+ const checkpointTuple = {
78
77
  config: {
79
78
  configurable: {
80
79
  thread_id,
@@ -82,11 +81,20 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
82
81
  checkpoint_ns,
83
82
  },
84
83
  },
85
- checkpoint: (await this.serde.parse(checkpoint)),
86
- metadata: (await this.serde.parse(metadata)),
84
+ checkpoint: (await this.serde.loadsTyped("json", checkpoint)),
85
+ metadata: (await this.serde.loadsTyped("json", metadata)),
87
86
  pendingWrites,
88
- parentConfig,
89
87
  };
88
+ if (parentCheckpointId !== undefined) {
89
+ checkpointTuple.parentConfig = {
90
+ configurable: {
91
+ thread_id,
92
+ checkpoint_ns,
93
+ checkpoint_id: parentCheckpointId,
94
+ },
95
+ };
96
+ }
97
+ return checkpointTuple;
90
98
  }
91
99
  }
92
100
  return undefined;
@@ -109,7 +117,7 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
109
117
  continue;
110
118
  }
111
119
  // Parse metadata
112
- const metadata = (await this.serde.parse(metadataStr));
120
+ const metadata = (await this.serde.loadsTyped("json", metadataStr));
113
121
  // Limit search results
114
122
  if (limit !== undefined) {
115
123
  if (limit <= 0)
@@ -119,9 +127,13 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
119
127
  }
120
128
  const writes = this.writes[_generateKey(threadId, checkpointNamespace, checkpointId)] ?? [];
121
129
  const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
122
- return [taskId, channel, await this.serde.parse(value)];
130
+ return [
131
+ taskId,
132
+ channel,
133
+ await this.serde.loadsTyped("json", value),
134
+ ];
123
135
  }));
124
- yield {
136
+ const checkpointTuple = {
125
137
  config: {
126
138
  configurable: {
127
139
  thread_id: threadId,
@@ -129,19 +141,20 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
129
141
  checkpoint_id: checkpointId,
130
142
  },
131
143
  },
132
- checkpoint: (await this.serde.parse(checkpoint)),
144
+ checkpoint: (await this.serde.loadsTyped("json", checkpoint)),
133
145
  metadata,
134
146
  pendingWrites,
135
- parentConfig: parentCheckpointId
136
- ? {
137
- configurable: {
138
- thread_id: threadId,
139
- checkpoint_ns: checkpointNamespace,
140
- checkpoint_id: parentCheckpointId,
141
- },
142
- }
143
- : undefined,
144
147
  };
148
+ if (parentCheckpointId !== undefined) {
149
+ checkpointTuple.parentConfig = {
150
+ configurable: {
151
+ thread_id: threadId,
152
+ checkpoint_ns: checkpointNamespace,
153
+ checkpoint_id: parentCheckpointId,
154
+ },
155
+ };
156
+ }
157
+ yield checkpointTuple;
145
158
  }
146
159
  }
147
160
  }
@@ -160,9 +173,11 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
160
173
  if (!this.storage[threadId][checkpointNamespace]) {
161
174
  this.storage[threadId][checkpointNamespace] = {};
162
175
  }
176
+ const [, serializedCheckpoint] = this.serde.dumpsTyped(checkpoint);
177
+ const [, serializedMetadata] = this.serde.dumpsTyped(metadata);
163
178
  this.storage[threadId][checkpointNamespace][checkpoint.id] = [
164
- this.serde.stringify(checkpoint),
165
- this.serde.stringify(metadata),
179
+ serializedCheckpoint,
180
+ serializedMetadata,
166
181
  config.configurable?.checkpoint_id, // parent
167
182
  ];
168
183
  return {
@@ -188,7 +203,8 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
188
203
  this.writes[key] = [];
189
204
  }
190
205
  const pendingWrites = writes.map(([channel, value]) => {
191
- return [taskId, channel, this.serde.stringify(value)];
206
+ const [, serializedValue] = this.serde.dumpsTyped(value);
207
+ return [taskId, channel, serializedValue];
192
208
  });
193
209
  this.writes[key].push(...pendingWrites);
194
210
  }
package/dist/memory.d.ts CHANGED
@@ -3,9 +3,9 @@ import { BaseCheckpointSaver, Checkpoint, CheckpointListOptions, CheckpointTuple
3
3
  import { SerializerProtocol } from "./serde/base.js";
4
4
  import { CheckpointMetadata, CheckpointPendingWrite, PendingWrite } from "./types.js";
5
5
  export declare class MemorySaver extends BaseCheckpointSaver {
6
- storage: Record<string, Record<string, Record<string, [string, string, string | undefined]>>>;
6
+ storage: Record<string, Record<string, Record<string, [Uint8Array, Uint8Array, string | undefined]>>>;
7
7
  writes: Record<string, CheckpointPendingWrite[]>;
8
- constructor(serde?: SerializerProtocol<unknown>);
8
+ constructor(serde?: SerializerProtocol);
9
9
  getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined>;
10
10
  list(config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple>;
11
11
  put(config: RunnableConfig, checkpoint: Checkpoint, metadata: CheckpointMetadata): Promise<RunnableConfig>;
package/dist/memory.js CHANGED
@@ -30,24 +30,28 @@ export class MemorySaver extends BaseCheckpointSaver {
30
30
  const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
31
31
  [];
32
32
  const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
33
- return [taskId, channel, await this.serde.parse(value)];
33
+ return [
34
+ taskId,
35
+ channel,
36
+ await this.serde.loadsTyped("json", value),
37
+ ];
34
38
  }));
35
- const parentConfig = parentCheckpointId !== undefined
36
- ? {
39
+ const checkpointTuple = {
40
+ config,
41
+ checkpoint: (await this.serde.loadsTyped("json", checkpoint)),
42
+ metadata: (await this.serde.loadsTyped("json", metadata)),
43
+ pendingWrites,
44
+ };
45
+ if (parentCheckpointId !== undefined) {
46
+ checkpointTuple.parentConfig = {
37
47
  configurable: {
38
48
  thread_id,
39
49
  checkpoint_ns,
40
50
  checkpoint_id,
41
51
  },
42
- }
43
- : undefined;
44
- return {
45
- config,
46
- checkpoint: (await this.serde.parse(checkpoint)),
47
- metadata: (await this.serde.parse(metadata)),
48
- pendingWrites,
49
- parentConfig,
50
- };
52
+ };
53
+ }
54
+ return checkpointTuple;
51
55
  }
52
56
  }
53
57
  else {
@@ -60,18 +64,13 @@ export class MemorySaver extends BaseCheckpointSaver {
60
64
  const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
61
65
  [];
62
66
  const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
63
- return [taskId, channel, await this.serde.parse(value)];
67
+ return [
68
+ taskId,
69
+ channel,
70
+ await this.serde.loadsTyped("json", value),
71
+ ];
64
72
  }));
65
- const parentConfig = parentCheckpointId !== undefined
66
- ? {
67
- configurable: {
68
- thread_id,
69
- checkpoint_ns,
70
- checkpoint_id: parentCheckpointId,
71
- },
72
- }
73
- : undefined;
74
- return {
73
+ const checkpointTuple = {
75
74
  config: {
76
75
  configurable: {
77
76
  thread_id,
@@ -79,11 +78,20 @@ export class MemorySaver extends BaseCheckpointSaver {
79
78
  checkpoint_ns,
80
79
  },
81
80
  },
82
- checkpoint: (await this.serde.parse(checkpoint)),
83
- metadata: (await this.serde.parse(metadata)),
81
+ checkpoint: (await this.serde.loadsTyped("json", checkpoint)),
82
+ metadata: (await this.serde.loadsTyped("json", metadata)),
84
83
  pendingWrites,
85
- parentConfig,
86
84
  };
85
+ if (parentCheckpointId !== undefined) {
86
+ checkpointTuple.parentConfig = {
87
+ configurable: {
88
+ thread_id,
89
+ checkpoint_ns,
90
+ checkpoint_id: parentCheckpointId,
91
+ },
92
+ };
93
+ }
94
+ return checkpointTuple;
87
95
  }
88
96
  }
89
97
  return undefined;
@@ -106,7 +114,7 @@ export class MemorySaver extends BaseCheckpointSaver {
106
114
  continue;
107
115
  }
108
116
  // Parse metadata
109
- const metadata = (await this.serde.parse(metadataStr));
117
+ const metadata = (await this.serde.loadsTyped("json", metadataStr));
110
118
  // Limit search results
111
119
  if (limit !== undefined) {
112
120
  if (limit <= 0)
@@ -116,9 +124,13 @@ export class MemorySaver extends BaseCheckpointSaver {
116
124
  }
117
125
  const writes = this.writes[_generateKey(threadId, checkpointNamespace, checkpointId)] ?? [];
118
126
  const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
119
- return [taskId, channel, await this.serde.parse(value)];
127
+ return [
128
+ taskId,
129
+ channel,
130
+ await this.serde.loadsTyped("json", value),
131
+ ];
120
132
  }));
121
- yield {
133
+ const checkpointTuple = {
122
134
  config: {
123
135
  configurable: {
124
136
  thread_id: threadId,
@@ -126,19 +138,20 @@ export class MemorySaver extends BaseCheckpointSaver {
126
138
  checkpoint_id: checkpointId,
127
139
  },
128
140
  },
129
- checkpoint: (await this.serde.parse(checkpoint)),
141
+ checkpoint: (await this.serde.loadsTyped("json", checkpoint)),
130
142
  metadata,
131
143
  pendingWrites,
132
- parentConfig: parentCheckpointId
133
- ? {
134
- configurable: {
135
- thread_id: threadId,
136
- checkpoint_ns: checkpointNamespace,
137
- checkpoint_id: parentCheckpointId,
138
- },
139
- }
140
- : undefined,
141
144
  };
145
+ if (parentCheckpointId !== undefined) {
146
+ checkpointTuple.parentConfig = {
147
+ configurable: {
148
+ thread_id: threadId,
149
+ checkpoint_ns: checkpointNamespace,
150
+ checkpoint_id: parentCheckpointId,
151
+ },
152
+ };
153
+ }
154
+ yield checkpointTuple;
142
155
  }
143
156
  }
144
157
  }
@@ -157,9 +170,11 @@ export class MemorySaver extends BaseCheckpointSaver {
157
170
  if (!this.storage[threadId][checkpointNamespace]) {
158
171
  this.storage[threadId][checkpointNamespace] = {};
159
172
  }
173
+ const [, serializedCheckpoint] = this.serde.dumpsTyped(checkpoint);
174
+ const [, serializedMetadata] = this.serde.dumpsTyped(metadata);
160
175
  this.storage[threadId][checkpointNamespace][checkpoint.id] = [
161
- this.serde.stringify(checkpoint),
162
- this.serde.stringify(metadata),
176
+ serializedCheckpoint,
177
+ serializedMetadata,
163
178
  config.configurable?.checkpoint_id, // parent
164
179
  ];
165
180
  return {
@@ -185,7 +200,8 @@ export class MemorySaver extends BaseCheckpointSaver {
185
200
  this.writes[key] = [];
186
201
  }
187
202
  const pendingWrites = writes.map(([channel, value]) => {
188
- return [taskId, channel, this.serde.stringify(value)];
203
+ const [, serializedValue] = this.serde.dumpsTyped(value);
204
+ return [taskId, channel, serializedValue];
189
205
  });
190
206
  this.writes[key].push(...pendingWrites);
191
207
  }
@@ -1,8 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DefaultSerializer = void 0;
4
- const load_1 = require("@langchain/core/load");
5
- exports.DefaultSerializer = {
6
- stringify: JSON.stringify,
7
- parse: load_1.load,
8
- };
@@ -1,12 +1,4 @@
1
- import { load } from "@langchain/core/load";
2
- export interface SerializerProtocol<D> {
3
- stringify(obj: D): string;
4
- parse(data: string): Promise<D>;
1
+ export interface SerializerProtocol {
2
+ dumpsTyped(data: any): [string, Uint8Array];
3
+ loadsTyped(type: string, data: Uint8Array | string): any;
5
4
  }
6
- export declare const DefaultSerializer: {
7
- stringify: {
8
- (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
9
- (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
10
- };
11
- parse: typeof load;
12
- };
@@ -1,5 +1 @@
1
- import { load } from "@langchain/core/load";
2
- export const DefaultSerializer = {
3
- stringify: JSON.stringify,
4
- parse: load,
5
- };
1
+ export {};
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonPlusSerializer = void 0;
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ /* eslint-disable no-instanceof/no-instanceof */
6
+ const load_1 = require("@langchain/core/load");
7
+ async function _reviver(value) {
8
+ if (value && typeof value === "object") {
9
+ if (value.lc === 2 && value.type === "undefined") {
10
+ return undefined;
11
+ }
12
+ else if (value.lc === 2 &&
13
+ value.type === "constructor" &&
14
+ Array.isArray(value.id)) {
15
+ try {
16
+ const constructorName = value.id[value.id.length - 1];
17
+ let constructor;
18
+ switch (constructorName) {
19
+ case "Set":
20
+ constructor = Set;
21
+ break;
22
+ case "Map":
23
+ constructor = Map;
24
+ break;
25
+ case "RegExp":
26
+ constructor = RegExp;
27
+ break;
28
+ case "Error":
29
+ constructor = Error;
30
+ break;
31
+ default:
32
+ return value;
33
+ }
34
+ if (value.method) {
35
+ return constructor[value.method](...(value.args || []));
36
+ }
37
+ else {
38
+ return new constructor(...(value.args || []));
39
+ }
40
+ }
41
+ catch (error) {
42
+ return value;
43
+ }
44
+ }
45
+ else if (value.lc === 1) {
46
+ return (0, load_1.load)(JSON.stringify(value));
47
+ }
48
+ else if (Array.isArray(value)) {
49
+ return Promise.all(value.map((item) => _reviver(item)));
50
+ }
51
+ else {
52
+ const revivedObj = {};
53
+ for (const [k, v] of Object.entries(value)) {
54
+ revivedObj[k] = await _reviver(v);
55
+ }
56
+ return revivedObj;
57
+ }
58
+ }
59
+ return value;
60
+ }
61
+ function _encodeConstructorArgs(
62
+ // eslint-disable-next-line @typescript-eslint/ban-types
63
+ constructor, method, args, kwargs) {
64
+ return {
65
+ lc: 2,
66
+ type: "constructor",
67
+ id: [constructor.name],
68
+ method: method ?? null,
69
+ args: args ?? [],
70
+ kwargs: kwargs ?? {},
71
+ };
72
+ }
73
+ function _default(_key, obj) {
74
+ if (obj === undefined) {
75
+ return {
76
+ lc: 2,
77
+ type: "undefined",
78
+ };
79
+ }
80
+ else if (obj instanceof Set || obj instanceof Map) {
81
+ return _encodeConstructorArgs(obj.constructor, undefined, [
82
+ Array.from(obj),
83
+ ]);
84
+ }
85
+ else if (obj instanceof RegExp) {
86
+ return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);
87
+ }
88
+ else if (obj instanceof Error) {
89
+ return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]);
90
+ }
91
+ else {
92
+ return obj;
93
+ }
94
+ }
95
+ class JsonPlusSerializer {
96
+ _dumps(obj) {
97
+ const jsonString = JSON.stringify(obj, (key, value) => {
98
+ if (value && typeof value === "object") {
99
+ if (Array.isArray(value)) {
100
+ // Handle arrays
101
+ return value.map((item) => _default(key, item));
102
+ }
103
+ else {
104
+ // Handle objects
105
+ const serialized = {};
106
+ for (const [k, v] of Object.entries(value)) {
107
+ serialized[k] = _default(k, v);
108
+ }
109
+ return serialized;
110
+ }
111
+ }
112
+ return _default(key, value);
113
+ });
114
+ return new TextEncoder().encode(jsonString);
115
+ }
116
+ dumpsTyped(obj) {
117
+ if (obj instanceof Uint8Array) {
118
+ return ["bytes", obj];
119
+ }
120
+ else {
121
+ return ["json", this._dumps(obj)];
122
+ }
123
+ }
124
+ async _loads(data) {
125
+ const parsed = JSON.parse(data);
126
+ return _reviver(parsed);
127
+ }
128
+ async loadsTyped(type, data) {
129
+ if (type === "bytes") {
130
+ return typeof data === "string" ? new TextEncoder().encode(data) : data;
131
+ }
132
+ else if (type === "json") {
133
+ return this._loads(typeof data === "string" ? data : new TextDecoder().decode(data));
134
+ }
135
+ else {
136
+ throw new Error(`Unknown serialization type: ${type}`);
137
+ }
138
+ }
139
+ }
140
+ exports.JsonPlusSerializer = JsonPlusSerializer;
@@ -0,0 +1,7 @@
1
+ import { SerializerProtocol } from "./base.js";
2
+ export declare class JsonPlusSerializer implements SerializerProtocol {
3
+ protected _dumps(obj: any): Uint8Array;
4
+ dumpsTyped(obj: any): [string, Uint8Array];
5
+ protected _loads(data: string): Promise<any>;
6
+ loadsTyped(type: string, data: Uint8Array | string): Promise<any>;
7
+ }
@@ -0,0 +1,136 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable no-instanceof/no-instanceof */
3
+ import { load } from "@langchain/core/load";
4
+ async function _reviver(value) {
5
+ if (value && typeof value === "object") {
6
+ if (value.lc === 2 && value.type === "undefined") {
7
+ return undefined;
8
+ }
9
+ else if (value.lc === 2 &&
10
+ value.type === "constructor" &&
11
+ Array.isArray(value.id)) {
12
+ try {
13
+ const constructorName = value.id[value.id.length - 1];
14
+ let constructor;
15
+ switch (constructorName) {
16
+ case "Set":
17
+ constructor = Set;
18
+ break;
19
+ case "Map":
20
+ constructor = Map;
21
+ break;
22
+ case "RegExp":
23
+ constructor = RegExp;
24
+ break;
25
+ case "Error":
26
+ constructor = Error;
27
+ break;
28
+ default:
29
+ return value;
30
+ }
31
+ if (value.method) {
32
+ return constructor[value.method](...(value.args || []));
33
+ }
34
+ else {
35
+ return new constructor(...(value.args || []));
36
+ }
37
+ }
38
+ catch (error) {
39
+ return value;
40
+ }
41
+ }
42
+ else if (value.lc === 1) {
43
+ return load(JSON.stringify(value));
44
+ }
45
+ else if (Array.isArray(value)) {
46
+ return Promise.all(value.map((item) => _reviver(item)));
47
+ }
48
+ else {
49
+ const revivedObj = {};
50
+ for (const [k, v] of Object.entries(value)) {
51
+ revivedObj[k] = await _reviver(v);
52
+ }
53
+ return revivedObj;
54
+ }
55
+ }
56
+ return value;
57
+ }
58
+ function _encodeConstructorArgs(
59
+ // eslint-disable-next-line @typescript-eslint/ban-types
60
+ constructor, method, args, kwargs) {
61
+ return {
62
+ lc: 2,
63
+ type: "constructor",
64
+ id: [constructor.name],
65
+ method: method ?? null,
66
+ args: args ?? [],
67
+ kwargs: kwargs ?? {},
68
+ };
69
+ }
70
+ function _default(_key, obj) {
71
+ if (obj === undefined) {
72
+ return {
73
+ lc: 2,
74
+ type: "undefined",
75
+ };
76
+ }
77
+ else if (obj instanceof Set || obj instanceof Map) {
78
+ return _encodeConstructorArgs(obj.constructor, undefined, [
79
+ Array.from(obj),
80
+ ]);
81
+ }
82
+ else if (obj instanceof RegExp) {
83
+ return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);
84
+ }
85
+ else if (obj instanceof Error) {
86
+ return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]);
87
+ }
88
+ else {
89
+ return obj;
90
+ }
91
+ }
92
+ export class JsonPlusSerializer {
93
+ _dumps(obj) {
94
+ const jsonString = JSON.stringify(obj, (key, value) => {
95
+ if (value && typeof value === "object") {
96
+ if (Array.isArray(value)) {
97
+ // Handle arrays
98
+ return value.map((item) => _default(key, item));
99
+ }
100
+ else {
101
+ // Handle objects
102
+ const serialized = {};
103
+ for (const [k, v] of Object.entries(value)) {
104
+ serialized[k] = _default(k, v);
105
+ }
106
+ return serialized;
107
+ }
108
+ }
109
+ return _default(key, value);
110
+ });
111
+ return new TextEncoder().encode(jsonString);
112
+ }
113
+ dumpsTyped(obj) {
114
+ if (obj instanceof Uint8Array) {
115
+ return ["bytes", obj];
116
+ }
117
+ else {
118
+ return ["json", this._dumps(obj)];
119
+ }
120
+ }
121
+ async _loads(data) {
122
+ const parsed = JSON.parse(data);
123
+ return _reviver(parsed);
124
+ }
125
+ async loadsTyped(type, data) {
126
+ if (type === "bytes") {
127
+ return typeof data === "string" ? new TextEncoder().encode(data) : data;
128
+ }
129
+ else if (type === "json") {
130
+ return this._loads(typeof data === "string" ? data : new TextDecoder().decode(data));
131
+ }
132
+ else {
133
+ throw new Error(`Unknown serialization type: ${type}`);
134
+ }
135
+ }
136
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-checkpoint",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "description": "Library with base interfaces for LangGraph checkpoint savers.",
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-checkpoint",
17
- "build:internal": "yarn lc_build_v2 --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",
@@ -37,7 +38,7 @@
37
38
  },
38
39
  "devDependencies": {
39
40
  "@jest/globals": "^29.5.0",
40
- "@langchain/scripts": "^0.0.22",
41
+ "@langchain/scripts": ">=0.1.2 <0.2.0",
41
42
  "@swc/core": "^1.3.90",
42
43
  "@swc/jest": "^0.2.29",
43
44
  "@tsconfig/recommended": "^1.0.3",