@skein-js/runtime 0.2.1 → 0.4.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 +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +52 -6
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -20,8 +20,8 @@ import { createExpressServer } from "@skein-js/express";
|
|
|
20
20
|
|
|
21
21
|
const runtime = await buildRuntime({
|
|
22
22
|
configPath: "/abs/path/to/langgraph.json",
|
|
23
|
-
store: "postgres", // "memory" | "postgres" (postgres reads
|
|
24
|
-
queue: "redis", // "memory" | "redis" (redis reads
|
|
23
|
+
store: "postgres", // "memory" | "postgres" (postgres reads POSTGRES_URI)
|
|
24
|
+
queue: "redis", // "memory" | "redis" (redis reads REDIS_URI)
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
const server = await createExpressServer({ deps: runtime.deps, cors: runtime.cors });
|
|
@@ -33,13 +33,13 @@ await runtime.dispose();
|
|
|
33
33
|
`store` and `queue` are **required** (no defaults — the CLI supplies its own flag defaults). The
|
|
34
34
|
driver branches:
|
|
35
35
|
|
|
36
|
-
- **`store: "postgres"`** connects `PostgresSkeinStore` (from `
|
|
36
|
+
- **`store: "postgres"`** connects `PostgresSkeinStore` (from `POSTGRES_URI`), runs its migrations,
|
|
37
37
|
and uses `PostgresSaver` as the LangGraph checkpointer.
|
|
38
|
-
- **`queue: "redis"`** uses the BullMQ run queue + Redis Streams/pub-sub event bus (from `
|
|
38
|
+
- **`queue: "redis"`** uses the BullMQ run queue + Redis Streams/pub-sub event bus (from `REDIS_URI`).
|
|
39
39
|
- **`store: "memory"` + `queue: "memory"`** delegates to [`@skein-js/express`](../server-express)'s
|
|
40
40
|
reloadable in-memory runtime, so `skein dev`'s hot-reload and cross-restart state persistence work.
|
|
41
41
|
|
|
42
|
-
A missing `
|
|
42
|
+
A missing `POSTGRES_URI` / `REDIS_URI` throws `RuntimeConfigError`; if assembly fails part-way, any
|
|
43
43
|
resources already created are disposed before rethrowing, so a failed build leaks nothing.
|
|
44
44
|
|
|
45
45
|
Graph hot-reload (`reloadGraphs()`) works in every mode; `snapshotState`/`hydrateState` are present
|
package/dist/index.d.ts
CHANGED
|
@@ -13,9 +13,9 @@ interface BuildRuntimeOptions {
|
|
|
13
13
|
configPath: string;
|
|
14
14
|
/** TS-capable importer (e.g. the CLI's vite loader). Omitted for plain JS/Node resolution. */
|
|
15
15
|
importModule?: ModuleImporter;
|
|
16
|
-
/** `"memory"` (default dev) or `"postgres"` (reads `
|
|
16
|
+
/** `"memory"` (default dev) or `"postgres"` (reads `POSTGRES_URI`). */
|
|
17
17
|
store: StoreDriver;
|
|
18
|
-
/** `"memory"` (default dev) or `"redis"` (reads `
|
|
18
|
+
/** `"memory"` (default dev) or `"redis"` (reads `REDIS_URI`). */
|
|
19
19
|
queue: QueueDriver;
|
|
20
20
|
}
|
|
21
21
|
interface SkeinRuntime {
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
} from "@skein-js/express";
|
|
12
12
|
import { RedisRunEventBus, RedisRunQueue } from "@skein-js/redis";
|
|
13
13
|
import { MemoryRunEventBus, MemoryRunQueue, MemorySkeinStore } from "@skein-js/storage-memory";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createPostgresPool,
|
|
16
|
+
PostgresSkeinStore
|
|
17
|
+
} from "@skein-js/storage-postgres";
|
|
15
18
|
|
|
16
19
|
// src/errors.ts
|
|
17
20
|
var RuntimeConfigError = class extends Error {
|
|
@@ -104,6 +107,20 @@ function requireEnv(name, driver) {
|
|
|
104
107
|
}
|
|
105
108
|
return value;
|
|
106
109
|
}
|
|
110
|
+
function postgresConnectionOptions() {
|
|
111
|
+
const options = {};
|
|
112
|
+
const rawMax = process.env["PG_POOL_MAX"];
|
|
113
|
+
if (rawMax !== void 0 && rawMax.trim() !== "") {
|
|
114
|
+
const max = Number(rawMax);
|
|
115
|
+
if (!Number.isInteger(max) || max <= 0) {
|
|
116
|
+
throw new RuntimeConfigError(`PG_POOL_MAX must be a positive integer (got "${rawMax}").`);
|
|
117
|
+
}
|
|
118
|
+
options.poolMax = max;
|
|
119
|
+
}
|
|
120
|
+
const noVerify = process.env["DATABASE_SSL_NO_VERIFY"];
|
|
121
|
+
if (noVerify === "1" || noVerify?.toLowerCase() === "true") options.sslNoVerify = true;
|
|
122
|
+
return options;
|
|
123
|
+
}
|
|
107
124
|
function reroutableGraphResolver(initial) {
|
|
108
125
|
let current = initial;
|
|
109
126
|
return {
|
|
@@ -148,26 +165,45 @@ async function buildRuntime(options) {
|
|
|
148
165
|
await Promise.allSettled(disposers.map((dispose) => dispose()));
|
|
149
166
|
};
|
|
150
167
|
try {
|
|
168
|
+
const storeTtl = resolveStoreTtl(first.config.store?.ttl);
|
|
151
169
|
const { skeinStore, checkpointer } = await (async () => {
|
|
152
170
|
if (store === "postgres") {
|
|
153
|
-
const databaseUrl = requireEnv("
|
|
171
|
+
const databaseUrl = requireEnv("POSTGRES_URI", "postgres");
|
|
154
172
|
const index = await resolveStoreIndex(first.config.store?.index, {
|
|
155
173
|
configDir: first.configDir,
|
|
156
174
|
importModule
|
|
157
175
|
});
|
|
158
|
-
const
|
|
176
|
+
const connectionOptions = postgresConnectionOptions();
|
|
177
|
+
const pgStore = await PostgresSkeinStore.connect(databaseUrl, {
|
|
178
|
+
...index ? { index } : {},
|
|
179
|
+
...storeTtl ? { ttl: storeTtl } : {},
|
|
180
|
+
...connectionOptions
|
|
181
|
+
});
|
|
159
182
|
disposers.push(() => pgStore.close());
|
|
160
183
|
await pgStore.migrate();
|
|
161
|
-
const saver = PostgresSaver
|
|
184
|
+
const saver = new PostgresSaver(createPostgresPool(databaseUrl, connectionOptions));
|
|
162
185
|
disposers.push(() => saver.end());
|
|
163
186
|
await saver.setup();
|
|
164
187
|
return { skeinStore: pgStore, checkpointer: saver };
|
|
165
188
|
}
|
|
166
|
-
return {
|
|
189
|
+
return {
|
|
190
|
+
skeinStore: new MemorySkeinStore(storeTtl ? { ttl: storeTtl } : void 0),
|
|
191
|
+
checkpointer: new MemorySaver()
|
|
192
|
+
};
|
|
167
193
|
})();
|
|
194
|
+
if (storeTtl) {
|
|
195
|
+
const everyMs = (storeTtl.sweepIntervalMinutes ?? 60) * 6e4;
|
|
196
|
+
const sweeper = setInterval(() => {
|
|
197
|
+
skeinStore.store.sweepExpired().catch((error) => {
|
|
198
|
+
console.error("skein: store TTL sweep failed", error);
|
|
199
|
+
});
|
|
200
|
+
}, everyMs);
|
|
201
|
+
sweeper.unref();
|
|
202
|
+
disposers.push(async () => clearInterval(sweeper));
|
|
203
|
+
}
|
|
168
204
|
const { runQueue, bus } = (() => {
|
|
169
205
|
if (queue === "redis") {
|
|
170
|
-
const redisUrl = requireEnv("
|
|
206
|
+
const redisUrl = requireEnv("REDIS_URI", "redis");
|
|
171
207
|
const redisQueue = new RedisRunQueue(redisUrl);
|
|
172
208
|
disposers.push(() => redisQueue.dispose());
|
|
173
209
|
const redisBus = new RedisRunEventBus(redisUrl);
|
|
@@ -200,6 +236,16 @@ async function buildRuntime(options) {
|
|
|
200
236
|
throw error;
|
|
201
237
|
}
|
|
202
238
|
}
|
|
239
|
+
function resolveStoreTtl(raw) {
|
|
240
|
+
if (!raw) return void 0;
|
|
241
|
+
const ttl = {};
|
|
242
|
+
if (typeof raw.default_ttl === "number") ttl.defaultTtl = raw.default_ttl;
|
|
243
|
+
if (typeof raw.refresh_on_read === "boolean") ttl.refreshOnRead = raw.refresh_on_read;
|
|
244
|
+
if (typeof raw.sweep_interval_minutes === "number") {
|
|
245
|
+
ttl.sweepIntervalMinutes = raw.sweep_interval_minutes;
|
|
246
|
+
}
|
|
247
|
+
return Object.keys(ttl).length > 0 ? ttl : void 0;
|
|
248
|
+
}
|
|
203
249
|
export {
|
|
204
250
|
RuntimeConfigError,
|
|
205
251
|
buildRuntime,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skein-js/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Assembles skein-js ProtocolDeps from langgraph.json + selected drivers (memory/Postgres/Redis).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Maina Wycliffe <wmmaina7@gmail.com>",
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"cors": "^2.8.5",
|
|
45
|
-
"@skein-js/agent-protocol": "0.
|
|
46
|
-
"@skein-js/
|
|
47
|
-
"@skein-js/
|
|
48
|
-
"@skein-js/storage-
|
|
49
|
-
"@skein-js/storage-
|
|
50
|
-
"@skein-js/
|
|
45
|
+
"@skein-js/agent-protocol": "0.4.0",
|
|
46
|
+
"@skein-js/config": "0.4.0",
|
|
47
|
+
"@skein-js/express": "0.4.0",
|
|
48
|
+
"@skein-js/storage-memory": "0.4.0",
|
|
49
|
+
"@skein-js/storage-postgres": "0.4.0",
|
|
50
|
+
"@skein-js/redis": "0.4.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@langchain/langgraph": "^1.4.0",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@langchain/langgraph": "^1.4.0",
|
|
59
59
|
"@langchain/langgraph-checkpoint-postgres": "^1.0.4",
|
|
60
60
|
"@types/cors": "^2.8.17",
|
|
61
|
-
"@skein-js/test-support": "0.
|
|
61
|
+
"@skein-js/test-support": "0.4.0"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public"
|