@skein-js/server-kit 0.11.2 → 0.12.0
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 +31 -3
- package/dist/chunk-JUBBCC7R.js +56 -0
- package/dist/chunk-QOHYARHD.js +237 -0
- package/dist/dev-BfYYRfEB.d.ts +46 -0
- package/dist/dev.d.ts +4 -0
- package/dist/dev.js +303 -0
- package/dist/in-memory-runtime-32UYJRVJ.js +9 -0
- package/dist/index.d.ts +325 -45
- package/dist/index.js +323 -496
- package/package.json +10 -5
package/dist/dev.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hydrateCheckpointer,
|
|
3
|
+
snapshotCheckpointer
|
|
4
|
+
} from "./chunk-JUBBCC7R.js";
|
|
5
|
+
|
|
6
|
+
// src/langgraph-import.ts
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import {
|
|
10
|
+
MemorySaver
|
|
11
|
+
} from "@langchain/langgraph";
|
|
12
|
+
import {
|
|
13
|
+
isTerminalRunStatus
|
|
14
|
+
} from "@skein-js/core";
|
|
15
|
+
import { SuperJSON } from "superjson";
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
var OPS_FILE = ".langgraphjs_ops.json";
|
|
18
|
+
var STORE_FILE = ".langgraphjs_api.store.json";
|
|
19
|
+
var CHECKPOINTER_FILE = ".langgraphjs_api.checkpointer.json";
|
|
20
|
+
var langgraphSuperjson = new SuperJSON();
|
|
21
|
+
langgraphSuperjson.registerCustom(
|
|
22
|
+
{
|
|
23
|
+
isApplicable: (value) => value instanceof Uint8Array,
|
|
24
|
+
serialize: (value) => Buffer.from(value).toString("base64"),
|
|
25
|
+
deserialize: (value) => new Uint8Array(Buffer.from(value, "base64"))
|
|
26
|
+
},
|
|
27
|
+
"Uint8Array"
|
|
28
|
+
);
|
|
29
|
+
var timestamp = z.union([z.date(), z.string()]).optional();
|
|
30
|
+
var jsonObject = z.record(z.unknown());
|
|
31
|
+
var langgraphAssistantSchema = z.object({
|
|
32
|
+
assistant_id: z.string(),
|
|
33
|
+
graph_id: z.string(),
|
|
34
|
+
name: z.string().optional(),
|
|
35
|
+
description: z.string().nullish(),
|
|
36
|
+
config: jsonObject.optional(),
|
|
37
|
+
context: z.unknown().optional(),
|
|
38
|
+
metadata: jsonObject.optional(),
|
|
39
|
+
version: z.number().optional(),
|
|
40
|
+
created_at: timestamp,
|
|
41
|
+
updated_at: timestamp
|
|
42
|
+
}).passthrough();
|
|
43
|
+
var langgraphAssistantVersionSchema = z.object({
|
|
44
|
+
assistant_id: z.string(),
|
|
45
|
+
version: z.number(),
|
|
46
|
+
graph_id: z.string(),
|
|
47
|
+
name: z.string().optional(),
|
|
48
|
+
description: z.string().nullish(),
|
|
49
|
+
config: jsonObject.optional(),
|
|
50
|
+
context: z.unknown().optional(),
|
|
51
|
+
metadata: jsonObject.optional(),
|
|
52
|
+
created_at: timestamp
|
|
53
|
+
}).passthrough();
|
|
54
|
+
var langgraphThreadSchema = z.object({
|
|
55
|
+
thread_id: z.string(),
|
|
56
|
+
status: z.string().optional(),
|
|
57
|
+
metadata: jsonObject.optional(),
|
|
58
|
+
values: jsonObject.optional(),
|
|
59
|
+
interrupts: jsonObject.optional(),
|
|
60
|
+
created_at: timestamp,
|
|
61
|
+
updated_at: timestamp
|
|
62
|
+
}).passthrough();
|
|
63
|
+
var langgraphRunSchema = z.object({
|
|
64
|
+
run_id: z.string(),
|
|
65
|
+
thread_id: z.string(),
|
|
66
|
+
assistant_id: z.string(),
|
|
67
|
+
status: z.string().optional(),
|
|
68
|
+
metadata: jsonObject.optional(),
|
|
69
|
+
multitask_strategy: z.string().nullish(),
|
|
70
|
+
kwargs: jsonObject.optional(),
|
|
71
|
+
created_at: timestamp,
|
|
72
|
+
updated_at: timestamp
|
|
73
|
+
}).passthrough();
|
|
74
|
+
var langgraphOpsSchema = z.object({
|
|
75
|
+
assistants: z.record(langgraphAssistantSchema).optional(),
|
|
76
|
+
assistant_versions: z.array(langgraphAssistantVersionSchema).optional(),
|
|
77
|
+
threads: z.record(langgraphThreadSchema).optional(),
|
|
78
|
+
runs: z.record(langgraphRunSchema).optional()
|
|
79
|
+
}).passthrough();
|
|
80
|
+
var langgraphStoreItemSchema = z.object({
|
|
81
|
+
namespace: z.array(z.string()),
|
|
82
|
+
key: z.string(),
|
|
83
|
+
value: jsonObject,
|
|
84
|
+
createdAt: timestamp,
|
|
85
|
+
updatedAt: timestamp
|
|
86
|
+
}).passthrough();
|
|
87
|
+
var langgraphStoreFileSchema = z.object({ data: z.map(z.string(), z.map(z.string(), langgraphStoreItemSchema)).optional() }).passthrough();
|
|
88
|
+
var langgraphCheckpointerSchema = z.object({ storage: jsonObject, writes: jsonObject }).passthrough();
|
|
89
|
+
async function readSuperjsonFile(filepath) {
|
|
90
|
+
let text;
|
|
91
|
+
try {
|
|
92
|
+
text = await readFile(filepath, "utf8");
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
return langgraphSuperjson.parse(text) ?? null;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Could not parse LangGraph state file "${filepath}": ${error instanceof Error ? error.message : String(error)}`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function validateShape(schema, value, label) {
|
|
105
|
+
const result = schema.safeParse(value);
|
|
106
|
+
if (!result.success) {
|
|
107
|
+
const detail = result.error.issues.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; ");
|
|
108
|
+
throw new Error(`Invalid LangGraph ${label}: ${detail}`);
|
|
109
|
+
}
|
|
110
|
+
return result.data;
|
|
111
|
+
}
|
|
112
|
+
function toIso(value, fallback) {
|
|
113
|
+
if (value instanceof Date) return value.toISOString();
|
|
114
|
+
if (typeof value === "string") return value;
|
|
115
|
+
return fallback;
|
|
116
|
+
}
|
|
117
|
+
function toAssistant(row, now) {
|
|
118
|
+
return {
|
|
119
|
+
assistant_id: row.assistant_id,
|
|
120
|
+
graph_id: row.graph_id,
|
|
121
|
+
name: row.name ?? row.graph_id,
|
|
122
|
+
description: row.description ?? void 0,
|
|
123
|
+
config: row.config ?? {},
|
|
124
|
+
context: row.context ?? {},
|
|
125
|
+
metadata: row.metadata ?? {},
|
|
126
|
+
version: row.version ?? 1,
|
|
127
|
+
created_at: toIso(row.created_at, now),
|
|
128
|
+
updated_at: toIso(row.updated_at, now)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function toAssistantVersion(row, now) {
|
|
132
|
+
return {
|
|
133
|
+
assistant_id: row.assistant_id,
|
|
134
|
+
version: row.version,
|
|
135
|
+
graph_id: row.graph_id,
|
|
136
|
+
name: row.name ?? row.graph_id,
|
|
137
|
+
description: row.description ?? void 0,
|
|
138
|
+
config: row.config ?? {},
|
|
139
|
+
context: row.context ?? {},
|
|
140
|
+
metadata: row.metadata ?? {},
|
|
141
|
+
created_at: toIso(row.created_at, now)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function toThread(row, now) {
|
|
145
|
+
const createdAt = toIso(row.created_at, now);
|
|
146
|
+
const updatedAt = toIso(row.updated_at, createdAt);
|
|
147
|
+
return {
|
|
148
|
+
thread_id: row.thread_id,
|
|
149
|
+
status: row.status ?? "idle",
|
|
150
|
+
metadata: row.metadata ?? {},
|
|
151
|
+
values: row.values ?? {},
|
|
152
|
+
interrupts: row.interrupts ?? {},
|
|
153
|
+
created_at: createdAt,
|
|
154
|
+
updated_at: updatedAt,
|
|
155
|
+
state_updated_at: updatedAt
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function toRun(row, now) {
|
|
159
|
+
const createdAt = toIso(row.created_at, now);
|
|
160
|
+
const status = row.status ?? "success";
|
|
161
|
+
return {
|
|
162
|
+
run_id: row.run_id,
|
|
163
|
+
thread_id: row.thread_id,
|
|
164
|
+
assistant_id: row.assistant_id,
|
|
165
|
+
status: isTerminalRunStatus(status) ? status : "error",
|
|
166
|
+
metadata: row.metadata ?? {},
|
|
167
|
+
multitask_strategy: row.multitask_strategy ?? null,
|
|
168
|
+
created_at: createdAt,
|
|
169
|
+
updated_at: toIso(row.updated_at, createdAt)
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function toRunKwargs(kwargs) {
|
|
173
|
+
if (!kwargs) return {};
|
|
174
|
+
const {
|
|
175
|
+
input,
|
|
176
|
+
command,
|
|
177
|
+
config,
|
|
178
|
+
context,
|
|
179
|
+
stream_mode,
|
|
180
|
+
interrupt_before,
|
|
181
|
+
interrupt_after,
|
|
182
|
+
webhook
|
|
183
|
+
} = kwargs;
|
|
184
|
+
return {
|
|
185
|
+
input,
|
|
186
|
+
command,
|
|
187
|
+
config,
|
|
188
|
+
context,
|
|
189
|
+
stream_mode,
|
|
190
|
+
interrupt_before,
|
|
191
|
+
interrupt_after,
|
|
192
|
+
...typeof webhook === "string" ? { webhook } : {}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async function readLanggraphDevState(langgraphApiDir) {
|
|
196
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
197
|
+
const [opsRaw, storeRaw, checkpointerRaw] = await Promise.all([
|
|
198
|
+
readSuperjsonFile(path.join(langgraphApiDir, OPS_FILE)),
|
|
199
|
+
readSuperjsonFile(path.join(langgraphApiDir, STORE_FILE)),
|
|
200
|
+
readSuperjsonFile(path.join(langgraphApiDir, CHECKPOINTER_FILE))
|
|
201
|
+
]);
|
|
202
|
+
if (!opsRaw && !storeRaw && !checkpointerRaw) return null;
|
|
203
|
+
const ops = opsRaw ? validateShape(langgraphOpsSchema, opsRaw, OPS_FILE) : null;
|
|
204
|
+
const storeFile = storeRaw ? validateShape(langgraphStoreFileSchema, storeRaw, STORE_FILE) : null;
|
|
205
|
+
const checkpointerFile = checkpointerRaw ? validateShape(langgraphCheckpointerSchema, checkpointerRaw, CHECKPOINTER_FILE) : null;
|
|
206
|
+
const runEntries = Object.entries(ops?.runs ?? {});
|
|
207
|
+
const items = [];
|
|
208
|
+
if (storeFile?.data) {
|
|
209
|
+
for (const namespaceItems of storeFile.data.values()) {
|
|
210
|
+
for (const stored of namespaceItems.values()) {
|
|
211
|
+
const item = {
|
|
212
|
+
namespace: stored.namespace,
|
|
213
|
+
key: stored.key,
|
|
214
|
+
value: stored.value,
|
|
215
|
+
createdAt: toIso(stored.createdAt, now),
|
|
216
|
+
updatedAt: toIso(stored.updatedAt, now)
|
|
217
|
+
};
|
|
218
|
+
items.push([JSON.stringify([stored.namespace, stored.key]), item]);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const store = {
|
|
223
|
+
assistants: Object.entries(ops?.assistants ?? {}).map(([id, row]) => [
|
|
224
|
+
id,
|
|
225
|
+
toAssistant(row, now)
|
|
226
|
+
]),
|
|
227
|
+
assistantVersions: (ops?.assistant_versions ?? []).map((row) => [
|
|
228
|
+
JSON.stringify([row.assistant_id, row.version]),
|
|
229
|
+
toAssistantVersion(row, now)
|
|
230
|
+
]),
|
|
231
|
+
threads: Object.entries(ops?.threads ?? {}).map(([id, row]) => [id, toThread(row, now)]),
|
|
232
|
+
runs: runEntries.map(([id, row]) => [id, toRun(row, now)]),
|
|
233
|
+
runKwargs: runEntries.map(([id, row]) => [id, toRunKwargs(row.kwargs)]),
|
|
234
|
+
items
|
|
235
|
+
};
|
|
236
|
+
let checkpoints = { storage: {}, writes: {} };
|
|
237
|
+
if (checkpointerFile) {
|
|
238
|
+
const saver = new MemorySaver();
|
|
239
|
+
saver.storage = checkpointerFile.storage;
|
|
240
|
+
saver.writes = checkpointerFile.writes;
|
|
241
|
+
checkpoints = snapshotCheckpointer(saver);
|
|
242
|
+
}
|
|
243
|
+
return { version: 1, store, checkpoints };
|
|
244
|
+
}
|
|
245
|
+
function describeSnapshot(snapshot) {
|
|
246
|
+
return {
|
|
247
|
+
assistants: snapshot.store.assistants.length,
|
|
248
|
+
threads: snapshot.store.threads.length,
|
|
249
|
+
runs: snapshot.store.runs.length,
|
|
250
|
+
items: snapshot.store.items.length,
|
|
251
|
+
checkpointedThreads: Object.keys(snapshot.checkpoints.storage).length
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function supportsRestore(store) {
|
|
255
|
+
return typeof store.restore === "function";
|
|
256
|
+
}
|
|
257
|
+
async function copyCheckpoints(snapshot, target) {
|
|
258
|
+
const source = new MemorySaver();
|
|
259
|
+
hydrateCheckpointer(source, snapshot);
|
|
260
|
+
const tuples = [];
|
|
261
|
+
for await (const tuple of source.list({})) tuples.push(tuple);
|
|
262
|
+
tuples.reverse();
|
|
263
|
+
for (const tuple of tuples) {
|
|
264
|
+
const configurable = tuple.config.configurable ?? {};
|
|
265
|
+
const putConfig = {
|
|
266
|
+
configurable: {
|
|
267
|
+
thread_id: configurable.thread_id,
|
|
268
|
+
checkpoint_ns: configurable.checkpoint_ns ?? "",
|
|
269
|
+
// `put` reads `checkpoint_id` as the PARENT pointer; the child's own id is `checkpoint.id`.
|
|
270
|
+
checkpoint_id: tuple.parentConfig?.configurable?.checkpoint_id
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const stored = await target.put(
|
|
274
|
+
putConfig,
|
|
275
|
+
tuple.checkpoint,
|
|
276
|
+
tuple.metadata ?? {},
|
|
277
|
+
tuple.checkpoint.channel_versions ?? {}
|
|
278
|
+
);
|
|
279
|
+
const writesByTask = /* @__PURE__ */ new Map();
|
|
280
|
+
for (const [taskId, channel, value] of tuple.pendingWrites ?? []) {
|
|
281
|
+
const writes = writesByTask.get(taskId) ?? [];
|
|
282
|
+
writes.push([channel, value]);
|
|
283
|
+
writesByTask.set(taskId, writes);
|
|
284
|
+
}
|
|
285
|
+
for (const [taskId, writes] of writesByTask) {
|
|
286
|
+
await target.putWrites(stored, writes, taskId);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async function loadSnapshotIntoStore(snapshot, store, checkpointer) {
|
|
291
|
+
if (!supportsRestore(store)) {
|
|
292
|
+
throw new Error(
|
|
293
|
+
"Target store does not support bulk import (no restore() method). Use the in-memory or Postgres driver, or implement restore() on your SkeinStore."
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
await store.restore(snapshot.store);
|
|
297
|
+
await copyCheckpoints(snapshot.checkpoints, checkpointer);
|
|
298
|
+
}
|
|
299
|
+
export {
|
|
300
|
+
describeSnapshot,
|
|
301
|
+
loadSnapshotIntoStore,
|
|
302
|
+
readLanggraphDevState
|
|
303
|
+
};
|