@langchain/langgraph-api 1.1.10 → 1.1.12

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.
@@ -86,7 +86,8 @@ api.get("/assistants/:assistant_id", async (c) => {
86
86
  api.delete("/assistants/:assistant_id", async (c) => {
87
87
  // Delete Assistant
88
88
  const assistantId = getAssistantId(c.req.param("assistant_id"));
89
- return c.json(await assistants().delete(assistantId, c.var.auth));
89
+ const deleteThreads = c.req.query("delete_threads") === "true";
90
+ return c.json(await assistants().delete(assistantId, deleteThreads, c.var.auth));
90
91
  });
91
92
  api.patch("/assistants/:assistant_id", zValidator("json", schemas.AssistantPatch), async (c) => {
92
93
  // Patch Assistant
@@ -19,5 +19,17 @@ export declare function getStaticGraphSchema(specMap: Record<string, GraphSpec>,
19
19
  mainThread?: boolean;
20
20
  timeoutMs?: number;
21
21
  }): Promise<Record<string, GraphSchemaWithSubgraphs>>;
22
+ /**
23
+ * Extract JSON schemas from a compiled graph at runtime.
24
+ *
25
+ * Uses a multi-tier extraction strategy:
26
+ * 1. StateSchema - Native JSON schema via getJsonSchema() (handles jsonSchemaExtra)
27
+ * 2. Zod Registry - Via schemaMetaRegistry (handles withLangGraph jsonSchemaExtra)
28
+ * 3. Direct Zod - Fallback conversion without registry (no jsonSchemaExtra)
29
+ * 4. Returns undefined to fall back to static TypeScript parser
30
+ *
31
+ * @param graph - The compiled Pregel graph to extract schemas from
32
+ * @returns GraphSchema with state/input/output/config schemas, or undefined if extraction fails
33
+ */
22
34
  export declare function getRuntimeGraphSchema(graph: Pregel<any, any, any, any, any>): Promise<GraphSchema | undefined>;
23
35
  export {};
@@ -38,7 +38,66 @@ export async function getStaticGraphSchema(input, options) {
38
38
  }
39
39
  return Object.fromEntries(Object.keys(input).map((graphId, idx) => [graphId, results[idx]]));
40
40
  }
41
- export async function getRuntimeGraphSchema(graph) {
41
+ // Symbol used when input inherits from state schema but as partial
42
+ const PartialStateSchema = Symbol.for("langgraph.state.partial");
43
+ function isStateSchemaLike(value) {
44
+ return (typeof value === "object" &&
45
+ value !== null &&
46
+ "getJsonSchema" in value &&
47
+ typeof value.getJsonSchema === "function" &&
48
+ "getInputJsonSchema" in value &&
49
+ typeof value.getInputJsonSchema === "function");
50
+ }
51
+ /**
52
+ * Try to extract schema from StateSchema instance.
53
+ * StateSchema handles jsonSchemaExtra internally via ReducedValue.jsonSchemaExtra
54
+ *
55
+ * @param graph - The compiled graph to extract schemas from
56
+ * @returns GraphSchema if StateSchema instances found, undefined otherwise
57
+ */
58
+ async function tryStateSchemaExtraction(graph) {
59
+ const builder = graph.builder;
60
+ if (!builder)
61
+ return undefined;
62
+ // Check if ANY of the schemas are StateSchema-like (have getJsonSchema/getInputJsonSchema methods)
63
+ const schemaDefIsLike = isStateSchemaLike(builder._schemaRuntimeDefinition);
64
+ const inputDefIsLike = isStateSchemaLike(builder._inputRuntimeDefinition);
65
+ const outputDefIsLike = isStateSchemaLike(builder._outputRuntimeDefinition);
66
+ const hasStateSchema = schemaDefIsLike || inputDefIsLike || outputDefIsLike;
67
+ if (!hasStateSchema)
68
+ return undefined;
69
+ // Extract from StateSchema-like instances
70
+ const state = isStateSchemaLike(builder._schemaRuntimeDefinition)
71
+ ? builder._schemaRuntimeDefinition.getJsonSchema()
72
+ : undefined;
73
+ const input = (() => {
74
+ if (isStateSchemaLike(builder._inputRuntimeDefinition)) {
75
+ return builder._inputRuntimeDefinition.getInputJsonSchema();
76
+ }
77
+ // PartialStateSchema means input inherits from state as partial
78
+ if (builder._inputRuntimeDefinition === PartialStateSchema &&
79
+ isStateSchemaLike(builder._schemaRuntimeDefinition)) {
80
+ return builder._schemaRuntimeDefinition.getInputJsonSchema();
81
+ }
82
+ return undefined;
83
+ })();
84
+ const output = isStateSchemaLike(builder._outputRuntimeDefinition)
85
+ ? builder._outputRuntimeDefinition.getJsonSchema()
86
+ : undefined;
87
+ // StateSchema doesn't have config schema support yet
88
+ const config = undefined;
89
+ if (!state && !input && !output)
90
+ return undefined;
91
+ return { state, input, output, config };
92
+ }
93
+ /**
94
+ * Try existing Zod extraction via schemaMetaRegistry.
95
+ * This handles jsonSchemaExtra from withLangGraph() calls.
96
+ *
97
+ * @param graph - The compiled graph to extract schemas from
98
+ * @returns GraphSchema if Zod schemas found in registry, undefined otherwise
99
+ */
100
+ async function tryZodRegistryExtraction(graph) {
42
101
  try {
43
102
  const { getInputTypeSchema, getOutputTypeSchema, getUpdateTypeSchema, getConfigTypeSchema, } = await import("@langchain/langgraph/zod/schema");
44
103
  const result = {
@@ -52,7 +111,78 @@ export async function getRuntimeGraphSchema(graph) {
52
111
  return result;
53
112
  }
54
113
  catch {
55
- // ignore
114
+ return undefined;
115
+ }
116
+ }
117
+ /**
118
+ * Fallback: Try direct Zod conversion without registry.
119
+ * Handles Zod schemas that weren't registered with withLangGraph().
120
+ * Note: jsonSchemaExtra will NOT be included in this path.
121
+ *
122
+ * @param graph - The compiled graph to extract schemas from
123
+ * @returns GraphSchema if Zod schemas found, undefined otherwise
124
+ */
125
+ async function tryDirectZodExtraction(graph) {
126
+ try {
127
+ const { toJsonSchema } = await import("@langchain/core/utils/json_schema");
128
+ const { isZodSchemaV3, isZodSchemaV4 } = await import("@langchain/core/utils/types");
129
+ const builder = graph.builder;
130
+ if (!builder)
131
+ return undefined;
132
+ const extractSchema = (schema) => {
133
+ if (!schema)
134
+ return undefined;
135
+ if (isZodSchemaV4(schema) || isZodSchemaV3(schema)) {
136
+ try {
137
+ return toJsonSchema(schema);
138
+ }
139
+ catch {
140
+ return undefined;
141
+ }
142
+ }
143
+ return undefined;
144
+ };
145
+ const state = extractSchema(builder._schemaRuntimeDefinition);
146
+ const input = extractSchema(builder._inputRuntimeDefinition) ??
147
+ (state ? { ...state, required: undefined } : undefined);
148
+ const output = extractSchema(builder._outputRuntimeDefinition);
149
+ const config = extractSchema(builder._configRuntimeSchema);
150
+ if (!state && !input && !output && !config)
151
+ return undefined;
152
+ return { state, input, output, config };
153
+ }
154
+ catch {
155
+ return undefined;
56
156
  }
157
+ }
158
+ /**
159
+ * Extract JSON schemas from a compiled graph at runtime.
160
+ *
161
+ * Uses a multi-tier extraction strategy:
162
+ * 1. StateSchema - Native JSON schema via getJsonSchema() (handles jsonSchemaExtra)
163
+ * 2. Zod Registry - Via schemaMetaRegistry (handles withLangGraph jsonSchemaExtra)
164
+ * 3. Direct Zod - Fallback conversion without registry (no jsonSchemaExtra)
165
+ * 4. Returns undefined to fall back to static TypeScript parser
166
+ *
167
+ * @param graph - The compiled Pregel graph to extract schemas from
168
+ * @returns GraphSchema with state/input/output/config schemas, or undefined if extraction fails
169
+ */
170
+ export async function getRuntimeGraphSchema(graph) {
171
+ const builder = graph.builder;
172
+ if (!builder)
173
+ return undefined;
174
+ // Priority 1: StateSchema (handles jsonSchemaExtra via ReducedValue)
175
+ const stateSchemaResult = await tryStateSchemaExtraction(graph);
176
+ if (stateSchemaResult)
177
+ return stateSchemaResult;
178
+ // Priority 2: Zod via schemaMetaRegistry (handles jsonSchemaExtra from withLangGraph)
179
+ const zodRegistryResult = await tryZodRegistryExtraction(graph);
180
+ if (zodRegistryResult)
181
+ return zodRegistryResult;
182
+ // Priority 3: Direct Zod conversion (no jsonSchemaExtra, but better than nothing)
183
+ const directZodResult = await tryDirectZodExtraction(graph);
184
+ if (directZodResult)
185
+ return directZodResult;
186
+ // Priority 4: Fall through to static TypeScript parser
57
187
  return undefined;
58
188
  }
@@ -77,7 +77,7 @@ export declare class FileSystemAssistants implements AssistantsRepo {
77
77
  name?: string;
78
78
  description?: string;
79
79
  }, auth: AuthContext | undefined): Promise<Assistant>;
80
- delete(assistant_id: string, auth: AuthContext | undefined): Promise<string[]>;
80
+ delete(assistant_id: string, delete_threads: boolean, auth: AuthContext | undefined): Promise<string[]>;
81
81
  setLatest(assistant_id: string, version: number, auth: AuthContext | undefined): Promise<Assistant>;
82
82
  getVersions(assistant_id: string, options: {
83
83
  limit: number;
@@ -330,7 +330,7 @@ export class FileSystemAssistants {
330
330
  return assistant;
331
331
  });
332
332
  }
333
- async delete(assistant_id, auth) {
333
+ async delete(assistant_id, delete_threads, auth) {
334
334
  const [filters] = await handleAuthEvent(auth, "assistants:delete", {
335
335
  assistant_id,
336
336
  });
@@ -343,13 +343,20 @@ export class FileSystemAssistants {
343
343
  throw new HTTPException(404, { message: "Assistant not found" });
344
344
  }
345
345
  delete STORE.assistants[assistant_id];
346
- // Cascade delete for assistant versions and crons
346
+ // Cascade delete for assistant versions and crons and threads
347
347
  STORE.assistant_versions = STORE.assistant_versions.filter((v) => v["assistant_id"] !== assistant_id);
348
348
  for (const run of Object.values(STORE.runs)) {
349
349
  if (run["assistant_id"] === assistant_id) {
350
350
  delete STORE.runs[run["run_id"]];
351
351
  }
352
352
  }
353
+ if (delete_threads === true) {
354
+ for (const thread of Object.values(STORE.threads)) {
355
+ if (thread["metadata"]?.["assistant_id"] === assistant_id) {
356
+ delete STORE.threads[thread["thread_id"]];
357
+ }
358
+ }
359
+ }
353
360
  return [assistant.assistant_id];
354
361
  });
355
362
  }
@@ -274,7 +274,7 @@ export interface AssistantsRepo {
274
274
  name?: string;
275
275
  description?: string;
276
276
  }, auth: AuthContext | undefined): Promise<Assistant>;
277
- delete(assistant_id: string, auth: AuthContext | undefined): Promise<string[]>;
277
+ delete(assistant_id: string, delete_threads: boolean, auth: AuthContext | undefined): Promise<string[]>;
278
278
  count(options: {
279
279
  graph_id?: string;
280
280
  name?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-api",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": "^18.19.0 || >=20.16.0"
@@ -70,7 +70,7 @@
70
70
  "winston": "^3.17.0",
71
71
  "winston-console-format": "^1.0.8",
72
72
  "zod": "^3.25.76 || ^4",
73
- "@langchain/langgraph-ui": "1.1.10"
73
+ "@langchain/langgraph-ui": "1.1.12"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@langchain/core": "^0.3.59 || ^1.0.1",
@@ -98,9 +98,9 @@
98
98
  "typescript": "^4.9.5 || ^5.4.5",
99
99
  "vitest": "^3.2.4",
100
100
  "wait-port": "^1.1.0",
101
- "@langchain/langgraph": "1.0.14",
101
+ "@langchain/langgraph": "1.1.3",
102
102
  "@langchain/langgraph-checkpoint": "1.0.0",
103
- "@langchain/langgraph-sdk": "1.4.6"
103
+ "@langchain/langgraph-sdk": "1.5.6"
104
104
  },
105
105
  "scripts": {
106
106
  "clean": "rm -rf dist/ .turbo/ ./tests/graphs/.langgraph_api/",