@skein-js/server-kit 0.6.3 → 0.7.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
@@ -19,6 +19,10 @@ handler table.
19
19
  - **In-memory dev runtime** — `loadInMemoryRuntime` / `loadReloadableInMemoryRuntime`: assemble a
20
20
  `ProtocolDeps` backed by in-process drivers from a `langgraph.json`. This is what powers `skein dev`
21
21
  and every adapter's `{ config }` convenience path (hot-reload + snapshot/restore included).
22
+ - **In-code embedding** — `embedInMemoryGraphs` / `graphMapToResolver`: build a `ProtocolDeps` around a
23
+ compiled graph (or map of them) you already hold — **no `langgraph.json`, no CLI** — then pass
24
+ `{ deps }` to any adapter. `overrides` swaps in production drivers/auth. See
25
+ [docs/embedding.md](../../docs/embedding.md).
22
26
  - **LangGraph dev-state import** — `readLanggraphDevState` / `loadSnapshotIntoStore` /
23
27
  `describeSnapshot`: read an existing `.langgraph_api/` directory and reconstruct skein's own
24
28
  `DevStateSnapshot`, so adopting skein carries all local state over losslessly.
@@ -33,6 +37,55 @@ handler table.
33
37
  > [`@skein-js/agent-protocol`](../agent-protocol), since it references the handler names. Adapters
34
38
  > import it from there.
35
39
 
