skein-js 0.9.0 → 0.9.1

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.
Files changed (3) hide show
  1. package/README.md +16 -9
  2. package/dist/index.js +40 -8
  3. package/package.json +6 -5
package/README.md CHANGED
@@ -67,15 +67,22 @@ any layer. Public-registry builds don't need it.
67
67
 
68
68
  ## `skein dev` flags
69
69
 
70
- | Flag | Values | Default | Notes |
71
- | ------------------ | -------------------- | ----------- | -------------------------------------------------------------- |
72
- | `-p, --port` | number | `2024` | Port to listen on. |
73
- | `--host` | host | `127.0.0.1` | Interface to bind. |
74
- | `--store <driver>` | `memory`, `postgres` | `memory` | `postgres` reads `POSTGRES_URI`; also selects `PostgresSaver`. |
75
- | `--queue <driver>` | `memory`, `redis` | `memory` | `redis` reads `REDIS_URI` (BullMQ queue + Redis Streams bus). |
76
- | `--no-persist` | | persists | Don't snapshot dev state to `.skein/` across restarts. |
77
- | `--no-reload` | | reloads | Disable hot reload on source change. |
78
- | `-v, --verbose` | — | off | Log per-run activity (tool calls, interrupts, timing). |
70
+ | Flag | Values | Default | Notes |
71
+ | ------------------------- | -------------------- | ----------- | -------------------------------------------------------------- |
72
+ | `-p, --port` | number | `2024` | Port to listen on. |
73
+ | `--host` | host | `127.0.0.1` | Interface to bind. |
74
+ | `--store <driver>` | `memory`, `postgres` | `memory` | `postgres` reads `POSTGRES_URI`; also selects `PostgresSaver`. |
75
+ | `--queue <driver>` | `memory`, `redis` | `memory` | `redis` reads `REDIS_URI` (BullMQ queue + Redis Streams bus). |
76
+ | `--concurrency` | number | `10` | Queued runs the background worker executes at once. |
77
+ | `-n, --n-jobs-per-worker` | number | `10` | LangGraph-compatible alias for `--concurrency`. |
78
+ | `--no-persist` | — | persists | Don't snapshot dev state to `.skein/` across restarts. |
79
+ | `--no-reload` | — | reloads | Disable hot reload on source change. |
80
+ | `-v, --verbose` | — | off | Log per-run activity (tool calls, interrupts, timing). |
81
+
82
+ `--store`, `--queue`, `--concurrency`, and `-n, --n-jobs-per-worker` are accepted by `skein start`
83
+ too. Concurrency also reads `SKEIN_RUN_CONCURRENCY` (or `N_JOBS_PER_WORKER`) when no flag is passed —
84
+ the path that reaches a container. See
85
+ [runs-and-redis.md](../../docs/runs-and-redis.md#run-concurrency).
79
86
 
80
87
  `skein dev --store postgres --queue redis` is a capability the LangGraph CLI does **not** offer: it
81
88
  lets you develop against **production-shaped** storage (durable Postgres checkpoints, pgvector
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  readLanggraphDevState
15
15
  } from "@skein-js/express";
16
16
  import { buildRuntime } from "@skein-js/runtime";
17
+ import { resolveRunConcurrency } from "@skein-js/server-kit";
17
18
 
18
19
  // src/colors.ts
19
20
  var colorEnabled = process.stdout.isTTY === true && process.env.NO_COLOR === void 0;
@@ -27,7 +28,7 @@ var dim = paint(2);
27
28
 
28
29
  // src/banner.ts
29
30
  function printBanner(info, logger2) {
30
- const { host, port, graphIds, authPath, workerCount } = info;
31
+ const { host, port, graphIds, authPath, runConcurrency } = info;
31
32
  const base = `http://${host}:${port}`;
32
33
  console.log();
33
34
  console.log(`${bold(green("skein"))} ${dim("\xB7 Agent Protocol dev server")}`);
@@ -37,7 +38,9 @@ function printBanner(info, logger2) {
37
38
  console.log();
38
39
  for (const id of graphIds) logger2.info(`Registering graph with id '${id}'`);
39
40
  if (authPath) logger2.info(`Loading auth from ${authPath}`);
40
- logger2.info(`Starting ${workerCount} worker${workerCount === 1 ? "" : "s"}`);
41
+ logger2.info(
42
+ runConcurrency === 1 ? "Starting 1 worker" : `Starting 1 worker, up to ${runConcurrency} concurrent runs`
43
+ );
41
44
  logger2.info(`Server running at ${base}`);
42
45
  }
43
46
 
@@ -225,6 +228,7 @@ async function runDev(options) {
225
228
  });
226
229
  const port = options.portExplicit ? options.port : envPort(options.port);
227
230
  const host = options.hostExplicit ? options.host : envHost(options.host);
231
+ const runConcurrency = resolveRunConcurrency(options.concurrency ?? options.nJobsPerWorker);
228
232
  const canPersist = options.persist && runtime.snapshotState !== void 0;
229
233
  if (options.persist && runtime.snapshotState === void 0) {
230
234
  console.log(
@@ -263,7 +267,8 @@ async function runDev(options) {
263
267
  deps: runtime.deps,
264
268
  cors: runtime.cors,
265
269
  warm: true,
266
- logger: devLogger
270
+ logger: devLogger,
271
+ worker: { maxConcurrency: runConcurrency }
267
272
  });
268
273
  await server.listen(port, host);
269
274
  } catch (error) {
@@ -278,7 +283,7 @@ async function runDev(options) {
278
283
  port,
279
284
  graphIds: runtime.deps.graphs.ids,
280
285
  authPath: config.auth?.path,
281
- workerCount: 1
286
+ runConcurrency
282
287
  },
283
288
  devLogger
284
289
  );
@@ -925,6 +930,7 @@ import { createExpressServer as createExpressServer2 } from "@skein-js/express";
925
930
  import {
926
931
  buildRuntime as buildRuntime3
927
932
  } from "@skein-js/runtime";
933
+ import { resolveRunConcurrency as resolveRunConcurrency2 } from "@skein-js/server-kit";
928
934
  var FORCE_EXIT_MS2 = 5e3;
929
935
  var logger = createDevLogger();
930
936
  function readBakedSchemas(configDir) {
@@ -941,11 +947,13 @@ async function runStart(options) {
941
947
  let schemas;
942
948
  let configDir;
943
949
  let authPath;
950
+ let runConcurrency;
944
951
  try {
945
952
  const loaded = await loadConfig5({ configPath });
946
953
  configDir = loaded.configDir;
947
954
  authPath = loaded.config.auth?.path;
948
955
  await applyProjectEnv(loaded.config, configDir);
956
+ runConcurrency = resolveRunConcurrency2(options.concurrency ?? options.nJobsPerWorker);
949
957
  schemas = readBakedSchemas(configDir);
950
958
  } catch (error) {
951
959
  console.error(`skein: ${error instanceof Error ? error.message : String(error)}`);
@@ -974,7 +982,8 @@ async function runStart(options) {
974
982
  deps: runtime.deps,
975
983
  cors: runtime.cors,
976
984
  warm: true,
977
- logger
985
+ logger,
986
+ worker: { maxConcurrency: runConcurrency }
978
987
  });
979
988
  await server.listen(port, host);
980
989
  } catch (error) {
@@ -983,7 +992,7 @@ async function runStart(options) {
983
992
  process.exitCode = 1;
984
993
  return;
985
994
  }
986
- printBanner({ host, port, graphIds: runtime.deps.graphs.ids, authPath, workerCount: 1 }, logger);
995
+ printBanner({ host, port, graphIds: runtime.deps.graphs.ids, authPath, runConcurrency }, logger);
987
996
  let shuttingDown = false;
988
997
  const shutdown = () => {
989
998
  if (shuttingDown) return;
@@ -1006,6 +1015,13 @@ function parsePort(value) {
1006
1015
  }
1007
1016
  return port;
1008
1017
  }
1018
+ function parseConcurrency(value) {
1019
+ const concurrency = Number(value);
1020
+ if (!Number.isInteger(concurrency) || concurrency <= 0) {
1021
+ throw new InvalidArgumentError("Concurrency must be a positive integer.");
1022
+ }
1023
+ return concurrency;
1024
+ }
1009
1025
  function parseChoice(choices) {
1010
1026
  return (value) => {
1011
1027
  if (!choices.includes(value)) {
@@ -1019,14 +1035,30 @@ var parseQueue = parseChoice(["memory", "redis"]);
1019
1035
  var program = new Command().name("skein").description(
1020
1036
  "Agent Protocol server for LangGraph.js \u2014 a drop-in replacement for the LangGraph CLI."
1021
1037
  ).version(version, "-v, --version");
1022
- program.command("dev").description("Run the in-process dev server with hot reload (no Docker).").option("-c, --config <path>", "Path to langgraph.json", "langgraph.json").option("-p, --port <port>", "Port to bind", parsePort, 2024).option("--host <host>", "Host to bind", "127.0.0.1").option("--no-reload", "Disable hot reload").option("--no-persist", "Don't persist dev state to .skein/ between restarts").option("--store <driver>", "Store driver: memory | postgres", parseStore, "memory").option("--queue <driver>", "Queue driver: memory | redis", parseQueue, "memory").option("-v, --verbose", "Log per-run activity: start/finish, tool calls, and interrupts").action(
1038
+ program.command("dev").description("Run the in-process dev server with hot reload (no Docker).").option("-c, --config <path>", "Path to langgraph.json", "langgraph.json").option("-p, --port <port>", "Port to bind", parsePort, 2024).option("--host <host>", "Host to bind", "127.0.0.1").option("--no-reload", "Disable hot reload").option("--no-persist", "Don't persist dev state to .skein/ between restarts").option("--store <driver>", "Store driver: memory | postgres", parseStore, "memory").option("--queue <driver>", "Queue driver: memory | redis", parseQueue, "memory").option(
1039
+ "--concurrency <count>",
1040
+ "Queued runs the background worker executes at once (default 10; env SKEIN_RUN_CONCURRENCY)",
1041
+ parseConcurrency
1042
+ ).option(
1043
+ "-n, --n-jobs-per-worker <count>",
1044
+ "Alias for --concurrency (LangGraph CLI compatibility)",
1045
+ parseConcurrency
1046
+ ).option("-v, --verbose", "Log per-run activity: start/finish, tool calls, and interrupts").action(
1023
1047
  (options, command) => runDev({
1024
1048
  ...options,
1025
1049
  portExplicit: command.getOptionValueSource("port") === "cli",
1026
1050
  hostExplicit: command.getOptionValueSource("host") === "cli"
1027
1051
  })
1028
1052
  );
1029
- program.command("start").description("Serve a pre-built .skein/build artifact (the production image entrypoint).").option("-c, --config <path>", "Path to the artifact's langgraph.json", "langgraph.json").option("-p, --port <port>", "Port to bind", parsePort, 2024).option("--host <host>", "Host to bind", "127.0.0.1").option("--store <driver>", "Store driver: memory | postgres", parseStore, "memory").option("--queue <driver>", "Queue driver: memory | redis", parseQueue, "memory").option("-v, --verbose", "Log per-run activity: start/finish, tool calls, and interrupts").action(
1053
+ program.command("start").description("Serve a pre-built .skein/build artifact (the production image entrypoint).").option("-c, --config <path>", "Path to the artifact's langgraph.json", "langgraph.json").option("-p, --port <port>", "Port to bind", parsePort, 2024).option("--host <host>", "Host to bind", "127.0.0.1").option("--store <driver>", "Store driver: memory | postgres", parseStore, "memory").option("--queue <driver>", "Queue driver: memory | redis", parseQueue, "memory").option(
1054
+ "--concurrency <count>",
1055
+ "Queued runs the background worker executes at once (default 10; env SKEIN_RUN_CONCURRENCY)",
1056
+ parseConcurrency
1057
+ ).option(
1058
+ "-n, --n-jobs-per-worker <count>",
1059
+ "Alias for --concurrency (LangGraph CLI compatibility)",
1060
+ parseConcurrency
1061
+ ).option("-v, --verbose", "Log per-run activity: start/finish, tool calls, and interrupts").action(
1030
1062
  (options, command) => runStart({
1031
1063
  ...options,
1032
1064
  portExplicit: command.getOptionValueSource("port") === "cli",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skein-js",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "The skein-js CLI — a drop-in replacement for the LangGraph CLI (dev/up/build/dockerfile).",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Maina Wycliffe <wmmaina7@gmail.com>",
@@ -47,10 +47,11 @@
47
47
  "@commander-js/extra-typings": "~13.1.0",
48
48
  "@langchain/langgraph-checkpoint-postgres": "^1.0.4",
49
49
  "commander": "~13.1.0",
50
- "@skein-js/core": "0.9.0",
51
- "@skein-js/config": "0.9.0",
52
- "@skein-js/express": "0.9.0",
53
- "@skein-js/runtime": "0.9.0"
50
+ "@skein-js/core": "0.9.1",
51
+ "@skein-js/express": "0.9.1",
52
+ "@skein-js/runtime": "0.9.1",
53
+ "@skein-js/server-kit": "0.9.1",
54
+ "@skein-js/config": "0.9.1"
54
55
  },
55
56
  "optionalDependencies": {
56
57
  "vite": "^8.1.0"