@langchain/langgraph-sdk 0.0.39 → 0.0.40

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.
@@ -1,12 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SSEDecoder = exports.BytesLineDecoder = void 0;
4
- const mergeArrays = (a, b) => {
5
- const mergedArray = new Uint8Array(a.length + b.length);
6
- mergedArray.set(a);
7
- mergedArray.set(b, a.length);
8
- return mergedArray;
9
- };
10
4
  const CR = "\r".charCodeAt(0);
11
5
  const LF = "\n".charCodeAt(0);
12
6
  const NULL = "\0".charCodeAt(0);
@@ -15,11 +9,11 @@ const SPACE = " ".charCodeAt(0);
15
9
  const TRAILING_NEWLINE = [CR, LF];
16
10
  class BytesLineDecoder extends TransformStream {
17
11
  constructor() {
18
- let buffer = new Uint8Array();
12
+ let buffer = [];
19
13
  let trailingCr = false;
20
14
  super({
21
15
  start() {
22
- buffer = new Uint8Array();
16
+ buffer = [];
23
17
  trailingCr = false;
24
18
  },
25
19
  transform(chunk, controller) {
@@ -27,7 +21,7 @@ class BytesLineDecoder extends TransformStream {
27
21
  let text = chunk;
28
22
  // Handle trailing CR from previous chunk
29
23
  if (trailingCr) {
30
- text = mergeArrays([CR], text);
24
+ text = joinArrays([[CR], text]);
31
25
  trailingCr = false;
32
26
  }
33
27
  // Check for trailing CR in current chunk
@@ -38,40 +32,39 @@ class BytesLineDecoder extends TransformStream {
38
32
  if (!text.length)
39
33
  return;
40
34
  const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1));
41
- // Pre-allocate lines array with estimated capacity
42
- let lines = [];
43
- for (let offset = 0; offset < text.byteLength;) {
44
- let idx = text.indexOf(CR, offset);
45
- if (idx === -1)
46
- idx = text.indexOf(LF, offset);
47
- if (idx === -1) {
48
- lines.push(text.subarray(offset));
49
- break;
35
+ const lastIdx = text.length - 1;
36
+ const { lines } = text.reduce((acc, cur, idx) => {
37
+ if (acc.from > idx)
38
+ return acc;
39
+ if (cur === CR || cur === LF) {
40
+ acc.lines.push(text.subarray(acc.from, idx));
41
+ if (cur === CR && text[idx + 1] === LF) {
42
+ acc.from = idx + 2;
43
+ }
44
+ else {
45
+ acc.from = idx + 1;
46
+ }
50
47
  }
51
- lines.push(text.subarray(offset, idx));
52
- if (text[idx] === CR && text[idx + 1] === LF) {
53
- offset = idx + 2;
48
+ if (idx === lastIdx && acc.from <= lastIdx) {
49
+ acc.lines.push(text.subarray(acc.from));
54
50
  }
55
- else {
56
- offset = idx + 1;
57
- }
58
- }
51
+ return acc;
52
+ }, { lines: [], from: 0 });
59
53
  if (lines.length === 1 && !trailingNewline) {
60
- buffer = mergeArrays(buffer, lines[0]);
54
+ buffer.push(lines[0]);
61
55
  return;
62
56
  }
63
57
  if (buffer.length) {
64
58
  // Include existing buffer in first line
65
- buffer = mergeArrays(buffer, lines[0]);
66
- lines = lines.slice(1);
67
- lines.unshift(buffer);
68
- buffer = new Uint8Array();
59
+ buffer.push(lines[0]);
60
+ lines[0] = joinArrays(buffer);
61
+ buffer = [];
69
62
  }
70
63
  if (!trailingNewline) {
71
64
  // If the last segment is not newline terminated,
72
65
  // buffer it for the next chunk
73
66
  if (lines.length)
74
- buffer = lines.pop();
67
+ buffer = [lines.pop()];
75
68
  }
76
69
  // Enqueue complete lines
77
70
  for (const line of lines) {
@@ -80,7 +73,7 @@ class BytesLineDecoder extends TransformStream {
80
73
  },
81
74
  flush(controller) {
82
75
  if (buffer.length) {
83
- controller.enqueue(buffer);
76
+ controller.enqueue(joinArrays(buffer));
84
77
  }
85
78
  },
86
79
  });
@@ -90,7 +83,7 @@ exports.BytesLineDecoder = BytesLineDecoder;
90
83
  class SSEDecoder extends TransformStream {
91
84
  constructor() {
92
85
  let event = "";
93
- let data = new Uint8Array();
86
+ let data = [];
94
87
  let lastEventId = "";
95
88
  let retry = null;
96
89
  const decoder = new TextDecoder();
@@ -102,11 +95,11 @@ class SSEDecoder extends TransformStream {
102
95
  return;
103
96
  const sse = {
104
97
  event,
105
- data: data.length ? JSON.parse(decoder.decode(data)) : null,
98
+ data: data.length ? decodeArraysToJson(decoder, data) : null,
106
99
  };
107
100
  // NOTE: as per the SSE spec, do not reset lastEventId
108
101
  event = "";
109
- data = new Uint8Array();
102
+ data = [];
110
103
  retry = null;
111
104
  controller.enqueue(sse);
112
105
  return;
@@ -125,7 +118,7 @@ class SSEDecoder extends TransformStream {
125
118
  event = decoder.decode(value);
126
119
  }
127
120
  else if (fieldName === "data") {
128
- data = mergeArrays(data, value);
121
+ data.push(value);
129
122
  }
130
123
  else if (fieldName === "id") {
131
124
  if (value.indexOf(NULL) === -1)
@@ -141,7 +134,7 @@ class SSEDecoder extends TransformStream {
141
134
  if (event) {
142
135
  controller.enqueue({
143
136
  event,
144
- data: data.length ? JSON.parse(decoder.decode(data)) : null,
137
+ data: data.length ? decodeArraysToJson(decoder, data) : null,
145
138
  });
146
139
  }
147
140
  },
@@ -149,3 +142,16 @@ class SSEDecoder extends TransformStream {
149
142
  }
150
143
  }
151
144
  exports.SSEDecoder = SSEDecoder;
145
+ function joinArrays(data) {
146
+ const totalLength = data.reduce((acc, curr) => acc + curr.length, 0);
147
+ let merged = new Uint8Array(totalLength);
148
+ let offset = 0;
149
+ for (const c of data) {
150
+ merged.set(c, offset);
151
+ offset += c.length;
152
+ }
153
+ return merged;
154
+ }
155
+ function decodeArraysToJson(decoder, data) {
156
+ return JSON.parse(decoder.decode(joinArrays(data)));
157
+ }
package/dist/utils/sse.js CHANGED
@@ -1,9 +1,3 @@
1
- const mergeArrays = (a, b) => {
2
- const mergedArray = new Uint8Array(a.length + b.length);
3
- mergedArray.set(a);
4
- mergedArray.set(b, a.length);
5
- return mergedArray;
6
- };
7
1
  const CR = "\r".charCodeAt(0);
8
2
  const LF = "\n".charCodeAt(0);
9
3
  const NULL = "\0".charCodeAt(0);
@@ -12,11 +6,11 @@ const SPACE = " ".charCodeAt(0);
12
6
  const TRAILING_NEWLINE = [CR, LF];
13
7
  export class BytesLineDecoder extends TransformStream {
14
8
  constructor() {
15
- let buffer = new Uint8Array();
9
+ let buffer = [];
16
10
  let trailingCr = false;
17
11
  super({
18
12
  start() {
19
- buffer = new Uint8Array();
13
+ buffer = [];
20
14
  trailingCr = false;
21
15
  },
22
16
  transform(chunk, controller) {
@@ -24,7 +18,7 @@ export class BytesLineDecoder extends TransformStream {
24
18
  let text = chunk;
25
19
  // Handle trailing CR from previous chunk
26
20
  if (trailingCr) {
27
- text = mergeArrays([CR], text);
21
+ text = joinArrays([[CR], text]);
28
22
  trailingCr = false;
29
23
  }
30
24
  // Check for trailing CR in current chunk
@@ -35,40 +29,39 @@ export class BytesLineDecoder extends TransformStream {
35
29
  if (!text.length)
36
30
  return;
37
31
  const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1));
38
- // Pre-allocate lines array with estimated capacity
39
- let lines = [];
40
- for (let offset = 0; offset < text.byteLength;) {
41
- let idx = text.indexOf(CR, offset);
42
- if (idx === -1)
43
- idx = text.indexOf(LF, offset);
44
- if (idx === -1) {
45
- lines.push(text.subarray(offset));
46
- break;
32
+ const lastIdx = text.length - 1;
33
+ const { lines } = text.reduce((acc, cur, idx) => {
34
+ if (acc.from > idx)
35
+ return acc;
36
+ if (cur === CR || cur === LF) {
37
+ acc.lines.push(text.subarray(acc.from, idx));
38
+ if (cur === CR && text[idx + 1] === LF) {
39
+ acc.from = idx + 2;
40
+ }
41
+ else {
42
+ acc.from = idx + 1;
43
+ }
47
44
  }
48
- lines.push(text.subarray(offset, idx));
49
- if (text[idx] === CR && text[idx + 1] === LF) {
50
- offset = idx + 2;
45
+ if (idx === lastIdx && acc.from <= lastIdx) {
46
+ acc.lines.push(text.subarray(acc.from));
51
47
  }
52
- else {
53
- offset = idx + 1;
54
- }
55
- }
48
+ return acc;
49
+ }, { lines: [], from: 0 });
56
50
  if (lines.length === 1 && !trailingNewline) {
57
- buffer = mergeArrays(buffer, lines[0]);
51
+ buffer.push(lines[0]);
58
52
  return;
59
53
  }
60
54
  if (buffer.length) {
61
55
  // Include existing buffer in first line
62
- buffer = mergeArrays(buffer, lines[0]);
63
- lines = lines.slice(1);
64
- lines.unshift(buffer);
65
- buffer = new Uint8Array();
56
+ buffer.push(lines[0]);
57
+ lines[0] = joinArrays(buffer);
58
+ buffer = [];
66
59
  }
67
60
  if (!trailingNewline) {
68
61
  // If the last segment is not newline terminated,
69
62
  // buffer it for the next chunk
70
63
  if (lines.length)
71
- buffer = lines.pop();
64
+ buffer = [lines.pop()];
72
65
  }
73
66
  // Enqueue complete lines
74
67
  for (const line of lines) {
@@ -77,7 +70,7 @@ export class BytesLineDecoder extends TransformStream {
77
70
  },
78
71
  flush(controller) {
79
72
  if (buffer.length) {
80
- controller.enqueue(buffer);
73
+ controller.enqueue(joinArrays(buffer));
81
74
  }
82
75
  },
83
76
  });
@@ -86,7 +79,7 @@ export class BytesLineDecoder extends TransformStream {
86
79
  export class SSEDecoder extends TransformStream {
87
80
  constructor() {
88
81
  let event = "";
89
- let data = new Uint8Array();
82
+ let data = [];
90
83
  let lastEventId = "";
91
84
  let retry = null;
92
85
  const decoder = new TextDecoder();
@@ -98,11 +91,11 @@ export class SSEDecoder extends TransformStream {
98
91
  return;
99
92
  const sse = {
100
93
  event,
101
- data: data.length ? JSON.parse(decoder.decode(data)) : null,
94
+ data: data.length ? decodeArraysToJson(decoder, data) : null,
102
95
  };
103
96
  // NOTE: as per the SSE spec, do not reset lastEventId
104
97
  event = "";
105
- data = new Uint8Array();
98
+ data = [];
106
99
  retry = null;
107
100
  controller.enqueue(sse);
108
101
  return;
@@ -121,7 +114,7 @@ export class SSEDecoder extends TransformStream {
121
114
  event = decoder.decode(value);
122
115
  }
123
116
  else if (fieldName === "data") {
124
- data = mergeArrays(data, value);
117
+ data.push(value);
125
118
  }
126
119
  else if (fieldName === "id") {
127
120
  if (value.indexOf(NULL) === -1)
@@ -137,10 +130,23 @@ export class SSEDecoder extends TransformStream {
137
130
  if (event) {
138
131
  controller.enqueue({
139
132
  event,
140
- data: data.length ? JSON.parse(decoder.decode(data)) : null,
133
+ data: data.length ? decodeArraysToJson(decoder, data) : null,
141
134
  });
142
135
  }
143
136
  },
144
137
  });
145
138
  }
146
139
  }
140
+ function joinArrays(data) {
141
+ const totalLength = data.reduce((acc, curr) => acc + curr.length, 0);
142
+ let merged = new Uint8Array(totalLength);
143
+ let offset = 0;
144
+ for (const c of data) {
145
+ merged.set(c, offset);
146
+ offset += c.length;
147
+ }
148
+ return merged;
149
+ }
150
+ function decodeArraysToJson(decoder, data) {
151
+ return JSON.parse(decoder.decode(joinArrays(data)));
152
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-sdk",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "Client library for interacting with the LangGraph API",
5
5
  "type": "module",
6
6
  "packageManager": "yarn@1.22.19",