skein-js 0.9.1 → 0.10.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 +26 -6
- package/dist/index.js +95 -39
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ one-word change (`langgraph dev` → `skein dev`).
|
|
|
17
17
|
- [Commands](#commands)
|
|
18
18
|
- [`skein dev` flags](#skein-dev-flags)
|
|
19
19
|
- [Self-hosted, no lock-in](#self-hosted-no-lock-in)
|
|
20
|
+
- [Deploy anywhere](#deploy-anywhere)
|
|
20
21
|
- [When the managed platform may fit you better](#when-the-managed-platform-may-fit-you-better)
|
|
21
22
|
- [Learn more](#learn-more)
|
|
22
23
|
- [License](#license)
|
|
@@ -52,12 +53,13 @@ LangGraph Studio — any Agent Protocol client works with only a URL change. See
|
|
|
52
53
|
|
|
53
54
|
## Commands
|
|
54
55
|
|
|
55
|
-
| Command | What it does
|
|
56
|
-
| ------------------ |
|
|
57
|
-
| `skein dev` | In-process dev server, hot reload, `.skein/` state, no Docker.
|
|
58
|
-
| `skein up` | Self-hosted stack via Docker Compose (app + Postgres + Redis).
|
|
59
|
-
| `skein build` | Build a deployable Docker image from the config.
|
|
60
|
-
| `skein dockerfile` | Emit a standalone Dockerfile (stdout by default).
|
|
56
|
+
| Command | What it does | LangGraph CLI equivalent | Key flags |
|
|
57
|
+
| ------------------ | ------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------ |
|
|
58
|
+
| `skein dev` | In-process dev server, hot reload, `.skein/` state, no Docker. | `langgraph dev` | see [`skein dev` flags](#skein-dev-flags) |
|
|
59
|
+
| `skein up` | Self-hosted stack via Docker Compose (app + Postgres + Redis). | `langgraph up` | `-p, --port` (8123) · `--host` (0.0.0.0) · `-n, --npmrc <path>` |
|
|
60
|
+
| `skein build` | Build a deployable Docker image from the config. | `langgraph build` | `-t, --tag` (defaults to the project dir name) · `-n, --npmrc <path>` |
|
|
61
|
+
| `skein dockerfile` | Emit a standalone Dockerfile (stdout by default). | `langgraph dockerfile` | `-o, --output <path>` |
|
|
62
|
+
| `skein start` | Serve a pre-built `.skein/build` artifact (the image's entrypoint). | — | `-p, --port` (8123) · `--host` · `--store` · `--queue` · `--concurrency` |
|
|
61
63
|
|
|
62
64
|
All commands take `-c, --config <path>` (default `langgraph.json`).
|
|
63
65
|
|
|
@@ -96,6 +98,23 @@ run your LangGraph.js graphs behind the standard Agent Protocol on **your own in
|
|
|
96
98
|
license key, no per-deployment fee, and no vendor lock-in. `skein up` brings up a Docker Compose
|
|
97
99
|
stack (app + your Postgres + your Redis) that you own end to end.
|
|
98
100
|
|
|
101
|
+
## Deploy anywhere
|
|
102
|
+
|
|
103
|
+
`skein build` produces an ordinary Docker image, so your LangGraph.js graphs run **anywhere you can
|
|
104
|
+
run a container** — Google Cloud Run, Railway, Fly.io, Render, AWS App Runner or ECS Fargate,
|
|
105
|
+
Kubernetes, or your own VPS.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
skein build -t my-agent # → a deployable Docker image
|
|
109
|
+
docker run -p 8123:8123 \
|
|
110
|
+
-e POSTGRES_URI="postgresql://…" \
|
|
111
|
+
-e REDIS_URI="redis://…" my-agent
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The image binds `$PORT` when a platform injects one (8123 when nothing does), runs as a non-root
|
|
115
|
+
user, serves a `/ok` health probe, and drains in-flight runs on `SIGTERM`. Step-by-step guides per
|
|
116
|
+
platform, and the knobs that are the same everywhere: [deploy anywhere](../../docs/deploy.md).
|
|
117
|
+
|
|
99
118
|
## When the managed platform may fit you better
|
|
100
119
|
|
|
101
120
|
skein-js gives you the code and full ownership, not a support contract. If you're an established
|
|
@@ -107,6 +126,7 @@ on top of the open LangGraph runtime.
|
|
|
107
126
|
|
|
108
127
|
## Learn more
|
|
109
128
|
|
|
129
|
+
- [Deploy anywhere](../../docs/deploy.md) — Cloud Run, Railway, Fly.io, Render, AWS, Kubernetes, VPS
|
|
110
130
|
- [LangGraph CLI compatibility](../../docs/langgraph-cli-compat.md) — commands + `langgraph.json` fields
|
|
111
131
|
- [skein-js overview](../../docs/index.md) · [Reuse-first architecture](../../docs/reuse.md) · [Roadmap](../../docs/roadmap.md)
|
|
112
132
|
- [skein-js root README](../../README.md)
|
package/dist/index.js
CHANGED
|
@@ -14,7 +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
|
+
import { resolveRunConcurrency, resolveShutdownGraceMs } from "@skein-js/server-kit";
|
|
18
18
|
|
|
19
19
|
// src/colors.ts
|
|
20
20
|
var colorEnabled = process.stdout.isTTY === true && process.env.NO_COLOR === void 0;
|
|
@@ -139,6 +139,8 @@ async function applyProjectEnv(config, configDir) {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
// src/serve-env.ts
|
|
142
|
+
var DEFAULT_DEV_PORT = 2024;
|
|
143
|
+
var DEFAULT_CONTAINER_PORT = 8123;
|
|
142
144
|
function envPort(fallback) {
|
|
143
145
|
const raw = process.env.PORT;
|
|
144
146
|
if (raw === void 0 || raw.trim() === "") return fallback;
|
|
@@ -157,6 +159,32 @@ function describeBindError(error, port) {
|
|
|
157
159
|
return `failed to start server: ${error instanceof Error ? error.message : String(error)}`;
|
|
158
160
|
}
|
|
159
161
|
|
|
162
|
+
// src/shutdown.ts
|
|
163
|
+
import { DEFAULT_SHUTDOWN_GRACE_MS } from "@skein-js/server-kit";
|
|
164
|
+
var FORCE_EXIT_BUFFER_MS = 3e3;
|
|
165
|
+
function forceExitDelayMs(graceMs = DEFAULT_SHUTDOWN_GRACE_MS) {
|
|
166
|
+
return graceMs + FORCE_EXIT_BUFFER_MS;
|
|
167
|
+
}
|
|
168
|
+
var describe = (error) => error instanceof Error ? error.message : String(error);
|
|
169
|
+
function createShutdownHandler(options) {
|
|
170
|
+
const { forceExitMs, close, onShutdownStart, exit = (code) => process.exit(code) } = options;
|
|
171
|
+
let shuttingDown = false;
|
|
172
|
+
return () => {
|
|
173
|
+
if (shuttingDown) return;
|
|
174
|
+
shuttingDown = true;
|
|
175
|
+
try {
|
|
176
|
+
onShutdownStart?.();
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error(`skein: pre-shutdown step failed: ${describe(error)}`);
|
|
179
|
+
}
|
|
180
|
+
const forceExit = setTimeout(() => exit(0), forceExitMs);
|
|
181
|
+
forceExit.unref();
|
|
182
|
+
void close().catch((error) => {
|
|
183
|
+
console.error(`skein: shutdown did not complete cleanly: ${describe(error)}`);
|
|
184
|
+
}).finally(() => exit(0));
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
160
188
|
// src/vite-graph-loader.ts
|
|
161
189
|
import { createServer as createNetServer } from "net";
|
|
162
190
|
function findFreePort() {
|
|
@@ -211,12 +239,12 @@ async function createViteGraphLoader(root, ignored = []) {
|
|
|
211
239
|
// src/dev-command.ts
|
|
212
240
|
var RELOAD_DEBOUNCE_MS = 120;
|
|
213
241
|
var AUTOSAVE_MS = 2e3;
|
|
214
|
-
var FORCE_EXIT_MS = 5e3;
|
|
215
242
|
var devLogger = createDevLogger();
|
|
216
243
|
async function runDev(options) {
|
|
217
244
|
const configPath = path3.resolve(process.cwd(), options.config);
|
|
218
245
|
const { config, configDir } = await loadConfig({ configPath });
|
|
219
246
|
await applyProjectEnv(config, configDir);
|
|
247
|
+
const shutdownGraceMs = resolveShutdownGraceMs();
|
|
220
248
|
const stateDir = path3.join(configDir, STATE_DIR);
|
|
221
249
|
const stateFile = devStateFile(configDir);
|
|
222
250
|
const loader = await createViteGraphLoader(configDir, [`${STATE_DIR}/**`, `**/${STATE_DIR}/**`]);
|
|
@@ -268,7 +296,7 @@ async function runDev(options) {
|
|
|
268
296
|
cors: runtime.cors,
|
|
269
297
|
warm: true,
|
|
270
298
|
logger: devLogger,
|
|
271
|
-
worker: { maxConcurrency: runConcurrency }
|
|
299
|
+
worker: { maxConcurrency: runConcurrency, shutdownGraceMs }
|
|
272
300
|
});
|
|
273
301
|
await server.listen(port, host);
|
|
274
302
|
} catch (error) {
|
|
@@ -346,18 +374,25 @@ async function runDev(options) {
|
|
|
346
374
|
pending = setTimeout(() => void reload(), RELOAD_DEBOUNCE_MS);
|
|
347
375
|
});
|
|
348
376
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
377
|
+
const shutdown = createShutdownHandler({
|
|
378
|
+
forceExitMs: forceExitDelayMs(shutdownGraceMs),
|
|
379
|
+
// Stop autosaving and flush one last snapshot synchronously, before anything can race it.
|
|
380
|
+
onShutdownStart: () => {
|
|
381
|
+
if (autosave) clearInterval(autosave);
|
|
382
|
+
saveState();
|
|
383
|
+
},
|
|
384
|
+
// Strictly ordered, never concurrent. `server.close()` stops the worker, which needs the store
|
|
385
|
+
// and queue still alive to settle in-flight runs terminally — and needs the vite loader alive
|
|
386
|
+
// too, since a draining graph may still `await import(...)` a module it hasn't loaded yet.
|
|
387
|
+
// Tearing either down alongside the drain fails the runs it was meant to save.
|
|
388
|
+
close: async () => {
|
|
389
|
+
try {
|
|
390
|
+
await server.close();
|
|
391
|
+
} finally {
|
|
392
|
+
await Promise.allSettled([loader.close(), runtime.dispose()]);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
361
396
|
process.on("SIGINT", shutdown);
|
|
362
397
|
process.on("SIGTERM", shutdown);
|
|
363
398
|
}
|
|
@@ -592,8 +627,9 @@ services:
|
|
|
592
627
|
ports:
|
|
593
628
|
- ${ports}
|
|
594
629
|
environment:
|
|
595
|
-
# The container CMD passes no --port; it binds $PORT (as a hosting platform would inject)
|
|
596
|
-
#
|
|
630
|
+
# The container CMD passes no --port; it binds $PORT (as a hosting platform would inject), and
|
|
631
|
+
# falls back to this same port anyway. Set explicitly so the mapping above stays correct even
|
|
632
|
+
# if a host port is published that differs from the port the container listens on.
|
|
597
633
|
PORT: "${options.containerPort}"
|
|
598
634
|
POSTGRES_URI: postgresql://postgres:postgres@postgres:5432/skein
|
|
599
635
|
REDIS_URI: redis://redis:6379
|
|
@@ -603,6 +639,11 @@ services:
|
|
|
603
639
|
redis:
|
|
604
640
|
condition: service_healthy
|
|
605
641
|
restart: unless-stopped
|
|
642
|
+
# Longer than Docker's 10s default so the app can finish its shutdown: it drains in-flight runs
|
|
643
|
+
# for SKEIN_SHUTDOWN_GRACE_MS, then aborts the stragglers so they settle to a terminal status.
|
|
644
|
+
# 10s leaves no headroom the moment that window is raised, and a SIGKILL mid-abort is exactly
|
|
645
|
+
# what leaves a run stuck in a non-terminal state.
|
|
646
|
+
stop_grace_period: 30s
|
|
606
647
|
|
|
607
648
|
postgres:
|
|
608
649
|
image: pgvector/pgvector:pg16
|
|
@@ -688,17 +729,28 @@ function generateDockerfile(options) {
|
|
|
688
729
|
// The bundle ships sourcemaps; enable them so stack traces map back to the original TypeScript.
|
|
689
730
|
`ENV NODE_OPTIONS=--enable-source-maps`,
|
|
690
731
|
`EXPOSE ${port}`,
|
|
691
|
-
// Liveness probe against skein's `/ok` endpoint, targeting the same port the server binds.
|
|
732
|
+
// Liveness probe against skein's `/ok` endpoint, targeting the same port the server binds. PORT
|
|
733
|
+
// is resolved exactly as `envPort` resolves it — integer, in range, blank counts as unset —
|
|
734
|
+
// rather than by truthiness, so a malformed value (`PORT=8080a`, `PORT=0`) has the probe and the
|
|
735
|
+
// server agree on the fallback instead of probing a URL the server never bound.
|
|
692
736
|
`HEALTHCHECK --interval=30s --timeout=3s --start-period=20s --retries=3 \\`,
|
|
693
|
-
` CMD node -e "fetch('http://127.0.0.1:'+
|
|
737
|
+
` CMD node -e "const r=Number(process.env.PORT);const p=Number.isInteger(r)&&r>=0&&r<=65535?r:${port};fetch('http://127.0.0.1:'+p+'/ok').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"`,
|
|
694
738
|
// Run unprivileged. The bundle writes nothing to disk, and /app is world-readable, so no chown.
|
|
695
739
|
`USER node`,
|
|
696
740
|
...dockerfileLines,
|
|
697
741
|
``,
|
|
698
742
|
`# Serve the compiled artifact against Postgres + Redis (POSTGRES_URI / REDIS_URI from the env).`,
|
|
699
|
-
`# No --port: the server binds $PORT when the platform injects one (Railway/Fly/Render)
|
|
700
|
-
`#
|
|
701
|
-
|
|
743
|
+
`# No --port: the server binds $PORT when the platform injects one (Railway/Fly/Render/Cloud Run),`,
|
|
744
|
+
`# else \`skein start\`'s default \u2014 the port EXPOSEd above, so a bare \`docker run -p ${port}:${port}\``,
|
|
745
|
+
`# works too.`,
|
|
746
|
+
`#`,
|
|
747
|
+
`# Invoked as \`node <entry>\` rather than \`npx skein\` so that **node itself is PID 1**. Under npx,`,
|
|
748
|
+
`# PID 1 is npm, which forwards SIGTERM to a \`sh -c\` child and exits immediately \u2014 the server is`,
|
|
749
|
+
`# killed mid-shutdown and in-flight runs are left stranded in a non-terminal status. Exec form`,
|
|
750
|
+
`# (no shell) keeps the signal path direct, so SIGTERM reaches skein's graceful-shutdown handler.`,
|
|
751
|
+
// Absolute, so a `dockerfile_lines` entry that changes WORKDIR (spliced in just above) can't
|
|
752
|
+
// leave the CMD resolving against the wrong directory.
|
|
753
|
+
`CMD ["node", "/app/node_modules/skein-js/dist/index.js", "start", "--store", "postgres", "--queue", "redis", "--host", "0.0.0.0"]`
|
|
702
754
|
];
|
|
703
755
|
return `${lines.join("\n")}
|
|
704
756
|
`;
|
|
@@ -709,7 +761,7 @@ function skeinCliVersion() {
|
|
|
709
761
|
return createRequire2(import.meta.url)("../package.json").version;
|
|
710
762
|
}
|
|
711
763
|
var ARTIFACT_SUBDIR = path5.join(".skein", "build");
|
|
712
|
-
var CONTAINER_PORT =
|
|
764
|
+
var CONTAINER_PORT = DEFAULT_CONTAINER_PORT;
|
|
713
765
|
var DOCKERFILE_NAME = "Dockerfile";
|
|
714
766
|
var COMPOSE_NAME = "compose.yaml";
|
|
715
767
|
var DOCKERIGNORE_NAME = ".dockerignore";
|
|
@@ -930,8 +982,7 @@ import { createExpressServer as createExpressServer2 } from "@skein-js/express";
|
|
|
930
982
|
import {
|
|
931
983
|
buildRuntime as buildRuntime3
|
|
932
984
|
} from "@skein-js/runtime";
|
|
933
|
-
import { resolveRunConcurrency as resolveRunConcurrency2 } from "@skein-js/server-kit";
|
|
934
|
-
var FORCE_EXIT_MS2 = 5e3;
|
|
985
|
+
import { resolveRunConcurrency as resolveRunConcurrency2, resolveShutdownGraceMs as resolveShutdownGraceMs2 } from "@skein-js/server-kit";
|
|
935
986
|
var logger = createDevLogger();
|
|
936
987
|
function readBakedSchemas(configDir) {
|
|
937
988
|
const schemasFile = path7.join(configDir, "schemas.json");
|
|
@@ -944,16 +995,21 @@ function readBakedSchemas(configDir) {
|
|
|
944
995
|
}
|
|
945
996
|
async function runStart(options) {
|
|
946
997
|
const configPath = path7.resolve(process.cwd(), options.config);
|
|
998
|
+
let handleSignal = () => process.exit(0);
|
|
999
|
+
process.on("SIGINT", () => handleSignal());
|
|
1000
|
+
process.on("SIGTERM", () => handleSignal());
|
|
947
1001
|
let schemas;
|
|
948
1002
|
let configDir;
|
|
949
1003
|
let authPath;
|
|
950
1004
|
let runConcurrency;
|
|
1005
|
+
let shutdownGraceMs;
|
|
951
1006
|
try {
|
|
952
1007
|
const loaded = await loadConfig5({ configPath });
|
|
953
1008
|
configDir = loaded.configDir;
|
|
954
1009
|
authPath = loaded.config.auth?.path;
|
|
955
1010
|
await applyProjectEnv(loaded.config, configDir);
|
|
956
1011
|
runConcurrency = resolveRunConcurrency2(options.concurrency ?? options.nJobsPerWorker);
|
|
1012
|
+
shutdownGraceMs = resolveShutdownGraceMs2();
|
|
957
1013
|
schemas = readBakedSchemas(configDir);
|
|
958
1014
|
} catch (error) {
|
|
959
1015
|
console.error(`skein: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -983,7 +1039,7 @@ async function runStart(options) {
|
|
|
983
1039
|
cors: runtime.cors,
|
|
984
1040
|
warm: true,
|
|
985
1041
|
logger,
|
|
986
|
-
worker: { maxConcurrency: runConcurrency }
|
|
1042
|
+
worker: { maxConcurrency: runConcurrency, shutdownGraceMs }
|
|
987
1043
|
});
|
|
988
1044
|
await server.listen(port, host);
|
|
989
1045
|
} catch (error) {
|
|
@@ -993,16 +1049,16 @@ async function runStart(options) {
|
|
|
993
1049
|
return;
|
|
994
1050
|
}
|
|
995
1051
|
printBanner({ host, port, graphIds: runtime.deps.graphs.ids, authPath, runConcurrency }, logger);
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1052
|
+
handleSignal = createShutdownHandler({
|
|
1053
|
+
forceExitMs: forceExitDelayMs(shutdownGraceMs),
|
|
1054
|
+
close: async () => {
|
|
1055
|
+
try {
|
|
1056
|
+
await server.close();
|
|
1057
|
+
} finally {
|
|
1058
|
+
await runtime.dispose();
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1006
1062
|
}
|
|
1007
1063
|
|
|
1008
1064
|
// src/index.ts
|
|
@@ -1035,7 +1091,7 @@ var parseQueue = parseChoice(["memory", "redis"]);
|
|
|
1035
1091
|
var program = new Command().name("skein").description(
|
|
1036
1092
|
"Agent Protocol server for LangGraph.js \u2014 a drop-in replacement for the LangGraph CLI."
|
|
1037
1093
|
).version(version, "-v, --version");
|
|
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,
|
|
1094
|
+
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, DEFAULT_DEV_PORT).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
1095
|
"--concurrency <count>",
|
|
1040
1096
|
"Queued runs the background worker executes at once (default 10; env SKEIN_RUN_CONCURRENCY)",
|
|
1041
1097
|
parseConcurrency
|
|
@@ -1050,7 +1106,7 @@ program.command("dev").description("Run the in-process dev server with hot reloa
|
|
|
1050
1106
|
hostExplicit: command.getOptionValueSource("host") === "cli"
|
|
1051
1107
|
})
|
|
1052
1108
|
);
|
|
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,
|
|
1109
|
+
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, DEFAULT_CONTAINER_PORT).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
1110
|
"--concurrency <count>",
|
|
1055
1111
|
"Queued runs the background worker executes at once (default 10; env SKEIN_RUN_CONCURRENCY)",
|
|
1056
1112
|
parseConcurrency
|
|
@@ -1065,7 +1121,7 @@ program.command("start").description("Serve a pre-built .skein/build artifact (t
|
|
|
1065
1121
|
hostExplicit: command.getOptionValueSource("host") === "cli"
|
|
1066
1122
|
})
|
|
1067
1123
|
);
|
|
1068
|
-
program.command("up").description("Bring up the production stack (Docker Compose: app + Postgres + Redis).").option("-c, --config <path>", "Path to langgraph.json", "langgraph.json").option("-p, --port <port>", "Port to expose", parsePort,
|
|
1124
|
+
program.command("up").description("Bring up the production stack (Docker Compose: app + Postgres + Redis).").option("-c, --config <path>", "Path to langgraph.json", "langgraph.json").option("-p, --port <port>", "Port to expose", parsePort, DEFAULT_CONTAINER_PORT).option("--host <host>", "Host to bind", "0.0.0.0").option(
|
|
1069
1125
|
"-n, --npmrc <path>",
|
|
1070
1126
|
"Path to an .npmrc for authenticating private-registry installs (wired in as a build secret)"
|
|
1071
1127
|
).action((options) => runUp(options));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skein-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
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>",
|
|
@@ -16,10 +16,16 @@
|
|
|
16
16
|
"keywords": [
|
|
17
17
|
"typescript",
|
|
18
18
|
"langgraph",
|
|
19
|
+
"langgraph-js",
|
|
19
20
|
"cli",
|
|
20
21
|
"agent-protocol",
|
|
21
22
|
"langgraph-cli",
|
|
22
|
-
"self-hosted"
|
|
23
|
+
"self-hosted",
|
|
24
|
+
"ai-agents",
|
|
25
|
+
"deploy",
|
|
26
|
+
"docker",
|
|
27
|
+
"cloud-run",
|
|
28
|
+
"kubernetes"
|
|
23
29
|
],
|
|
24
30
|
"type": "module",
|
|
25
31
|
"main": "./dist/index.js",
|
|
@@ -47,11 +53,11 @@
|
|
|
47
53
|
"@commander-js/extra-typings": "~13.1.0",
|
|
48
54
|
"@langchain/langgraph-checkpoint-postgres": "^1.0.4",
|
|
49
55
|
"commander": "~13.1.0",
|
|
50
|
-
"@skein-js/core": "0.
|
|
51
|
-
"@skein-js/
|
|
52
|
-
"@skein-js/
|
|
53
|
-
"@skein-js/server-kit": "0.
|
|
54
|
-
"@skein-js/
|
|
56
|
+
"@skein-js/core": "0.10.0",
|
|
57
|
+
"@skein-js/config": "0.10.0",
|
|
58
|
+
"@skein-js/express": "0.10.0",
|
|
59
|
+
"@skein-js/server-kit": "0.10.0",
|
|
60
|
+
"@skein-js/runtime": "0.10.0"
|
|
55
61
|
},
|
|
56
62
|
"optionalDependencies": {
|
|
57
63
|
"vite": "^8.1.0"
|