@ai-sdk/langchain 2.0.254 → 2.0.256

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @ai-sdk/langchain
2
2
 
3
+ ## 2.0.256
4
+
5
+ ### Patch Changes
6
+
7
+ - 5995d53: Preserve LangGraph subgraph namespaces and step lifecycles without letting concurrent namespace counters split active text or reasoning streams.
8
+ - Updated dependencies [2171d15]
9
+ - ai@6.0.248
10
+
11
+ ## 2.0.255
12
+
13
+ ### Patch Changes
14
+
15
+ - ai@6.0.247
16
+
3
17
  ## 2.0.254
4
18
 
5
19
  ### Patch Changes
package/dist/index.js CHANGED
@@ -34,7 +34,77 @@ var import_ai = require("ai");
34
34
  // src/utils.ts
35
35
  var import_messages = require("@langchain/core/messages");
36
36
  function parseLangGraphEvent(event) {
37
- return event.length === 3 ? [event[1], event[2]] : [event[0], event[1]];
37
+ return event.length === 3 ? [event[0], event[1], event[2]] : [void 0, event[0], event[1]];
38
+ }
39
+ function getLangGraphProviderMetadata(namespace) {
40
+ return namespace === void 0 ? void 0 : {
41
+ langchain: {
42
+ namespace
43
+ }
44
+ };
45
+ }
46
+ function addLangGraphNamespace(chunk, namespace) {
47
+ var _a;
48
+ if (namespace === void 0) {
49
+ return chunk;
50
+ }
51
+ switch (chunk.type) {
52
+ case "text-start":
53
+ case "text-delta":
54
+ case "text-end":
55
+ case "reasoning-start":
56
+ case "reasoning-delta":
57
+ case "reasoning-end":
58
+ case "tool-input-start":
59
+ case "tool-input-available":
60
+ case "tool-input-error":
61
+ case "tool-output-available":
62
+ case "tool-output-error":
63
+ case "source-url":
64
+ case "source-document":
65
+ case "file": {
66
+ return {
67
+ ...chunk,
68
+ providerMetadata: {
69
+ ...chunk.providerMetadata,
70
+ langchain: {
71
+ ...(_a = chunk.providerMetadata) == null ? void 0 : _a.langchain,
72
+ namespace
73
+ }
74
+ }
75
+ };
76
+ }
77
+ default:
78
+ return chunk;
79
+ }
80
+ }
81
+ function createLangGraphNamespaceController(controller, state, eventNamespace) {
82
+ return {
83
+ get desiredSize() {
84
+ return controller.desiredSize;
85
+ },
86
+ close: () => controller.close(),
87
+ error: (reason) => controller.error(reason),
88
+ enqueue: (chunk) => {
89
+ if (chunk === void 0) {
90
+ return;
91
+ }
92
+ let messageNamespace;
93
+ switch (chunk.type) {
94
+ case "text-start":
95
+ case "text-delta":
96
+ case "text-end":
97
+ case "reasoning-start":
98
+ case "reasoning-delta":
99
+ case "reasoning-end":
100
+ messageNamespace = state.messageNamespaces.get(chunk.id);
101
+ break;
102
+ }
103
+ controller.enqueue(
104
+ addLangGraphNamespace(chunk, messageNamespace != null ? messageNamespace : eventNamespace)
105
+ );
106
+ }
107
+ };
38
108
  }
