@langchain/langgraph-api 1.2.4 → 1.2.5

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.
@@ -305,15 +305,20 @@ export class RunProtocolSession {
305
305
  case "tools":
306
306
  await this.pushEvent(this.createEvent("tools", namespace, normalizeToolData(event.data, event.id ?? uuid7())));
307
307
  return;
308
- default:
309
- // Route unknown methods as named custom events. This allows
310
- // reducers to emit("a2a", data) and have it appear on the
311
- // custom channel with name set for client-side filtering.
308
+ default: {
309
+ // Route unknown methods as named custom events. Extension
310
+ // StreamChannels emit `custom:<name>` on the wire (matching
311
+ // Python's mux); strip the prefix so `custom:<name>`
312
+ // subscriptions match on `data.name === <name>`.
313
+ const channelName = method.startsWith("custom:")
314
+ ? method.slice("custom:".length)
315
+ : method;
312
316
  await this.pushEvent(this.createEvent("custom", namespace, {
313
- name: method,
317
+ name: channelName,
314
318
  payload: event.data,
315
319
  }));
316
320
  return;
321
+ }
317
322
  }
318
323
  }
319
324
  /**
@@ -367,8 +372,21 @@ export class RunProtocolSession {
367
372
  await this.pushEvent(this.createEvent("checkpoints", namespace, data));
368
373
  return true;
369
374
  }
370
- default:
371
- return false;
375
+ default: {
376
+ if (!method.startsWith("custom:")) {
377
+ return false;
378
+ }
379
+ const channelName = method.slice("custom:".length);
380
+ if (!channelName) {
381
+ return false;
382
+ }
383
+ await this.ensureNamespaces(namespace);
384
+ await this.pushEvent(this.createEvent("custom", namespace, {
385
+ name: channelName,
386
+ payload: data,
387
+ }));
388
+ return true;
389
+ }
372
390
  }
373
391
  }
374
392
  /**
package/dist/stream.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isBaseMessage } from "@langchain/core/messages";
2
2
  import { LangChainTracer } from "@langchain/core/tracers/tracer_langchain";
3
- import { convertToProtocolEvent, STREAM_EVENTS_V3_MODES, } from "@langchain/langgraph/web";
3
+ import { convertToProtocolEvent, isCheckpointEnvelope, STREAM_EVENTS_V3_MODES, } from "@langchain/langgraph/web";
4
4
  import { Client as LangSmithClient, getDefaultProjectName } from "langsmith";
5
5
  import { getLangGraphCommand } from "./command.mjs";
6
6
  import { PROTOCOL_STREAM_RUN_KEY } from "./protocol/constants.mjs";
@@ -136,14 +136,10 @@ export async function* streamState(run, options) {
136
136
  continue;
137
137
  if (event.event === "on_chain_stream" &&
138
138
  (kwargs.subgraphs || event.run_id === run.run_id)) {
139
- // Pregel's stream tuple is `[ns, mode, payload, meta?]` (4th element
140
- // is the optional `StreamChunkMeta`, preserved when streaming with
141
- // `subgraphs: true`). The meta carries the lightweight checkpoint
142
- // envelope attached by `_emitValuesWithCheckpointMeta`, which we
143
- // forward as a companion `checkpoints` source event below.
139
+ // Pregel stream chunks are `[ns, mode, payload]`. Lightweight checkpoint
140
+ // envelopes arrive as a separate `checkpoints` chunk before `values`.
144
141
  const rawTuple = (kwargs.subgraphs ? event.data.chunk : [null, ...event.data.chunk]);
145
142
  const [ns, mode, chunk] = rawTuple;
146
- const chunkMeta = rawTuple[3];
147
143
  let data = chunk;
148
144
  if (mode === "debug") {
149
145
  const debugChunk = chunk;
@@ -159,9 +155,26 @@ export async function* streamState(run, options) {
159
155
  }
160
156
  }
161
157
  else if (mode === "checkpoints") {
162
- const debugCheckpoint = preprocessDebugCheckpoint(chunk);
158
+ if (isCheckpointEnvelope(chunk)) {
159
+ // Lightweight envelopes pair with `values` on the v3 path.
160
+ // Legacy `checkpoints` stream mode consumers expect full debug
161
+ // snapshots (`values` / `metadata` / `next`) from `mapDebugCheckpoint`.
162
+ if (!userStreamMode.includes("checkpoints")) {
163
+ const sseEvent = kwargs.subgraphs && ns?.length
164
+ ? `checkpoints|${ns.join("|")}`
165
+ : "checkpoints";
166
+ yield { event: sseEvent, data: chunk };
167
+ }
168
+ continue;
169
+ }
170
+ const debugPayload = chunk;
171
+ const debugCheckpoint = preprocessDebugCheckpoint(debugPayload);
163
172
  options?.onCheckpoint?.(debugCheckpoint);
164
- data = debugCheckpoint;
173
+ data = {
174
+ values: debugPayload.values,
175
+ metadata: debugPayload.metadata,
176
+ next: debugPayload.next,
177
+ };
165
178
  }
166
179
  else if (mode === "tasks") {
167
180
  const debugTask = preprocessDebugCheckpointTask(chunk);
@@ -170,20 +183,6 @@ export async function* streamState(run, options) {
170
183
  }
171
184
  data = debugTask;
172
185
  }
173
- // Emit the lightweight checkpoint envelope as a dedicated
174
- // `checkpoints` source event immediately BEFORE the companion
175
- // `values` event so clients subscribed to both channels have the
176
- // envelope buffered by the time the values payload arrives
177
- // (`useMessageMetadata(msg.id).parentCheckpointId` for fork /
178
- // edit flows). Clients that only want fork / time-travel metadata
179
- // subscribe to `checkpoints` alone and avoid the full-state
180
- // payload.
181
- if (mode === "values" && chunkMeta?.checkpoint != null) {
182
- const sseEvent = kwargs.subgraphs && ns?.length
183
- ? `checkpoints|${ns.join("|")}`
184
- : "checkpoints";
185
- yield { event: sseEvent, data: chunkMeta.checkpoint };
186
- }
187
186
  if (mode === "messages") {
188
187
  if (userStreamMode.includes("messages-tuple")) {
189
188
  if (kwargs.subgraphs && ns?.length) {
@@ -270,13 +269,12 @@ async function* fallbackProtocolStreamFromGraphStream(graph, input, options) {
270
269
  let seq = 0;
271
270
  const stream = await graph.stream(input, options);
272
271
  for await (const tuple of stream) {
273
- const [namespace, mode, payload, meta] = tuple;
272
+ const [namespace, mode, payload] = tuple;
274
273
  const events = convertToProtocolEvent({
275
274
  namespace: namespace ?? [],
276
275
  mode,
277
276
  payload,
278
277
  seq,
279
- meta: meta,
280
278
  });
281
279
  seq += events.length;
282
280
  for (const event of events) {
@@ -411,6 +409,7 @@ export async function* streamStateV2(run, options) {
411
409
  const normalized = mode === "tools" ||
412
410
  mode === "updates" ||
413
411
  mode === "custom" ||
412
+ mode.startsWith("custom:") ||
414
413
  mode === "messages" ||
415
414
  mode === "checkpoints" ||
416
415
  mode === "lifecycle";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-api",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": "^18.19.0 || >=20.16.0"
@@ -61,7 +61,7 @@
61
61
  "dedent": "^1.5.3",
62
62
  "dotenv": "^16.4.7",
63
63
  "exit-hook": "^4.0.0",
64
- "hono": "^4.12.18",
64
+ "hono": "^4.12.21",
65
65
  "langsmith": ">=0.5.19 <1.0.0",
66
66
  "open": "^10.1.0",
67
67
  "semver": "^7.7.1",
@@ -72,10 +72,10 @@
72
72
  "winston": "^3.17.0",
73
73
  "winston-console-format": "^1.0.8",
74
74
  "zod": "^3.25.76 || ^4",
75
- "@langchain/langgraph-ui": "1.2.4"
75
+ "@langchain/langgraph-ui": "1.2.5"
76
76
  },
77
77
  "peerDependencies": {
78
- "@langchain/core": "^1.1.44",
78
+ "@langchain/core": "^1.1.48",
79
79
  "@langchain/langgraph": "^0.2.57 || ^0.3.0 || ^0.4.0 || ^1.0.0-alpha || ^1.0.0 || ^1.3.1-rc.0",
80
80
  "@langchain/langgraph-checkpoint": "~0.0.16 || ^0.1.0 || ~1.0.0",
81
81
  "@langchain/langgraph-sdk": "^1.9.3-rc.0",
@@ -87,23 +87,23 @@
87
87
  }
88
88
  },
89
89
  "devDependencies": {
90
- "@langchain/core": "^1.1.44",
90
+ "@langchain/core": "^1.1.48",
91
91
  "@types/babel__code-frame": "^7.0.6",
92
92
  "@types/node": "^18.15.11",
93
- "@types/react": "^19.0.8",
93
+ "@types/react": "^19.2.16",
94
94
  "@types/react-dom": "^19.0.3",
95
95
  "@types/semver": "^7.7.0",
96
96
  "@types/uuid": "^10.0.0",
97
97
  "deepagents": "^1.9.0",
98
98
  "jose": "^6.0.10",
99
- "langchain": "^1.2.30",
99
+ "langchain": "^1.4.4",
100
100
  "postgres": "^3.4.5",
101
101
  "typescript": "^4.9.5 || ^5.4.5",
102
102
  "vitest": "^3.2.4",
103
103
  "wait-port": "^1.1.0",
104
- "@langchain/langgraph": "1.3.3",
104
+ "@langchain/langgraph": "1.3.6",
105
105
  "@langchain/langgraph-checkpoint": "1.0.4",
106
- "@langchain/langgraph-sdk": "1.9.11"
106
+ "@langchain/langgraph-sdk": "1.9.17"
107
107
  },
108
108
  "scripts": {
109
109
  "clean": "rm -rf dist/ .turbo/ ./tests/graphs/.langgraph_api/ ./tests/protocol-v2/graphs/.langgraph_api/",