@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 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 DATABASE_URL)
24
- queue: "redis", // "memory" | "redis" (redis reads REDIS_URL)
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 `DATABASE_URL`), runs its migrations,
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 `REDIS_URL`).
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 `DATABASE_URL` / `REDIS_URL` throws `RuntimeConfigError`; if assembly fails part-way, any
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 `DATABASE_URL`). */
16
+ /** `"memory"` (default dev) or `"postgres"` (reads `POSTGRES_URI`). */
17
17
  store: StoreDriver;
18
- /** `"memory"` (default dev) or `"redis"` (reads `REDIS_URL`). */
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 { PostgresSkeinStore } from "@skein-js/storage-postgres";
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("DATABASE_URL", "postgres");
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 pgStore = await PostgresSkeinStore.connect(databaseUrl, index ? { index } : {});
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.fromConnString(databaseUrl);
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 { skeinStore: new MemorySkeinStore(), checkpointer: new MemorySaver() };
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("REDIS_URL", "redis");
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.2.1",
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.2.1",
46
- "@skein-js/express": "0.2.1",
47
- "@skein-js/redis": "0.2.1",
48
- "@skein-js/storage-postgres": "0.2.1",
49
- "@skein-js/storage-memory": "0.2.1",
50
- "@skein-js/config": "0.2.1"
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.2.1"
61
+ "@skein-js/test-support": "0.4.0"
62
62
  },
63
63
  "publishConfig": {
64
64
  "access": "public"