@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/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Shared, framework-agnostic building blocks for skein-js HTTP adapters.
|
|
4
4
|
|
|
5
|
-
Part of **[skein-js](../../README.md)** —
|
|
5
|
+
Part of **[skein-js](../../README.md)** — the open-source alternative to LangGraph Platform for TypeScript: a self-hosted [Agent Protocol](https://github.com/langchain-ai/agent-protocol) server for [LangGraph.js](https://github.com/langchain-ai/langgraphjs), and a drop-in replacement for the LangGraph CLI.
|
|
6
6
|
|
|
7
7
|
This package is the common ground the framework adapters ([`@skein-js/express`](../server-express),
|
|
8
8
|
[`@skein-js/fastify`](../server-fastify), [`@skein-js/nestjs`](../server-nestjs),
|
|
@@ -24,8 +24,9 @@ handler table.
|
|
|
24
24
|
`{ deps }` to any adapter. `overrides` swaps in production drivers/auth. See
|
|
25
25
|
[docs/embedding.md](../../docs/embedding.md).
|
|
26
26
|
- **LangGraph dev-state import** — `readLanggraphDevState` / `loadSnapshotIntoStore` /
|
|
27
|
-
`describeSnapshot
|
|
28
|
-
`DevStateSnapshot`, so adopting skein carries
|
|
27
|
+
`describeSnapshot`, from the **`@skein-js/server-kit/dev` subpath**: read an existing
|
|
28
|
+
`.langgraph_api/` directory and reconstruct skein's own `DevStateSnapshot`, so adopting skein carries
|
|
29
|
+
all local state over losslessly.
|
|
29
30
|
- **CORS** — `corsFromHttpConfig` / `toCorsOptions` map a `langgraph.json` `http.cors` block to
|
|
30
31
|
`cors`-style `CorsOptions`; `allowedOrigin` / `corsResponseHeaders` / `applyNodeCors` /
|
|
31
32
|
`sendNodePreflight` derive CORS headers for the adapters without a CORS middleware of their own
|
|
@@ -92,12 +93,39 @@ Pass `overrides` to swap in production drivers or an auth engine while keeping t
|
|
|
92
93
|
`DEFAULT_RUN_CONCURRENCY` (10, matching the LangGraph CLI). The environment is validated even when
|
|
93
94
|
an explicit value is given, so the two sources can't silently disagree. `skein dev`/`start` use it
|
|
94
95
|
to resolve the number they print in the startup banner.
|
|
96
|
+
- **`startHeapPressureMonitor(options): HeapPressureMonitor`** — samples `v8.getHeapStatistics()` on an
|
|
97
|
+
unref'd interval and warns **once per crossing** (85% of the heap limit, re-arming below 70%), with
|
|
98
|
+
in-flight runs and buffered frames alongside so the line distinguishes too-much-concurrency from a slow
|
|
99
|
+
SSE consumer from a leak. `resolveHeapPressureOptions()` reads `SKEIN_HEAP_WARN_PERCENT` (`0` disables)
|
|
100
|
+
and `SKEIN_HEAP_SAMPLE_MS`. Started by `resolveProtocolRuntime` and stopped with the worker, so no
|
|
101
|
+
adapter has to remember it. Free when no logger is configured — it schedules nothing.
|
|
102
|
+
- **`checkHeapHeadroom(): HeapHeadroom`** — the boot-time counterpart: compares V8's ceiling with the
|
|
103
|
+
container's cgroup limit and warns when the automatic sizing does not fit (see
|
|
104
|
+
[deploy.md](../../docs/deploy.md)).
|
|
105
|
+
- **`describePoolPressure(runConcurrency, poolMax): string | undefined`** — warns when the worker can
|
|
106
|
+
execute more runs at once than the Postgres pool can serve.
|
|
107
|
+
- **`resolveMaxPageSize(explicit?, env?): number`** — the same chain for the store page bound:
|
|
108
|
+
explicit `maxPageSize` → `SKEIN_MAX_PAGE_SIZE` → `DEFAULT_MAX_PAGE_SIZE` (1000). Every driver applies
|
|
109
|
+
it to list/search, including when the caller asks for no limit.
|
|
95
110
|
- **`loadInMemoryRuntime` / `loadReloadableInMemoryRuntime`** — assemble a `ProtocolDeps` from a
|
|
96
111
|
`langgraph.json` using in-process drivers. The reloadable variant adds `reloadGraphs` /
|
|
97
112
|
`snapshotState` / `hydrateState` (what powers `skein dev`'s hot reload + cross-restart persistence).
|
|
98
113
|
- **`readLanggraphDevState` / `loadSnapshotIntoStore` / `describeSnapshot`** — read an existing
|
|
99
114
|
`.langgraph_api/` directory and reconstruct a `DevStateSnapshot`, so adopting skein carries local
|
|
100
115
|
state over losslessly.
|
|
116
|
+
|
|
117
|
+
Imported from **`@skein-js/server-kit/dev`**, not the package root:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { readLanggraphDevState } from "@skein-js/server-kit/dev";
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
They carry `superjson` and `node:fs/promises`, and only `skein dev` / `skein import` call them, so
|
|
124
|
+
keeping them on the root barrel put a filesystem snapshot deserializer into every adapter's module
|
|
125
|
+
graph. There is deliberately no root re-export — a re-export is still a static import. The
|
|
126
|
+
`DevStateCounts` _type_ remains exported from the root, since `export type` is erased. See
|
|
127
|
+
[docs/bundling.md](../../docs/bundling.md).
|
|
128
|
+
|
|
101
129
|
- **CORS** — `corsFromHttpConfig` / `toCorsOptions` map a `langgraph.json` `http.cors` block to
|
|
102
130
|
`cors`-style options; `allowedOrigin` / `corsResponseHeaders` / `applyNodeCors` / `sendNodePreflight`
|
|
103
131
|
derive CORS headers for adapters without a CORS middleware of their own.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// src/dev-persistence.ts
|
|
2
|
+
var toBase64 = (bytes) => Buffer.from(bytes).toString("base64");
|
|
3
|
+
var fromBase64 = (text) => new Uint8Array(Buffer.from(text, "base64"));
|
|
4
|
+
var mapValues = (record, fn) => Object.fromEntries(Object.entries(record).map(([key, value]) => [key, fn(value)]));
|
|
5
|
+
function snapshotCheckpointer(saver) {
|
|
6
|
+
return {
|
|
7
|
+
storage: mapValues(
|
|
8
|
+
saver.storage,
|
|
9
|
+
(namespaces) => mapValues(
|
|
10
|
+
namespaces,
|
|
11
|
+
(checkpoints) => mapValues(checkpoints, ([checkpoint, metadata, parentId]) => [
|
|
12
|
+
toBase64(checkpoint),
|
|
13
|
+
toBase64(metadata),
|
|
14
|
+
parentId
|
|
15
|
+
])
|
|
16
|
+
)
|
|
17
|
+
),
|
|
18
|
+
writes: mapValues(
|
|
19
|
+
saver.writes,
|
|
20
|
+
(taskWrites) => mapValues(taskWrites, ([taskId, channel, blob]) => [
|
|
21
|
+
taskId,
|
|
22
|
+
channel,
|
|
23
|
+
toBase64(blob)
|
|
24
|
+
])
|
|
25
|
+
)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function hydrateCheckpointer(saver, snapshot) {
|
|
29
|
+
saver.storage = mapValues(
|
|
30
|
+
snapshot.storage,
|
|
31
|
+
(namespaces) => mapValues(
|
|
32
|
+
namespaces,
|
|
33
|
+
(checkpoints) => mapValues(
|
|
34
|
+
checkpoints,
|
|
35
|
+
([checkpoint, metadata, parentId]) => [
|
|
36
|
+
fromBase64(checkpoint),
|
|
37
|
+
fromBase64(metadata),
|
|
38
|
+
parentId
|
|
39
|
+
]
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
saver.writes = mapValues(
|
|
44
|
+
snapshot.writes,
|
|
45
|
+
(taskWrites) => mapValues(taskWrites, ([taskId, channel, blob]) => [
|
|
46
|
+
taskId,
|
|
47
|
+
channel,
|
|
48
|
+
fromBase64(blob)
|
|
49
|
+
])
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
snapshotCheckpointer,
|
|
55
|
+
hydrateCheckpointer
|
|
56
|
+
};
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hydrateCheckpointer,
|
|
3
|
+
snapshotCheckpointer
|
|
4
|
+
} from "./chunk-JUBBCC7R.js";
|
|
5
|
+
|
|
6
|
+
// src/in-memory-runtime.ts
|
|
7
|
+
import { MemorySaver as MemorySaver2 } from "@langchain/langgraph";
|
|
8
|
+
import {
|
|
9
|
+
loadAuthEngine,
|
|
10
|
+
loadConfig
|
|
11
|
+
} from "@skein-js/config";
|
|
12
|
+
import { MemoryRunEventBus as MemoryRunEventBus2, MemoryRunQueue as MemoryRunQueue2, MemorySkeinStore as MemorySkeinStore2 } from "@skein-js/storage-memory";
|
|
13
|
+
|
|
14
|
+
// src/cors-config.ts
|
|
15
|
+
import {
|
|
16
|
+
filterSkeinRoutes,
|
|
17
|
+
skeinRoutes
|
|
18
|
+
} from "@skein-js/agent-protocol";
|
|
19
|
+
var ALWAYS_EXPOSED_HEADERS = ["content-location", "x-pagination-total"];
|
|
20
|
+
function toCorsOptions(config) {
|
|
21
|
+
const options = {};
|
|
22
|
+
const allowAll = config.allow_origins?.includes("*") ?? false;
|
|
23
|
+
if (config.allow_origin_regex !== void 0) {
|
|
24
|
+
const pattern = new RegExp(`^(?:${config.allow_origin_regex})$`);
|
|
25
|
+
const listed = allowAll ? void 0 : new Set(config.allow_origins);
|
|
26
|
+
options.origin = (origin, callback) => callback(
|
|
27
|
+
null,
|
|
28
|
+
origin !== void 0 && (allowAll || pattern.test(origin) || (listed?.has(origin) ?? false))
|
|
29
|
+
);
|
|
30
|
+
} else if (config.allow_origins !== void 0) {
|
|
31
|
+
options.origin = allowAll ? "*" : config.allow_origins;
|
|
32
|
+
}
|
|
33
|
+
if (config.allow_methods !== void 0) options.methods = config.allow_methods;
|
|
34
|
+
if (config.allow_headers !== void 0) options.allowedHeaders = config.allow_headers;
|
|
35
|
+
if (config.allow_credentials !== void 0) options.credentials = config.allow_credentials;
|
|
36
|
+
if (config.max_age !== void 0) options.maxAge = config.max_age;
|
|
37
|
+
const exposed = /* @__PURE__ */ new Set([...ALWAYS_EXPOSED_HEADERS, ...config.expose_headers ?? []]);
|
|
38
|
+
options.exposedHeaders = [...exposed];
|
|
39
|
+
return options;
|
|
40
|
+
}
|
|
41
|
+
function corsFromHttpConfig(http) {
|
|
42
|
+
if (typeof http !== "object" || http === null) return void 0;
|
|
43
|
+
const cors = http.cors;
|
|
44
|
+
if (typeof cors !== "object" || cors === null) return void 0;
|
|
45
|
+
return toCorsOptions(cors);
|
|
46
|
+
}
|
|
47
|
+
var DISABLE_FLAGS = {
|
|
48
|
+
disable_assistants: "assistants",
|
|
49
|
+
disable_threads: "threads",
|
|
50
|
+
disable_runs: "runs",
|
|
51
|
+
disable_crons: "crons",
|
|
52
|
+
disable_store: "store",
|
|
53
|
+
disable_meta: "meta"
|
|
54
|
+
};
|
|
55
|
+
function disabledRoutesFromHttpConfig(http) {
|
|
56
|
+
if (typeof http !== "object" || http === null) return {};
|
|
57
|
+
const flags = http;
|
|
58
|
+
const disabled = {};
|
|
59
|
+
for (const [flag, group] of Object.entries(DISABLE_FLAGS)) {
|
|
60
|
+
if (flags[flag] === true) disabled[group] = true;
|
|
61
|
+
}
|
|
62
|
+
return disabled;
|
|
63
|
+
}
|
|
64
|
+
function routesFromHttpConfig(http) {
|
|
65
|
+
return filterSkeinRoutes(skeinRoutes, disabledRoutesFromHttpConfig(http));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/in-memory-deps.ts
|
|
69
|
+
import { MemorySaver } from "@langchain/langgraph";
|
|
70
|
+
import { MemoryRunEventBus, MemoryRunQueue, MemorySkeinStore } from "@skein-js/storage-memory";
|
|
71
|
+
|
|
72
|
+
// src/max-page-size.ts
|
|
73
|
+
import { DEFAULT_MAX_PAGE_SIZE } from "@skein-js/core";
|
|
74
|
+
|
|
75
|
+
// src/env-numbers.ts
|
|
76
|
+
import { SkeinConfigError } from "@skein-js/config/errors";
|
|
77
|
+
function requirePositiveInteger(source, raw) {
|
|
78
|
+
const parsed = Number(raw);
|
|
79
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
80
|
+
throw new SkeinConfigError(`${source} must be a positive integer (got "${String(raw)}").`);
|
|
81
|
+
}
|
|
82
|
+
return parsed;
|
|
83
|
+
}
|
|
84
|
+
function positiveIntegerFromEnv(names, env) {
|
|
85
|
+
for (const name of names) {
|
|
86
|
+
const raw = env[name];
|
|
87
|
+
if (raw === void 0 || raw.trim() === "") continue;
|
|
88
|
+
return requirePositiveInteger(name, raw);
|
|
89
|
+
}
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/max-page-size.ts
|
|
94
|
+
var MAX_PAGE_SIZE_ENV_VARS = ["SKEIN_MAX_PAGE_SIZE"];
|
|
95
|
+
function resolveMaxPageSize(explicit, env = process.env) {
|
|
96
|
+
const fromEnv = positiveIntegerFromEnv(MAX_PAGE_SIZE_ENV_VARS, env);
|
|
97
|
+
if (explicit === void 0) return fromEnv ?? DEFAULT_MAX_PAGE_SIZE;
|
|
98
|
+
return requirePositiveInteger("store.maxPageSize", explicit);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/memory-bus-limits.ts
|
|
102
|
+
import {
|
|
103
|
+
DEFAULT_MEMORY_BUS_MAX_FRAMES_PER_RUN,
|
|
104
|
+
DEFAULT_MEMORY_BUS_MAX_RETAINED_RUNS
|
|
105
|
+
} from "@skein-js/storage-memory";
|
|
106
|
+
var MAX_RETAINED_RUNS_ENV = "SKEIN_MEMORY_BUS_MAX_RETAINED_RUNS";
|
|
107
|
+
var MAX_FRAMES_PER_RUN_ENV = "SKEIN_MEMORY_BUS_MAX_FRAMES_PER_RUN";
|
|
108
|
+
function resolveMemoryBusLimits(explicit = {}, env = process.env) {
|
|
109
|
+
const retainedFromEnv = positiveIntegerFromEnv([MAX_RETAINED_RUNS_ENV], env);
|
|
110
|
+
const framesFromEnv = positiveIntegerFromEnv([MAX_FRAMES_PER_RUN_ENV], env);
|
|
111
|
+
return {
|
|
112
|
+
maxRetainedRuns: explicit.maxRetainedRuns === void 0 ? retainedFromEnv ?? DEFAULT_MEMORY_BUS_MAX_RETAINED_RUNS : requirePositiveInteger("maxRetainedRuns", explicit.maxRetainedRuns),
|
|
113
|
+
maxFramesPerRun: explicit.maxFramesPerRun === void 0 ? framesFromEnv ?? DEFAULT_MEMORY_BUS_MAX_FRAMES_PER_RUN : requirePositiveInteger("maxFramesPerRun", explicit.maxFramesPerRun)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/in-memory-deps.ts
|
|
118
|
+
function isGraphResolver(graphs) {
|
|
119
|
+
const candidate = graphs;
|
|
120
|
+
return Array.isArray(candidate.ids) && typeof candidate.load === "function";
|
|
121
|
+
}
|
|
122
|
+
function normalizeEmbeddableGraphs(graphs) {
|
|
123
|
+
return isGraphResolver(graphs) ? graphs : graphMapToResolver(graphs);
|
|
124
|
+
}
|
|
125
|
+
function graphMapToResolver(graphs) {
|
|
126
|
+
const ids = Object.keys(graphs);
|
|
127
|
+
return {
|
|
128
|
+
ids,
|
|
129
|
+
load: async (graphId) => {
|
|
130
|
+
const graph = graphs[graphId];
|
|
131
|
+
if (graph == null) {
|
|
132
|
+
const known = ids.join(", ") || "none";
|
|
133
|
+
throw new Error(
|
|
134
|
+
ids.includes(graphId) ? `Graph "${graphId}" resolved to ${String(graph)} \u2014 check its export/factory (known: ${known}).` : `Unknown graph "${graphId}" (known: ${known}).`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return graph;
|
|
138
|
+
},
|
|
139
|
+
schemas: async (graphId) => ({ [graphId]: { graph_id: graphId } })
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function embedInMemoryGraphs(graphs, overrides = {}) {
|
|
143
|
+
return {
|
|
144
|
+
// `maxPageSize` resolved for the same reason as the bus limits below: an embedded host's
|
|
145
|
+
// `SKEIN_MAX_PAGE_SIZE` has to reach the driver that applies it.
|
|
146
|
+
store: new MemorySkeinStore({ maxPageSize: resolveMaxPageSize() }),
|
|
147
|
+
graphs: normalizeEmbeddableGraphs(graphs),
|
|
148
|
+
queue: new MemoryRunQueue(),
|
|
149
|
+
// Resolved rather than defaulted, so `SKEIN_MEMORY_BUS_*` reaches an embedded host too — this is
|
|
150
|
+
// the driver set a long-lived single-process deployment actually runs on.
|
|
151
|
+
bus: new MemoryRunEventBus(resolveMemoryBusLimits()),
|
|
152
|
+
checkpointer: new MemorySaver(),
|
|
153
|
+
...overrides
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
var createInMemoryDeps = embedInMemoryGraphs;
|
|
157
|
+
|
|
158
|
+
// src/in-memory-runtime.ts
|
|
159
|
+
function toGraphResolver(graphs) {
|
|
160
|
+
return {
|
|
161
|
+
ids: graphs.ids,
|
|
162
|
+
load: (graphId) => graphs.load(graphId),
|
|
163
|
+
schemas: async (graphId) => await graphs.schemas(graphId)
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async function loadInMemoryRuntime(configPath, importModule, staticSchemas) {
|
|
167
|
+
const { graphs, config, configDir } = await loadConfig({
|
|
168
|
+
configPath,
|
|
169
|
+
importModule,
|
|
170
|
+
staticSchemas
|
|
171
|
+
});
|
|
172
|
+
const deps = embedInMemoryGraphs(toGraphResolver(graphs));
|
|
173
|
+
deps.auth = await loadAuthEngine(config.auth, { configDir, importModule });
|
|
174
|
+
return {
|
|
175
|
+
deps,
|
|
176
|
+
cors: corsFromHttpConfig(config.http),
|
|
177
|
+
routes: routesFromHttpConfig(config.http)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function loadReloadableInMemoryRuntime(configPath, importModule, staticSchemas, extraDeps) {
|
|
181
|
+
const first = await loadConfig({ configPath, importModule, staticSchemas });
|
|
182
|
+
let current = first.graphs;
|
|
183
|
+
const graphs = {
|
|
184
|
+
ids: first.graphs.ids,
|
|
185
|
+
load: (graphId) => current.load(graphId),
|
|
186
|
+
schemas: async (graphId) => await current.schemas(graphId)
|
|
187
|
+
};
|
|
188
|
+
const store = new MemorySkeinStore2({ maxPageSize: resolveMaxPageSize() });
|
|
189
|
+
const checkpointer = new MemorySaver2();
|
|
190
|
+
const deps = {
|
|
191
|
+
store,
|
|
192
|
+
graphs,
|
|
193
|
+
queue: new MemoryRunQueue2(),
|
|
194
|
+
// This is the path `skein start` and `skein up` take by default, so it is the longest-lived
|
|
195
|
+
// memory bus skein runs — the bounds have to be resolved here too, not just on the embed paths.
|
|
196
|
+
bus: new MemoryRunEventBus2(resolveMemoryBusLimits()),
|
|
197
|
+
checkpointer,
|
|
198
|
+
auth: await loadAuthEngine(first.config.auth, { configDir: first.configDir, importModule }),
|
|
199
|
+
...extraDeps
|
|
200
|
+
};
|
|
201
|
+
return {
|
|
202
|
+
deps,
|
|
203
|
+
cors: corsFromHttpConfig(first.config.http),
|
|
204
|
+
routes: routesFromHttpConfig(first.config.http),
|
|
205
|
+
config: first.config,
|
|
206
|
+
configDir: first.configDir,
|
|
207
|
+
reloadGraphs: async () => {
|
|
208
|
+
current = (await loadConfig({ configPath, importModule, staticSchemas })).graphs;
|
|
209
|
+
},
|
|
210
|
+
snapshotState: () => ({
|
|
211
|
+
version: 1,
|
|
212
|
+
store: store.snapshot(),
|
|
213
|
+
checkpoints: snapshotCheckpointer(checkpointer)
|
|
214
|
+
}),
|
|
215
|
+
hydrateState: (snapshot) => {
|
|
216
|
+
store.hydrate(snapshot.store);
|
|
217
|
+
hydrateCheckpointer(checkpointer, snapshot.checkpoints);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export {
|
|
223
|
+
requirePositiveInteger,
|
|
224
|
+
positiveIntegerFromEnv,
|
|
225
|
+
toCorsOptions,
|
|
226
|
+
corsFromHttpConfig,
|
|
227
|
+
disabledRoutesFromHttpConfig,
|
|
228
|
+
routesFromHttpConfig,
|
|
229
|
+
resolveMaxPageSize,
|
|
230
|
+
resolveMemoryBusLimits,
|
|
231
|
+
normalizeEmbeddableGraphs,
|
|
232
|
+
graphMapToResolver,
|
|
233
|
+
embedInMemoryGraphs,
|
|
234
|
+
createInMemoryDeps,
|
|
235
|
+
loadInMemoryRuntime,
|
|
236
|
+
loadReloadableInMemoryRuntime
|
|
237
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { BaseCheckpointSaver } from '@langchain/langgraph';
|
|
2
|
+
import { SkeinStore } from '@skein-js/core';
|
|
3
|
+
import { MemoryStoreSnapshot } from '@skein-js/storage-memory';
|
|
4
|
+
|
|
5
|
+
/** The checkpoint tuple `[checkpoint, metadata, parentId?]` with the blobs base64-encoded. */
|
|
6
|
+
type SerializedCheckpointTuple = [string, string, string | undefined];
|
|
7
|
+
/** `MemorySaver.storage` (thread → namespace → checkpointId → tuple) with blobs base64-encoded. */
|
|
8
|
+
type SerializedCheckpointStorage = Record<string, Record<string, Record<string, SerializedCheckpointTuple>>>;
|
|
9
|
+
/** `MemorySaver.writes` (key → taskId+idx → `[taskId, channel, blob]`) with the blob base64-encoded. */
|
|
10
|
+
type SerializedCheckpointWrites = Record<string, Record<string, [string, string, string]>>;
|
|
11
|
+
interface CheckpointerSnapshot {
|
|
12
|
+
storage: SerializedCheckpointStorage;
|
|
13
|
+
writes: SerializedCheckpointWrites;
|
|
14
|
+
}
|
|
15
|
+
/** A JSON-serializable snapshot of the whole in-memory dev runtime. */
|
|
16
|
+
interface DevStateSnapshot {
|
|
17
|
+
version: 1;
|
|
18
|
+
store: MemoryStoreSnapshot;
|
|
19
|
+
checkpoints: CheckpointerSnapshot;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Read a LangGraph `.langgraph_api/` directory and reconstruct skein's `DevStateSnapshot`.
|
|
24
|
+
* Returns `null` when the directory holds none of the expected files (nothing to import).
|
|
25
|
+
*/
|
|
26
|
+
declare function readLanggraphDevState(langgraphApiDir: string): Promise<DevStateSnapshot | null>;
|
|
27
|
+
/** Row/checkpoint counts in a snapshot, for CLI + log summaries. */
|
|
28
|
+
interface DevStateCounts {
|
|
29
|
+
assistants: number;
|
|
30
|
+
threads: number;
|
|
31
|
+
runs: number;
|
|
32
|
+
items: number;
|
|
33
|
+
/** Threads that carry graph checkpoint history. */
|
|
34
|
+
checkpointedThreads: number;
|
|
35
|
+
}
|
|
36
|
+
declare function describeSnapshot(snapshot: DevStateSnapshot): DevStateCounts;
|
|
37
|
+
/**
|
|
38
|
+
* Load a `DevStateSnapshot` into a live store + checkpointer — the sink for importing into a real
|
|
39
|
+
* skein deployment (e.g. Postgres). Resource rows go through the driver's `restore` (ids +
|
|
40
|
+
* timestamps preserved, `ON CONFLICT DO NOTHING` so re-runs are safe); checkpoints — graph state +
|
|
41
|
+
* full history — are copied via the public checkpointer API. Throws if the store can't bulk-restore
|
|
42
|
+
* (both first-party drivers can); a custom driver must implement `restore` to be an import target.
|
|
43
|
+
*/
|
|
44
|
+
declare function loadSnapshotIntoStore(snapshot: DevStateSnapshot, store: SkeinStore, checkpointer: BaseCheckpointSaver): Promise<void>;
|
|
45
|
+
|
|
46
|
+
export { type DevStateSnapshot as D, type DevStateCounts as a, describeSnapshot as d, loadSnapshotIntoStore as l, readLanggraphDevState as r };
|
package/dist/dev.d.ts
ADDED