40
+ ## Install
41
+
42
+ ```bash
43
+ pnpm add @skein-js/server-kit @langchain/langgraph
44
+ ```
45
+
46
+ `@langchain/langgraph` is a peer dependency. You install this package directly when you **embed a
47
+ graph in code** (`embedInMemoryGraphs`) or **write your own adapter**; the shipped adapters depend on
48
+ it for you.
49
+
50
+ ## Usage
51
+
52
+ The most common direct use is the in-code on-ramp — turn a compiled graph (or a map of them) into a
53
+ `ProtocolDeps` and hand `{ deps }` to any adapter, with **no `langgraph.json` and no CLI**:
54
+
55
+ ```ts
56
+ import { createExpressServer } from "@skein-js/express";
57
+ import { embedInMemoryGraphs } from "@skein-js/server-kit";
58
+ import { graph } from "./my-graph.js";
59
+
60
+ const server = await createExpressServer({ deps: embedInMemoryGraphs({ agent: graph }) });
61
+ await server.listen(2024);
62
+ ```
63
+
64
+ Pass `overrides` to swap in production drivers or an auth engine while keeping the rest in-memory. See
65
+ [docs/embedding.md](../../docs/embedding.md).
66
+
67
+ ## API
68
+
69
+ - **`embedInMemoryGraphs(graphs, options?): ProtocolDeps`** — build a `ProtocolDeps` (store, queue,
70
+ bus, checkpointer) around a compiled graph or `Record<string, EmbeddableGraph>`. `options.overrides`
71
+ replaces any dep (e.g. a Postgres store, an `auth` engine). `createInMemoryDeps` is a
72
+ **`@deprecated`** alias. `graphMapToResolver` / `normalizeEmbeddableGraphs` are the lower-level
73
+ graph→`GraphResolver` helpers.
74
+ - **`resolveProtocolRuntime(options): Promise<ResolvedProtocolRuntime>`** — turn a
75
+ `{ config } | { deps }` bag (`SkeinRuntimeOptions`) into a live runtime (assistants seeded, worker
76
+ started) — the step every adapter runs before mounting routes.
77
+ - **`loadInMemoryRuntime` / `loadReloadableInMemoryRuntime`** — assemble a `ProtocolDeps` from a
78
+ `langgraph.json` using in-process drivers. The reloadable variant adds `reloadGraphs` /
79
+ `snapshotState` / `hydrateState` (what powers `skein dev`'s hot reload + cross-restart persistence).
80
+ - **`readLanggraphDevState` / `loadSnapshotIntoStore` / `describeSnapshot`** — read an existing
81
+ `.langgraph_api/` directory and reconstruct a `DevStateSnapshot`, so adopting skein carries local
82
+ state over losslessly.
83
+ - **CORS** — `corsFromHttpConfig` / `toCorsOptions` map a `langgraph.json` `http.cors` block to
84
+ `cors`-style options; `allowedOrigin` / `corsResponseHeaders` / `applyNodeCors` / `sendNodePreflight`
85
+ derive CORS headers for adapters without a CORS middleware of their own.
86
+ - **Node transport** — `sendNodeResponse` / `sendNodeError` serialize a `ProtocolResponse`
87
+ (JSON / 204 / SSE) onto a Node `ServerResponse`, shared by the NestJS + Next.js Pages Router adapters.
88
+
36
89
  ## Learn more
37
90
 
38
91
  - [Building your own adapter](../../docs/building-an-adapter.md)
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { ProtocolRuntime, Logger, ProtocolDeps, ProtocolResponse } from '@skein-js/agent-protocol';
1
+ import { ProtocolRuntime, Logger, ProtocolDeps, GraphResolver, ProtocolResponse } from '@skein-js/agent-protocol';
2
+ export { CompiledGraphFactory, GraphResolver, ProtocolDeps, ResolvedGraph } from '@skein-js/agent-protocol';
2
3
  import { ModuleImporter, GraphSchemas } from '@skein-js/config';
3
4
  import { CorsOptions } from 'cors';
4
5
  export { CorsOptions } from 'cors';
5
6
  import { MemoryStoreSnapshot } from '@skein-js/storage-memory';
6
- import { BaseCheckpointSaver } from '@langchain/langgraph';
7
+ import { CompiledGraph, BaseCheckpointSaver } from '@langchain/langgraph';
7
8
  import { SkeinStore } from '@skein-js/core';
8
9
  import { ServerResponse } from 'node:http';
9
10
 
@@ -97,6 +98,53 @@ interface ReloadableInMemoryRuntime extends InMemoryRuntimeConfig {
97
98
  */
98
99
  declare function loadReloadableInMemoryRuntime(configPath: string, importModule?: ModuleImporter, staticSchemas?: Record<string, GraphSchemas>): Promise<ReloadableInMemoryRuntime>;
99
100
 
101
+ type AnyCompiledGraph = CompiledGraph<any>;
102
+ /**
103
+ * A graph you can embed in code: any compiled LangGraph.js graph, or a factory that builds one per run
104
+ * (called with the run's `configurable`). Keys of a graph map become graph ids.
105
+ */
106
+ type EmbeddableGraph = AnyCompiledGraph | ((config: {
107
+ configurable?: Record<string, unknown>;
108
+ }) => AnyCompiledGraph | Promise<AnyCompiledGraph>);
109
+ /**
110
+ * Accept either a ready {@link GraphResolver} or a plain graph map and return a `GraphResolver` either
111
+ * way — the normalization every in-code embedding helper shares (`embedInMemoryGraphs` here,
112
+ * `embedPostgresGraphs` in `@skein-js/runtime`), so the {@link isGraphResolver} discriminator lives in
113
+ * exactly one place.
114
+ */
115
+ declare function normalizeEmbeddableGraphs(graphs: GraphResolver | Record<string, EmbeddableGraph>): GraphResolver;
116
+ /**
117
+ * Turn a map of compiled graphs (or per-config factories) into a {@link GraphResolver}. Keys become the
118
+ * graph ids — one auto-registered assistant each. `schemas()` returns a minimal `{ graph_id }` stub:
119
+ * enough for the assistants introspection endpoints and everything `useStream` / Agent Chat UI render.
120
+ * Real input/output/state schema extraction stays a `langgraph.json`/config feature — it needs static
121
+ * TypeScript analysis of the graph source, which a compiled graph object no longer carries.
122
+ */
123
+ declare function graphMapToResolver(graphs: Record<string, EmbeddableGraph>): GraphResolver;
124
+ /**
125
+ * Build a `ProtocolDeps` backed by fresh in-process drivers (store, queue, bus, checkpointer) around
126
+ * graphs you already hold in code — no `langgraph.json`, no CLI. Pass a map of compiled graphs (or
127
+ * factories), or a ready {@link GraphResolver}. Hand the result to any adapter's `{ deps }` seam:
128
+ *
129
+ * ```ts
130
+ * import { embedInMemoryGraphs } from "@skein-js/server-kit";
131
+ * import { createExpressServer } from "@skein-js/express";
132
+ *
133
+ * createExpressServer({ deps: embedInMemoryGraphs({ myAgent: graph }) }).listen(2024);
134
+ * ```
135
+ *
136
+ * `overrides` replaces any driver or adds `auth`/`logger` — e.g. swap in a Postgres store + Redis
137
+ * queue for a durable, horizontally-scalable deployment. `graphs` is intentionally excluded from
138
+ * `overrides` (the first argument is the single source of graphs), so a stray `graphs` key can't
139
+ * silently void it.
140
+ */
141
+ declare function embedInMemoryGraphs(graphs: GraphResolver | Record<string, EmbeddableGraph>, overrides?: Omit<Partial<ProtocolDeps>, "graphs">): ProtocolDeps;
142
+ /**
143
+ * @deprecated Renamed to {@link embedInMemoryGraphs} — the function takes graphs and returns a
144
+ * `ProtocolDeps`, not a graph. Kept for back-compat; slated for removal in a future major.
145
+ */
146
+ declare const createInMemoryDeps: typeof embedInMemoryGraphs;
147
+
100
148
  /**
101
149
  * Read a LangGraph `.langgraph_api/` directory and reconstruct skein's `DevStateSnapshot`.
102
150
  * Returns `null` when the directory holds none of the expected files (nothing to import).
@@ -166,4 +214,4 @@ declare function sendNodeResponse(response: ProtocolResponse, res: ServerRespons
166
214
  /** Serialize a caught error onto the Node `res`, using the protocol status when the error carries one. */
167
215
  declare function sendNodeError(error: unknown, res: ServerResponse, logger?: Logger, adapterName?: string): void;
168
216
 
169
- export { type CorsSetting, type DevStateCounts, type DevStateSnapshot, type InMemoryRuntimeConfig, type LanggraphCorsConfig, type ReloadableInMemoryRuntime, type ResolvedProtocolRuntime, type SkeinRuntimeCommonOptions, type SkeinRuntimeOptions, allowedOrigin, applyNodeCors, corsFromHttpConfig, corsPreflightHeaders, corsResponseHeaders, describeSnapshot, joinList, loadInMemoryRuntime, loadReloadableInMemoryRuntime, loadSnapshotIntoStore, readLanggraphDevState, resolveProtocolRuntime, sendNodeError, sendNodePreflight, sendNodeResponse, toCorsOptions };
217
+ export { type CorsSetting, type DevStateCounts, type DevStateSnapshot, type EmbeddableGraph, type InMemoryRuntimeConfig, type LanggraphCorsConfig, type ReloadableInMemoryRuntime, type ResolvedProtocolRuntime, type SkeinRuntimeCommonOptions, type SkeinRuntimeOptions, allowedOrigin, applyNodeCors, corsFromHttpConfig, corsPreflightHeaders, corsResponseHeaders, createInMemoryDeps, describeSnapshot, embedInMemoryGraphs, graphMapToResolver, joinList, loadInMemoryRuntime, loadReloadableInMemoryRuntime, loadSnapshotIntoStore, normalizeEmbeddableGraphs, readLanggraphDevState, resolveProtocolRuntime, sendNodeError, sendNodePreflight, sendNodeResponse, toCorsOptions };
package/dist/index.js CHANGED
@@ -4,12 +4,12 @@ import {
4
4
  } from "@skein-js/agent-protocol";
5
5
 
6
6
  // src/in-memory-runtime.ts
7
- import { MemorySaver } from "@langchain/langgraph";
7
+ import { MemorySaver as MemorySaver2 } from "@langchain/langgraph";
8
8
  import {
9
9
  loadAuthEngine,
10
10
  loadConfig
11
11
  } from "@skein-js/config";
12
- import { MemoryRunEventBus, MemoryRunQueue, MemorySkeinStore } from "@skein-js/storage-memory";
12
+ import { MemoryRunEventBus as MemoryRunEventBus2, MemoryRunQueue as MemoryRunQueue2, MemorySkeinStore as MemorySkeinStore2 } from "@skein-js/storage-memory";
13
13
 
14
14
  // src/cors-config.ts
15
15
  var ALWAYS_EXPOSED_HEADERS = ["content-location", "x-pagination-total"];
@@ -93,21 +93,51 @@ function hydrateCheckpointer(saver, snapshot) {
93
93
  );
94
94
  }
95
95
 
96
- // src/in-memory-runtime.ts
97
- function toGraphResolver(graphs) {
96
+ // src/in-memory-deps.ts
97
+ import { MemorySaver } from "@langchain/langgraph";
98
+ import { MemoryRunEventBus, MemoryRunQueue, MemorySkeinStore } from "@skein-js/storage-memory";
99
+ function isGraphResolver(graphs) {
100
+ const candidate = graphs;
101
+ return Array.isArray(candidate.ids) && typeof candidate.load === "function";
102
+ }
103
+ function normalizeEmbeddableGraphs(graphs) {
104
+ return isGraphResolver(graphs) ? graphs : graphMapToResolver(graphs);
105
+ }
106
+ function graphMapToResolver(graphs) {
107
+ const ids = Object.keys(graphs);
98
108
  return {
99
- ids: graphs.ids,
100
- load: (graphId) => graphs.load(graphId),
101
- schemas: async (graphId) => await graphs.schemas(graphId)
109
+ ids,
110
+ load: async (graphId) => {
111
+ const graph = graphs[graphId];
112
+ if (graph == null) {
113
+ const known = ids.join(", ") || "none";
114
+ throw new Error(
115
+ ids.includes(graphId) ? `Graph "${graphId}" resolved to ${String(graph)} \u2014 check its export/factory (known: ${known}).` : `Unknown graph "${graphId}" (known: ${known}).`
116
+ );
117
+ }
118
+ return graph;
119
+ },
120
+ schemas: async (graphId) => ({ [graphId]: { graph_id: graphId } })
102
121
  };
103
122
  }
104
- function buildInMemoryDeps(graphs) {
123
+ function embedInMemoryGraphs(graphs, overrides = {}) {
105
124
  return {
106
125
  store: new MemorySkeinStore(),
107
- graphs,
126
+ graphs: normalizeEmbeddableGraphs(graphs),
108
127
  queue: new MemoryRunQueue(),
109
128
  bus: new MemoryRunEventBus(),
110
- checkpointer: new MemorySaver()
129
+ checkpointer: new MemorySaver(),
130
+ ...overrides
131
+ };
132
+ }
133
+ var createInMemoryDeps = embedInMemoryGraphs;
134
+
135
+ // src/in-memory-runtime.ts
136
+ function toGraphResolver(graphs) {
137
+ return {
138
+ ids: graphs.ids,
139
+ load: (graphId) => graphs.load(graphId),
140
+ schemas: async (graphId) => await graphs.schemas(graphId)
111
141
  };
112
142
  }
113
143
  async function loadInMemoryRuntime(configPath, importModule, staticSchemas) {
@@ -116,7 +146,7 @@ async function loadInMemoryRuntime(configPath, importModule, staticSchemas) {
116
146
  importModule,
117
147
  staticSchemas
118
148
  });
119
- const deps = buildInMemoryDeps(toGraphResolver(graphs));
149
+ const deps = embedInMemoryGraphs(toGraphResolver(graphs));
120
150
  deps.auth = await loadAuthEngine(config.auth, { configDir, importModule });
121
151
  return {
122
152
  deps,
@@ -131,13 +161,13 @@ async function loadReloadableInMemoryRuntime(configPath, importModule, staticSch
131
161
  load: (graphId) => current.load(graphId),
132
162
  schemas: async (graphId) => await current.schemas(graphId)
133
163
  };
134
- const store = new MemorySkeinStore();
135
- const checkpointer = new MemorySaver();
164
+ const store = new MemorySkeinStore2();
165
+ const checkpointer = new MemorySaver2();
136
166
  const deps = {
137
167
  store,
138
168
  graphs,
139
- queue: new MemoryRunQueue(),
140
- bus: new MemoryRunEventBus(),
169
+ queue: new MemoryRunQueue2(),
170
+ bus: new MemoryRunEventBus2(),
141
171
  checkpointer,
142
172
  auth: await loadAuthEngine(first.config.auth, { configDir: first.configDir, importModule })
143
173
  };
@@ -189,7 +219,7 @@ async function resolveProtocolRuntime(options) {
189
219
  import { readFile } from "fs/promises";
190
220
  import path from "path";
191
221
  import {
192
- MemorySaver as MemorySaver2
222
+ MemorySaver as MemorySaver3
193
223
  } from "@langchain/langgraph";
194
224
  import {
195
225
  isTerminalRunStatus
@@ -417,7 +447,7 @@ async function readLanggraphDevState(langgraphApiDir) {
417
447
  };
418
448
  let checkpoints = { storage: {}, writes: {} };
419
449
  if (checkpointerFile) {
420
- const saver = new MemorySaver2();
450
+ const saver = new MemorySaver3();
421
451
  saver.storage = checkpointerFile.storage;
422
452
  saver.writes = checkpointerFile.writes;
423
453
  checkpoints = snapshotCheckpointer(saver);
@@ -437,7 +467,7 @@ function supportsRestore(store) {
437
467
  return typeof store.restore === "function";
438
468
  }
439
469
  async function copyCheckpoints(snapshot, target) {
440
- const source = new MemorySaver2();
470
+ const source = new MemorySaver3();
441
471
  hydrateCheckpointer(source, snapshot);
442
472
  const tuples = [];
443
473
  for await (const tuple of source.list({})) tuples.push(tuple);
@@ -615,11 +645,15 @@ export {
615
645
  corsFromHttpConfig,
616
646
  corsPreflightHeaders,
617
647
  corsResponseHeaders,
648
+ createInMemoryDeps,
618
649
  describeSnapshot,
650
+ embedInMemoryGraphs,
651
+ graphMapToResolver,
619
652
  joinList,
620
653
  loadInMemoryRuntime,
621
654
  loadReloadableInMemoryRuntime,
622
655
  loadSnapshotIntoStore,
656
+ normalizeEmbeddableGraphs,
623
657
  readLanggraphDevState,
624
658
  resolveProtocolRuntime,
625
659
  sendNodeError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skein-js/server-kit",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "description": "Shared, framework-agnostic building blocks for skein-js HTTP adapters — in-memory dev runtime, LangGraph dev-state import, and langgraph.json CORS mapping.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Maina Wycliffe <wmmaina7@gmail.com>",
@@ -43,10 +43,10 @@
43
43
  "cors": "^2.8.5",
44
44
  "superjson": "^2.2.6",
45
45
  "zod": "^3.25.76",
46
- "@skein-js/agent-protocol": "0.6.3",
47
- "@skein-js/config": "0.6.3",
48
- "@skein-js/core": "0.6.3",
49
- "@skein-js/storage-memory": "0.6.3"
46
+ "@skein-js/agent-protocol": "0.7.0",
47
+ "@skein-js/config": "0.7.0",
48
+ "@skein-js/core": "0.7.0",
49
+ "@skein-js/storage-memory": "0.7.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "@langchain/langgraph": "^1.4.0"