39
109
  function convertToolResultPart(block) {
40
110
  const content = (() => {
@@ -542,6 +612,34 @@ function getOrCreateToolCallInfoByIndex(toolCallInfoByIndex, msgId) {
542
612
  }
543
613
  return toolCallInfo;
544
614
  }
615
+ function getLangGraphNamespaceKey(namespace) {
616
+ return JSON.stringify(namespace != null ? namespace : []);
617
+ }
618
+ function closeStepNamespaceMessages(state, stepNamespace, controller) {
619
+ let hasConcurrentMessageParts = false;
620
+ for (const [id, seen] of state.messageSeen) {
621
+ const messageNamespace = getLangGraphNamespaceKey(
622
+ state.messageNamespaces.get(id)
623
+ );
624
+ if (messageNamespace !== stepNamespace) {
625
+ if (seen.text || seen.reasoning) {
626
+ hasConcurrentMessageParts = true;
627
+ }
628
+ continue;
629
+ }
630
+ if (seen.text) {
631
+ controller.enqueue({ type: "text-end", id });
632
+ }
633
+ if (seen.reasoning) {
634
+ controller.enqueue({ type: "reasoning-end", id });
635
+ }
636
+ state.messageSeen.delete(id);
637
+ state.messageNamespaces.delete(id);
638
+ state.messageConcat.delete(id);
639
+ state.messageReasoningIds.delete(id);
640
+ }
641
+ return hasConcurrentMessageParts;
642
+ }
545
643
  function processLangGraphEvent(event, state, controller) {
546
644
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
547
645
  const {
@@ -554,7 +652,9 @@ function processLangGraphEvent(event, state, controller) {
554
652
  toolCallInfoByIndex,
555
653
  emittedToolCallsByKey
556
654
  } = state;
557
- const [type, data] = parseLangGraphEvent(event);
655
+ const [rawNamespace, type, data] = parseLangGraphEvent(event);
656
+ const namespace = Array.isArray(rawNamespace) && rawNamespace.every((segment) => typeof segment === "string") ? rawNamespace : void 0;
657
+ controller = createLangGraphNamespaceController(controller, state, namespace);
558
658
  switch (type) {
559
659
  case "custom": {
560
660
  let customTypeName = "custom";
@@ -581,23 +681,28 @@ function processLangGraphEvent(event, state, controller) {
581
681
  const msg = rawMsg;
582
682
  const msgId = getMessageId(msg);
583
683
  if (!msgId) return;
684
+ if (namespace !== void 0) {
685
+ state.messageNamespaces.set(msgId, namespace);
686
+ }
584
687
  const langgraphStep = typeof (metadata == null ? void 0 : metadata.langgraph_step) === "number" ? metadata.langgraph_step : null;
585
- if (langgraphStep !== null && langgraphStep !== state.currentStep) {
688
+ const eventNamespace = getLangGraphNamespaceKey(namespace);
689
+ if (langgraphStep !== null && state.stepNamespace === null) {
690
+ state.stepNamespace = eventNamespace;
691
+ }
692
+ if (langgraphStep !== null && eventNamespace === state.stepNamespace && langgraphStep !== state.currentStep) {
586
693
  if (state.currentStep !== null) {
587
- for (const [id, seen] of messageSeen) {
588
- if (seen.text) {
589
- controller.enqueue({ type: "text-end", id });
590
- }
591
- if (seen.reasoning) {
592
- controller.enqueue({ type: "reasoning-end", id });
593
- }
594
- messageSeen.delete(id);
595
- messageConcat.delete(id);
596
- messageReasoningIds.delete(id);
694
+ const hasConcurrentMessageParts = closeStepNamespaceMessages(
695
+ state,
696
+ state.stepNamespace,
697
+ controller
698
+ );
699
+ if (!hasConcurrentMessageParts) {
700
+ controller.enqueue({ type: "finish-step" });
701
+ controller.enqueue({ type: "start-step" });
597
702
  }
598
- controller.enqueue({ type: "finish-step" });
703
+ } else {
704
+ controller.enqueue({ type: "start-step" });
599
705
  }
600
- controller.enqueue({ type: "start-step" });
601
706
  state.currentStep = langgraphStep;
602
707
  }
603
708
  if (import_messages.AIMessageChunk.isInstance(msg)) {
@@ -770,6 +875,7 @@ function processLangGraphEvent(event, state, controller) {
770
875
  controller.enqueue({ type: "reasoning-end", id });
771
876
  }
772
877
  messageSeen.delete(id);
878
+ state.messageNamespaces.delete(id);
773
879
  messageConcat.delete(id);
774
880
  messageReasoningIds.delete(id);
775
881
  }
@@ -1105,6 +1211,7 @@ function toUIMessageStream(stream, callbacks) {
1105
1211
  };
1106
1212
  const langGraphState = {
1107
1213
  messageSeen: /* @__PURE__ */ new Map(),
1214
+ messageNamespaces: /* @__PURE__ */ new Map(),
1108
1215
  messageConcat: /* @__PURE__ */ new Map(),
1109
1216
  emittedToolCalls: /* @__PURE__ */ new Set(),
1110
1217
  emittedImages: /* @__PURE__ */ new Set(),
@@ -1112,6 +1219,7 @@ function toUIMessageStream(stream, callbacks) {
1112
1219
  messageReasoningIds: /* @__PURE__ */ new Map(),
1113
1220
  toolCallInfoByIndex: /* @__PURE__ */ new Map(),
1114
1221
  currentStep: null,
1222
+ stepNamespace: null,
1115
1223
  emittedToolCallsByKey: /* @__PURE__ */ new Map(),
1116
1224
  emittedSourceIds: /* @__PURE__ */ new Set()
1117
1225
  };
@@ -1180,7 +1288,7 @@ function toUIMessageStream(stream, callbacks) {
1180
1288
  );
1181
1289
  } else {
1182
1290
  const eventArray = value;
1183
- const [type, data] = parseLangGraphEvent(eventArray);
1291
+ const [, type, data] = parseLangGraphEvent(eventArray);
1184
1292
  if (type === "values") {
1185
1293
  lastValuesData = data;
1186
1294
  }
@@ -1207,11 +1315,22 @@ function toUIMessageStream(stream, callbacks) {
1207
1315
  controller.enqueue({ type: "finish" });
1208
1316
  } else if (streamType === "langgraph") {
1209
1317
  for (const [id, seen] of langGraphState.messageSeen) {
1318
+ const providerMetadata = getLangGraphProviderMetadata(
1319
+ langGraphState.messageNamespaces.get(id)
1320
+ );
1210
1321
  if (seen.text) {
1211
- controller.enqueue({ type: "text-end", id });
1322
+ controller.enqueue({
1323
+ type: "text-end",
1324
+ id,
1325
+ ...providerMetadata !== void 0 && { providerMetadata }
1326
+ });
1212
1327
  }
1213
1328
  if (seen.reasoning) {
1214
- controller.enqueue({ type: "reasoning-end", id });
1329
+ controller.enqueue({
1330
+ type: "reasoning-end",
1331
+ id,
1332
+ ...providerMetadata !== void 0 && { providerMetadata }
1333
+ });
1215
1334
  }
1216
1335
  }
1217
1336
  if (langGraphState.currentStep !== null) {