@skein-js/agent-protocol 0.8.0 → 0.9.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/dist/index.d.ts CHANGED
@@ -374,6 +374,12 @@ interface ProtocolRequest {
374
374
  query: Record<string, string | string[] | undefined>;
375
375
  body: unknown;
376
376
  headers: Record<string, string | undefined>;
377
+ /**
378
+ * Aborts when the client goes away, so a handler can stop work the caller will never read.
379
+ * Optional: an adapter that can't observe disconnects simply omits it. Currently honored by the
380
+ * single-graph invoke surface; protocol runs carry their own cancellation through the run row.
381
+ */
382
+ signal?: AbortSignal;
377
383
  }
378
384
  /** A normalized response an adapter serializes back onto its framework response. */
379
385
  type ProtocolResponse = {
@@ -466,11 +472,16 @@ interface ProtocolRuntime {
466
472
  declare function createProtocolRuntime(deps: ProtocolDeps, options?: ProtocolRuntimeOptions): ProtocolRuntime;
467
473
 
468
474
  type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
469
- interface RouteBinding {
475
+ /**
476
+ * One route. `HandlerName` defaults to a member of the protocol handler table; a surface mounted
477
+ * outside that table (the single-graph invoke endpoint) parameterizes it with its own handler names,
478
+ * so `handler` never has to lie about being a `keyof ProtocolHandlers` an adapter could look up.
479
+ */
480
+ interface RouteBinding<HandlerName = keyof ProtocolHandlers> {
470
481
  method: HttpMethod;
471
482
  /** Path with `:param` placeholders, e.g. `/threads/:thread_id/runs/stream`. */
472
483
  path: string;
473
- handler: keyof ProtocolHandlers;
484
+ handler: HandlerName;
474
485
  /**
475
486
  * Fold the path `thread_id` into the request body before dispatch. The SDK addresses a
476
487
  * thread-scoped run by its path (`POST /threads/{id}/runs/stream`) while carrying only
@@ -493,18 +504,50 @@ declare function copyThreadIdIntoBody(request: ProtocolRequest): ProtocolRequest
493
504
  */
494
505
  declare const foldThreadId: typeof copyThreadIdIntoBody;
495
506
  /** A resolved route: the matched binding plus the path params extracted from the URL. */
496
- interface RouteMatch {
497
- binding: RouteBinding;
507
+ interface RouteMatch<HandlerName = keyof ProtocolHandlers> {
508
+ binding: RouteBinding<HandlerName>;
498
509
  params: Record<string, string>;
499
510
  }
511
+ /** Matches a `method` + `pathname` against a fixed route table. Built by {@link createRouteMatcher}. */
512
+ type RouteMatcher<HandlerName = keyof ProtocolHandlers> = (method: string, pathname: string) => RouteMatch<HandlerName> | undefined;
513
+ /**
514
+ * Build a matcher over any route table — the protocol's own, or the simplified invoke surface's.
515
+ * Each `:param` path is compiled to a named-group regex once, anchored (`^…$`) so a literal segment
516
+ * can't be matched as a param value. The returned matcher iterates in table order, which is
517
+ * most-specific-first, so a literal segment wins over a `:param`.
518
+ */
519
+ declare function createRouteMatcher<HandlerName>(bindings: readonly RouteBinding<HandlerName>[]): RouteMatcher<HandlerName>;
520
+ /**
521
+ * Match a `method` + `pathname` (no query string) against the Agent Protocol route table. This is
522
+ * what adapters that dispatch from a catch-all route (NestJS middleware, Next.js route handlers) use
523
+ * in place of a framework router; Express/Fastify bind `skeinRoutes` to their native router instead.
524
+ */
525
+ declare const matchSkeinRoute: RouteMatcher;
526
+
527
+ /** The default path prefix the invoke endpoint mounts under. */
528
+ declare const DEFAULT_INVOKE_PREFIX = "/invoke";
529
+ /** Options for {@link createGraphInvokeHandler}. */
530
+ interface GraphInvokeOptions {
531
+ /**
532
+ * Stream modes used when the caller opts into SSE, overridable per request via `?stream_mode=`.
533
+ * Defaults to `"values"` — each frame is the full state after a step, ending at the same value the
534
+ * JSON response would have returned.
535
+ */
536
+ streamMode?: StreamMode | StreamMode[];
537
+ }
538
+ /** The single handler name this surface binds — deliberately not a `keyof ProtocolHandlers`. */
539
+ type GraphInvokeHandlerName = "invokeGraph";
540
+ /**
541
+ * The route table for the invoke surface — one POST, shaped like {@link skeinRoutes} so catch-all
542
+ * adapters (NestJS, Next.js) can match it the same way and native routers can bind it directly.
543
+ * Parameterized with its own handler name, so nothing can mistake it for a protocol-table lookup key.
544
+ */
545
+ declare function graphInvokeRoutes(prefix?: string): RouteBinding<GraphInvokeHandlerName>[];
500
546
  /**
501
- * Match a `method` + `pathname` (no query string) against the route table, returning the binding and
502
- * extracted path params, or `undefined` when nothing matches. Iterates in table order, which is
503
- * most-specific-first, so a literal segment wins over a `:param`. This is what adapters that dispatch
504
- * from a catch-all route (NestJS middleware, Next.js route handlers) use in place of a framework
505
- * router; Express/Fastify bind `skeinRoutes` to their native router instead.
547
+ * Build the handler for `POST <prefix>/:graph_id`. Returns a {@link ProtocolHandler}, so every
548
+ * adapter serializes it through the same JSON/SSE path the protocol routes already use.
506
549
  */
507
- declare function matchSkeinRoute(method: string, pathname: string): RouteMatch | undefined;
550
+ declare function createGraphInvokeHandler(deps: ProtocolDeps, options?: GraphInvokeOptions): ProtocolHandler;
508
551
 
509
552
  type LangGraphSearchItem = Item$1 & {
510
553
  score?: number;
@@ -559,4 +602,4 @@ declare function toSseEvents(frames: AsyncIterable<RunFrame>, finalStatus: () =>
559
602
  */
560
603
  declare function parseAfterSeq(lastEventId: string | undefined): number;
561
604
 
562
- export { type AssistantService, type Clock, type CommandInput, type CompiledGraphFactory, type CreateAssistantInput, type CreateRunInput, type CreateThreadInput, type DeleteAssistantOptions, type DrawGraphOptions, type GraphResolver, type GraphSchemas, type HistoryOptions, type HttpMethod, type Logger, type PatchThreadInput, type ProtocolContext, type ProtocolDeps, type ProtocolHandler, type ProtocolHandlers, type ProtocolRequest, type ProtocolResponse, type ProtocolRuntime, type ProtocolRuntimeOptions, type ProtocolService, type ResolvedGraph, type RouteBinding, type RouteMatch, type RunService, type RunWorker, type RunWorkerOptions, SSE_HEADERS, SkeinBaseStore, type StartedStream, type StoreService, type SubgraphsOptions, type ThreadService, type ThreadStreamInput, type ThreadStreamService, buildProtocolService, copyThreadIdIntoBody, createContext, createProtocolHandlers, createProtocolRuntime, createProtocolService, createProtocolServiceFromContext, createRunWorker, encodeFrame, encodeTerminal, foldThreadId, matchSkeinRoute, parseAfterSeq, skeinRoutes, toSseEvents };
605
+ export { type AssistantService, type Clock, type CommandInput, type CompiledGraphFactory, type CreateAssistantInput, type CreateRunInput, type CreateThreadInput, DEFAULT_INVOKE_PREFIX, type DeleteAssistantOptions, type DrawGraphOptions, type GraphInvokeHandlerName, type GraphInvokeOptions, type GraphResolver, type GraphSchemas, type HistoryOptions, type HttpMethod, type Logger, type PatchThreadInput, type ProtocolContext, type ProtocolDeps, type ProtocolHandler, type ProtocolHandlers, type ProtocolRequest, type ProtocolResponse, type ProtocolRuntime, type ProtocolRuntimeOptions, type ProtocolService, type ResolvedGraph, type RouteBinding, type RouteMatch, type RouteMatcher, type RunService, type RunWorker, type RunWorkerOptions, SSE_HEADERS, SkeinBaseStore, type StartedStream, type StoreService, type SubgraphsOptions, type ThreadService, type ThreadStreamInput, type ThreadStreamService, buildProtocolService, copyThreadIdIntoBody, createContext, createGraphInvokeHandler, createProtocolHandlers, createProtocolRuntime, createProtocolService, createProtocolServiceFromContext, createRouteMatcher, createRunWorker, encodeFrame, encodeTerminal, foldThreadId, graphInvokeRoutes, matchSkeinRoute, parseAfterSeq, skeinRoutes, toSseEvents };
package/dist/index.js CHANGED
@@ -758,50 +758,6 @@ import {
758
758
  SkeinHttpError as SkeinHttpError4
759
759
  } from "@skein-js/core";
760
760
 
761
- // src/normalize-error.ts
762
- import { isSkeinHttpError as isSkeinHttpError2, SkeinHttpError as SkeinHttpError3 } from "@skein-js/core";
763
- function serializeError(error) {
764
- if (error instanceof Error) {
765
- return { name: error.name, message: error.message };
766
- }
767
- return { name: "Error", message: String(error) };
768
- }
769
-
770
- // src/sse/run-frame-stream.ts
771
- var STREAM_MODES = [
772
- "values",
773
- "updates",
774
- "messages",
775
- "messages-tuple",
776
- "custom",
777
- "events",
778
- "debug"
779
- ];
780
- function isStreamMode(value) {
781
- return typeof value === "string" && STREAM_MODES.includes(value);
782
- }
783
- function chunkToFrameBody(chunk) {
784
- if (Array.isArray(chunk) && chunk.length === 2 && isStreamMode(chunk[0])) {
785
- return { event: chunk[0], data: chunk[1] };
786
- }
787
- return { event: "updates", data: chunk };
788
- }
789
- function toRunFrame(seq, body) {
790
- return { seq, event: body.event, data: body.data };
791
- }
792
- function streamEventToFrameBody(event, runId, graphModes) {
793
- if (event.tags?.includes("langsmith:hidden")) return null;
794
- if (event.event === "on_chain_stream" && event.run_id === runId) {
795
- const chunk = event.data?.chunk;
796
- if (Array.isArray(chunk) && chunk.length === 2 && isStreamMode(chunk[0])) {
797
- const mode = chunk[0];
798
- return graphModes.includes(mode) ? { event: mode, data: chunk[1] } : null;
799
- }
800
- return null;
801
- }
802
- return { event: "events", data: event };
803
- }
804
-
805
761
  // src/store/skein-base-store.ts
806
762
  import {
807
763
  BaseStore
@@ -878,6 +834,60 @@ var SkeinBaseStore = class extends BaseStore {
878
834
  }
879
835
  };
880
836
 
837
+ // src/graphs/resolve-compiled-graph.ts
838
+ async function resolveCompiledGraph(graphs, graphId, attachments) {
839
+ const resolved = await graphs.load(graphId);
840
+ const shared = typeof resolved === "function" ? await resolved({ configurable: attachments.configurable }) : resolved;
841
+ const graph = Object.create(shared);
842
+ graph.checkpointer = attachments.checkpointer;
843
+ graph.store = new SkeinBaseStore(attachments.store);
844
+ return graph;
845
+ }
846
+
847
+ // src/normalize-error.ts
848
+ import { isSkeinHttpError as isSkeinHttpError2, SkeinHttpError as SkeinHttpError3 } from "@skein-js/core";
849
+ function serializeError(error) {
850
+ if (error instanceof Error) {
851
+ return { name: error.name, message: error.message };
852
+ }
853
+ return { name: "Error", message: String(error) };
854
+ }
855
+
856
+ // src/sse/run-frame-stream.ts
857
+ var STREAM_MODES = [
858
+ "values",
859
+ "updates",
860
+ "messages",
861
+ "messages-tuple",
862
+ "custom",
863
+ "events",
864
+ "debug"
865
+ ];
866
+ function isStreamMode(value) {
867
+ return typeof value === "string" && STREAM_MODES.includes(value);
868
+ }
869
+ function chunkToFrameBody(chunk) {
870
+ if (Array.isArray(chunk) && chunk.length === 2 && isStreamMode(chunk[0])) {
871
+ return { event: chunk[0], data: chunk[1] };
872
+ }
873
+ return { event: "updates", data: chunk };
874
+ }
875
+ function toRunFrame(seq, body) {
876
+ return { seq, event: body.event, data: body.data };
877
+ }
878
+ function streamEventToFrameBody(event, runId, graphModes) {
879
+ if (event.tags?.includes("langsmith:hidden")) return null;
880
+ if (event.event === "on_chain_stream" && event.run_id === runId) {
881
+ const chunk = event.data?.chunk;
882
+ if (Array.isArray(chunk) && chunk.length === 2 && isStreamMode(chunk[0])) {
883
+ const mode = chunk[0];
884
+ return graphModes.includes(mode) ? { event: mode, data: chunk[1] } : null;
885
+ }
886
+ return null;
887
+ }
888
+ return { event: "events", data: event };
889
+ }
890
+
881
891
  // src/runs/run-status.ts
882
892
  import { isTerminalRunStatus } from "@skein-js/core";
883
893
  function threadStatusForRun(status) {
@@ -1125,16 +1135,11 @@ function abortedStatus(reason) {
1125
1135
  return "cancelled";
1126
1136
  }
1127
1137
  async function resolveGraph(deps, graphId, kwargs) {
1128
- const resolved = await deps.graphs.load(graphId);
1129
- const graph = typeof resolved === "function" ? (
1130
- // Expose the authenticated caller to a graph *factory* too, so a factory that branches on the
1131
- // principal sees the same `langgraph_auth_user` a node reads — sanitized identically, so a
1132
- // client can't spoof it via its own configurable.
1133
- await resolved({ configurable: toFactoryConfigurable(kwargs) })
1134
- ) : resolved;
1135
- graph.checkpointer = deps.checkpointer;
1136
- graph.store = new SkeinBaseStore(deps.store.store);
1137
- return graph;
1138
+ return resolveCompiledGraph(deps.graphs, graphId, {
1139
+ configurable: toFactoryConfigurable(kwargs),
1140
+ checkpointer: deps.checkpointer,
1141
+ store: deps.store.store
1142
+ });
1138
1143
  }
1139
1144
  async function finalizeRun(deps, runId, status) {
1140
1145
  const fresh = await deps.store.runs.get(runId);
@@ -1960,27 +1965,29 @@ function synthesizeRequest(req) {
1960
1965
  });
1961
1966
  }
1962
1967
 
1963
- // src/auth/authorizing-handlers.ts
1968
+ // src/auth/authenticate-request.ts
1964
1969
  var STUDIO_USER = {
1965
1970
  identity: "langgraph-studio-user",
1966
1971
  display_name: "langgraph-studio-user",
1967
1972
  is_authenticated: true,
1968
1973
  permissions: []
1969
1974
  };
1975
+ async function resolveAuthContext(engine, req) {
1976
+ if (!engine.studioAuthDisabled && req.headers["x-auth-scheme"] === "langsmith") {
1977
+ return { user: STUDIO_USER, scopes: [] };
1978
+ }
1979
+ return engine.authenticate(synthesizeRequest(req));
1980
+ }
1981
+
1982
+ // src/auth/authorizing-handlers.ts
1970
1983
  function createAuthorizingHandlers(context, engine) {
1971
1984
  const baseHandlers = createProtocolHandlers(createProtocolServiceFromContext(context));
1972
1985
  const names = Object.keys(ROUTE_AUTHZ);
1973
- const resolveAuthContext = async (req) => {
1974
- if (!engine.studioAuthDisabled && req.headers["x-auth-scheme"] === "langsmith") {
1975
- return { user: STUDIO_USER, scopes: [] };
1976
- }
1977
- return engine.authenticate(synthesizeRequest(req));
1978
- };
1979
1986
  const wrapped = {};
1980
1987
  for (const name of names) {
1981
1988
  const route = ROUTE_AUTHZ[name];
1982
1989
  wrapped[name] = async (req) => {
1983
- const authContext = await resolveAuthContext(req);
1990
+ const authContext = await resolveAuthContext(engine, req);
1984
1991
  const { filters } = await engine.authorize({
1985
1992
  resource: route.resource,
1986
1993
  action: route.action,
@@ -2154,19 +2161,22 @@ function copyThreadIdIntoBody(request) {
2154
2161
  return { ...request, body: { ...base, thread_id: threadId } };
2155
2162
  }
2156
2163
  var foldThreadId = copyThreadIdIntoBody;
2157
- var compiledRoutes = skeinRoutes.map((binding) => ({
2158
- binding,
2159
- regex: new RegExp(`^${binding.path.replace(/:(\w+)/g, "(?<$1>[^/]+)")}$`)
2160
- }));
2161
- function matchSkeinRoute(method, pathname) {
2162
- const wanted = method.toLowerCase();
2163
- for (const { binding, regex } of compiledRoutes) {
2164
- if (binding.method !== wanted) continue;
2165
- const match = regex.exec(pathname);
2166
- if (match) return { binding, params: decodeParams(match.groups) };
2167
- }
2168
- return void 0;
2164
+ function createRouteMatcher(bindings) {
2165
+ const compiled = bindings.map((binding) => ({
2166
+ binding,
2167
+ regex: new RegExp(`^${binding.path.replace(/:(\w+)/g, "(?<$1>[^/]+)")}$`)
2168
+ }));
2169
+ return (method, pathname) => {
2170
+ const wanted = method.toLowerCase();
2171
+ for (const { binding, regex } of compiled) {
2172
+ if (binding.method !== wanted) continue;
2173
+ const match = regex.exec(pathname);
2174
+ if (match) return { binding, params: decodeParams(match.groups) };
2175
+ }
2176
+ return void 0;
2177
+ };
2169
2178
  }
2179
+ var matchSkeinRoute = createRouteMatcher(skeinRoutes);
2170
2180
  function decodeParams(groups) {
2171
2181
  const params = {};
2172
2182
  for (const [key, value] of Object.entries(groups ?? {})) {
@@ -2178,20 +2188,149 @@ function decodeParams(groups) {
2178
2188
  }
2179
2189
  return params;
2180
2190
  }
2191
+
2192
+ // src/invoke/graph-invoke.ts
2193
+ import { randomUUID } from "crypto";
2194
+ import { MemorySaver } from "@langchain/langgraph";
2195
+ import {
2196
+ SkeinHttpError as SkeinHttpError10
2197
+ } from "@skein-js/core";
2198
+ import { z as z2 } from "zod";
2199
+ var DEFAULT_INVOKE_PREFIX = "/invoke";
2200
+ function graphInvokeRoutes(prefix = DEFAULT_INVOKE_PREFIX) {
2201
+ return [{ method: "post", path: `${normalizePrefix(prefix)}/:graph_id`, handler: "invokeGraph" }];
2202
+ }
2203
+ function normalizePrefix(prefix) {
2204
+ const trimmed = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
2205
+ return trimmed === "/" ? "" : trimmed;
2206
+ }
2207
+ function wantsEventStream(req) {
2208
+ return req.headers["accept"]?.includes("text/event-stream") ?? false;
2209
+ }
2210
+ function createRunSignal(timeoutMs, callerSignal) {
2211
+ if (timeoutMs === void 0 && !callerSignal) return { signal: void 0, dispose: () => {
2212
+ } };
2213
+ const controller = new AbortController();
2214
+ const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => controller.abort(new Error(`Run exceeded ${timeoutMs}ms`)), timeoutMs);
2215
+ const onCallerAbort = () => controller.abort(callerSignal?.reason);
2216
+ if (callerSignal?.aborted) onCallerAbort();
2217
+ else callerSignal?.addEventListener("abort", onCallerAbort);
2218
+ return {
2219
+ signal: controller.signal,
2220
+ dispose: () => {
2221
+ if (timer !== void 0) clearTimeout(timer);
2222
+ callerSignal?.removeEventListener("abort", onCallerAbort);
2223
+ }
2224
+ };
2225
+ }
2226
+ var INVOKE_STREAM_MODES = [
2227
+ "values",
2228
+ "updates",
2229
+ "messages",
2230
+ "messages-tuple",
2231
+ "custom",
2232
+ "debug"
2233
+ ];
2234
+ var streamModeQuerySchema = z2.array(z2.enum(INVOKE_STREAM_MODES)).min(1, "expected at least one stream mode");
2235
+ function streamModeFromQuery(value) {
2236
+ const raw = Array.isArray(value) ? value : value === void 0 ? [] : value.split(",");
2237
+ const modes = raw.map((mode) => mode.trim()).filter((mode) => mode.length > 0);
2238
+ if (modes.length === 0) return void 0;
2239
+ if (modes.includes("events")) {
2240
+ throw SkeinHttpError10.badRequest(
2241
+ 'Stream mode "events" is not supported on the invoke surface; use the Agent Protocol run endpoints for token-level events.'
2242
+ );
2243
+ }
2244
+ return parse(streamModeQuerySchema, modes, "stream_mode query parameter");
2245
+ }
2246
+ function createGraphInvokeHandler(deps, options = {}) {
2247
+ return async (req) => {
2248
+ const graphId = requireParam(req.params, "graph_id");
2249
+ let authContext;
2250
+ if (deps.auth) {
2251
+ authContext = await resolveAuthContext(deps.auth, req);
2252
+ await deps.auth.authorize({
2253
+ resource: "threads",
2254
+ action: "create_run",
2255
+ // `authValue` spreads the body last, and on this surface the body is arbitrary caller-supplied
2256
+ // graph input — so a body key named `graph_id` would shadow the path param and let a policy
2257
+ // authorize a different graph than the one that actually runs. Re-stamp the server-derived id
2258
+ // last so the value a policy judges is always the graph we execute.
2259
+ value: { ...authValue(req), graph_id: graphId },
2260
+ context: authContext
2261
+ });
2262
+ }
2263
+ if (!deps.graphs.ids.includes(graphId)) {
2264
+ throw SkeinHttpError10.notFound(`Graph "${graphId}" is not registered.`, {
2265
+ code: "graph_not_found"
2266
+ });
2267
+ }
2268
+ const factoryConfigurable2 = withAuthUser({}, authContext?.user, authContext?.scopes);
2269
+ const graph = await resolveCompiledGraph(deps.graphs, graphId, {
2270
+ configurable: Object.keys(factoryConfigurable2).length > 0 ? factoryConfigurable2 : void 0,
2271
+ checkpointer: new MemorySaver(),
2272
+ store: deps.store.store
2273
+ });
2274
+ const configurable = withAuthUser(
2275
+ { thread_id: randomUUID() },
2276
+ authContext?.user,
2277
+ authContext?.scopes
2278
+ );
2279
+ const input = req.body ?? {};
2280
+ const { signal, dispose } = createRunSignal(deps.runTimeoutMs, req.signal);
2281
+ if (!wantsEventStream(req)) {
2282
+ try {
2283
+ const output = await graph.invoke(input, { configurable, signal });
2284
+ return { kind: "json", status: 200, body: output };
2285
+ } finally {
2286
+ dispose();
2287
+ }
2288
+ }
2289
+ const streamMode = toGraphStreamModes(
2290
+ streamModeFromQuery(req.query["stream_mode"]) ?? options.streamMode ?? "values"
2291
+ );
2292
+ let status = "success";
2293
+ const frames = async function* () {
2294
+ let seq = 0;
2295
+ try {
2296
+ const stream = await graph.stream(input, {
2297
+ configurable,
2298
+ streamMode,
2299
+ signal
2300
+ });
2301
+ for await (const chunk of stream) {
2302
+ seq += 1;
2303
+ yield toRunFrame(seq, chunkToFrameBody(chunk));
2304
+ }
2305
+ } catch (error) {
2306
+ status = "error";
2307
+ seq += 1;
2308
+ yield { seq, event: "error", data: serializeError(error) };
2309
+ } finally {
2310
+ dispose();
2311
+ }
2312
+ };
2313
+ return { kind: "sse", status: 200, events: toSseEvents(frames(), async () => status) };
2314
+ };
2315
+ }
2181
2316
  export {
2317
+ DEFAULT_INVOKE_PREFIX,
2182
2318
  SSE_HEADERS,
2183
2319
  SkeinBaseStore,
2184
2320
  buildProtocolService,
2185
2321
  copyThreadIdIntoBody,
2186
2322
  createContext,
2323
+ createGraphInvokeHandler,
2187
2324
  createProtocolHandlers,
2188
2325
  createProtocolRuntime,
2189
2326
  createProtocolService,
2190
2327
  createProtocolServiceFromContext,
2328
+ createRouteMatcher,
2191
2329
  createRunWorker,
2192
2330
  encodeFrame,
2193
2331
  encodeTerminal,
2194
2332
  foldThreadId,
2333
+ graphInvokeRoutes,
2195
2334
  matchSkeinRoute,
2196
2335
  parseAfterSeq,
2197
2336
  skeinRoutes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skein-js/agent-protocol",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Framework-agnostic Agent Protocol engine for LangGraph.js — run engine, handlers, and SSE, driven entirely by injected dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Maina Wycliffe <wmmaina7@gmail.com>",
@@ -44,14 +44,14 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "zod": "^3.25.76",
47
- "@skein-js/core": "0.8.0"
47
+ "@skein-js/core": "0.9.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@langchain/langgraph": "^1.4.0",
51
51
  "@langchain/langgraph-sdk": "^1.9.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@skein-js/storage-memory": "0.8.0"
54
+ "@skein-js/storage-memory": "0.9.0"
55
55
  },
56
56
  "publishConfig": {
57
57
  "access": "public"