@anthropic-ai/sdk 0.5.2 → 0.5.4
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 +19 -0
- package/README.md +7 -7
- package/core.d.ts +4 -1
- package/core.d.ts.map +1 -1
- package/core.js +31 -8
- package/core.js.map +1 -1
- package/core.mjs +31 -8
- package/core.mjs.map +1 -1
- package/index.d.mts +7 -0
- package/index.d.ts +7 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/index.mjs +1 -0
- package/index.mjs.map +1 -1
- package/package.json +1 -1
- package/resources/completions.d.ts +14 -92
- package/resources/completions.d.ts.map +1 -1
- package/resources/completions.js.map +1 -1
- package/resources/completions.mjs.map +1 -1
- package/src/_shims/fileFromPath.node.ts +1 -1
- package/src/_shims/fileFromPath.ts +1 -1
- package/src/_shims/getMultipartRequestOptions.node.ts +1 -1
- package/src/_shims/getMultipartRequestOptions.ts +1 -1
- package/src/core.ts +32 -8
- package/src/index.ts +10 -1
- package/src/resources/completions.ts +18 -96
- package/src/streaming.ts +120 -111
- package/src/uploads.ts +10 -9
- package/src/version.ts +1 -1
- package/streaming.d.ts.map +1 -1
- package/streaming.js +92 -84
- package/streaming.js.map +1 -1
- package/streaming.mjs +92 -84
- package/streaming.mjs.map +1 -1
- package/uploads.d.ts +1 -1
- package/uploads.d.ts.map +1 -1
- package/uploads.js +2 -1
- package/uploads.js.map +1 -1
- package/uploads.mjs +2 -1
- package/uploads.mjs.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/version.mjs +1 -1
- package/version.mjs.map +1 -1
package/src/streaming.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Response } from '
|
|
1
|
+
import type { Response } from './_shims/fetch.js';
|
|
2
2
|
|
|
3
3
|
import { APIResponse, Headers, createResponseHeaders } from './core';
|
|
4
4
|
|
|
5
|
-
import { safeJSON } from '
|
|
6
|
-
import { APIError } from '
|
|
5
|
+
import { safeJSON } from './core';
|
|
6
|
+
import { APIError } from './error';
|
|
7
7
|
|
|
8
8
|
type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;
|
|
9
9
|
|
|
@@ -13,61 +13,6 @@ type ServerSentEvent = {
|
|
|
13
13
|
raw: string[];
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
class SSEDecoder {
|
|
17
|
-
private data: string[];
|
|
18
|
-
private event: string | null;
|
|
19
|
-
private chunks: string[];
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
this.event = null;
|
|
23
|
-
this.data = [];
|
|
24
|
-
this.chunks = [];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
decode(line: string) {
|
|
28
|
-
if (line.endsWith('\r')) {
|
|
29
|
-
line = line.substring(0, line.length - 1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (!line) {
|
|
33
|
-
// empty line and we didn't previously encounter any messages
|
|
34
|
-
if (!this.event && !this.data.length) return null;
|
|
35
|
-
|
|
36
|
-
const sse: ServerSentEvent = {
|
|
37
|
-
event: this.event,
|
|
38
|
-
data: this.data.join('\n'),
|
|
39
|
-
raw: this.chunks,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
this.event = null;
|
|
43
|
-
this.data = [];
|
|
44
|
-
this.chunks = [];
|
|
45
|
-
|
|
46
|
-
return sse;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
this.chunks.push(line);
|
|
50
|
-
|
|
51
|
-
if (line.startsWith(':')) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let [fieldname, _, value] = partition(line, ':');
|
|
56
|
-
|
|
57
|
-
if (value.startsWith(' ')) {
|
|
58
|
-
value = value.substring(1);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (fieldname === 'event') {
|
|
62
|
-
this.event = value;
|
|
63
|
-
} else if (fieldname === 'data') {
|
|
64
|
-
this.data.push(value);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
16
|
export class Stream<Item> implements AsyncIterable<Item>, APIResponse<Stream<Item>> {
|
|
72
17
|
/** @deprecated - please use the async iterator instead. We plan to add additional helper methods shortly. */
|
|
73
18
|
response: Response;
|
|
@@ -93,9 +38,7 @@ export class Stream<Item> implements AsyncIterable<Item>, APIResponse<Stream<Ite
|
|
|
93
38
|
|
|
94
39
|
const iter = readableStreamAsyncIterable<Bytes>(this.response.body);
|
|
95
40
|
for await (const chunk of iter) {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
for (const line of lineDecoder.decode(text)) {
|
|
41
|
+
for (const line of lineDecoder.decode(chunk)) {
|
|
99
42
|
const sse = this.decoder.decode(line);
|
|
100
43
|
if (sse) yield sse;
|
|
101
44
|
}
|
|
@@ -143,7 +86,60 @@ export class Stream<Item> implements AsyncIterable<Item>, APIResponse<Stream<Ite
|
|
|
143
86
|
}
|
|
144
87
|
}
|
|
145
88
|
|
|
146
|
-
|
|
89
|
+
class SSEDecoder {
|
|
90
|
+
private data: string[];
|
|
91
|
+
private event: string | null;
|
|
92
|
+
private chunks: string[];
|
|
93
|
+
|
|
94
|
+
constructor() {
|
|
95
|
+
this.event = null;
|
|
96
|
+
this.data = [];
|
|
97
|
+
this.chunks = [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
decode(line: string) {
|
|
101
|
+
if (line.endsWith('\r')) {
|
|
102
|
+
line = line.substring(0, line.length - 1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!line) {
|
|
106
|
+
// empty line and we didn't previously encounter any messages
|
|
107
|
+
if (!this.event && !this.data.length) return null;
|
|
108
|
+
|
|
109
|
+
const sse: ServerSentEvent = {
|
|
110
|
+
event: this.event,
|
|
111
|
+
data: this.data.join('\n'),
|
|
112
|
+
raw: this.chunks,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
this.event = null;
|
|
116
|
+
this.data = [];
|
|
117
|
+
this.chunks = [];
|
|
118
|
+
|
|
119
|
+
return sse;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.chunks.push(line);
|
|
123
|
+
|
|
124
|
+
if (line.startsWith(':')) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let [fieldname, _, value] = partition(line, ':');
|
|
129
|
+
|
|
130
|
+
if (value.startsWith(' ')) {
|
|
131
|
+
value = value.substring(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (fieldname === 'event') {
|
|
135
|
+
this.event = value;
|
|
136
|
+
} else if (fieldname === 'data') {
|
|
137
|
+
this.data.push(value);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
147
143
|
|
|
148
144
|
/**
|
|
149
145
|
* A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
|
|
@@ -152,15 +148,22 @@ const NEWLINE_CHARS = '\n\r\x0b\x0c\x1c\x1d\x1e\x85\u2028\u2029';
|
|
|
152
148
|
* https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
|
|
153
149
|
*/
|
|
154
150
|
class LineDecoder {
|
|
151
|
+
// prettier-ignore
|
|
152
|
+
static NEWLINE_CHARS = new Set(['\n', '\r', '\x0b', '\x0c', '\x1c', '\x1d', '\x1e', '\x85', '\u2028', '\u2029']);
|
|
153
|
+
static NEWLINE_REGEXP = /\r\n|[\n\r\x0b\x0c\x1c\x1d\x1e\x85\u2028\u2029]/g;
|
|
154
|
+
|
|
155
155
|
buffer: string[];
|
|
156
156
|
trailingCR: boolean;
|
|
157
|
+
textDecoder: any; // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
|
|
157
158
|
|
|
158
159
|
constructor() {
|
|
159
160
|
this.buffer = [];
|
|
160
161
|
this.trailingCR = false;
|
|
161
162
|
}
|
|
162
163
|
|
|
163
|
-
decode(
|
|
164
|
+
decode(chunk: Bytes): string[] {
|
|
165
|
+
let text = this.decodeText(chunk);
|
|
166
|
+
|
|
164
167
|
if (this.trailingCR) {
|
|
165
168
|
text = '\r' + text;
|
|
166
169
|
this.trailingCR = false;
|
|
@@ -174,10 +177,10 @@ class LineDecoder {
|
|
|
174
177
|
return [];
|
|
175
178
|
}
|
|
176
179
|
|
|
177
|
-
const
|
|
178
|
-
let lines = text.split(
|
|
180
|
+
const trailingNewline = LineDecoder.NEWLINE_CHARS.has(text[text.length - 1] || '');
|
|
181
|
+
let lines = text.split(LineDecoder.NEWLINE_REGEXP);
|
|
179
182
|
|
|
180
|
-
if (lines.length === 1 && !
|
|
183
|
+
if (lines.length === 1 && !trailingNewline) {
|
|
181
184
|
this.buffer.push(lines[0]!);
|
|
182
185
|
return [];
|
|
183
186
|
}
|
|
@@ -187,13 +190,50 @@ class LineDecoder {
|
|
|
187
190
|
this.buffer = [];
|
|
188
191
|
}
|
|
189
192
|
|
|
190
|
-
if (!
|
|
193
|
+
if (!trailingNewline) {
|
|
191
194
|
this.buffer = [lines.pop() || ''];
|
|
192
195
|
}
|
|
193
196
|
|
|
194
197
|
return lines;
|
|
195
198
|
}
|
|
196
199
|
|
|
200
|
+
decodeText(bytes: Bytes): string {
|
|
201
|
+
if (bytes == null) return '';
|
|
202
|
+
if (typeof bytes === 'string') return bytes;
|
|
203
|
+
|
|
204
|
+
// Node:
|
|
205
|
+
if (typeof Buffer !== 'undefined') {
|
|
206
|
+
if (bytes instanceof Buffer) {
|
|
207
|
+
return bytes.toString();
|
|
208
|
+
}
|
|
209
|
+
if (bytes instanceof Uint8Array) {
|
|
210
|
+
return Buffer.from(bytes).toString();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
throw new Error(
|
|
214
|
+
`Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Browser
|
|
219
|
+
if (typeof TextDecoder !== 'undefined') {
|
|
220
|
+
if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {
|
|
221
|
+
this.textDecoder ??= new TextDecoder('utf8');
|
|
222
|
+
return this.textDecoder.decode(bytes);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
throw new Error(
|
|
226
|
+
`Unexpected: received non-Uint8Array/ArrayBuffer (${
|
|
227
|
+
(bytes as any).constructor.name
|
|
228
|
+
}) in a web platform. Please report this error.`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
throw new Error(
|
|
233
|
+
`Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`,
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
197
237
|
flush(): string[] {
|
|
198
238
|
if (!this.buffer.length && !this.trailingCR) {
|
|
199
239
|
return [];
|
|
@@ -215,62 +255,31 @@ function partition(str: string, delimiter: string): [string, string, string] {
|
|
|
215
255
|
return [str, '', ''];
|
|
216
256
|
}
|
|
217
257
|
|
|
218
|
-
let _textDecoder;
|
|
219
|
-
function decodeText(bytes: Bytes): string {
|
|
220
|
-
if (bytes == null) return '';
|
|
221
|
-
if (typeof bytes === 'string') return bytes;
|
|
222
|
-
|
|
223
|
-
// Node:
|
|
224
|
-
if (typeof Buffer !== 'undefined') {
|
|
225
|
-
if (bytes instanceof Buffer) {
|
|
226
|
-
return bytes.toString();
|
|
227
|
-
}
|
|
228
|
-
if (bytes instanceof Uint8Array) {
|
|
229
|
-
return Buffer.from(bytes).toString();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
throw new Error(`Unexpected: received non-Uint8Array (${bytes.constructor.name}) in Node.`);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Browser
|
|
236
|
-
if (typeof TextDecoder !== 'undefined') {
|
|
237
|
-
if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {
|
|
238
|
-
_textDecoder ??= new TextDecoder('utf8');
|
|
239
|
-
return _textDecoder.decode(bytes);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
throw new Error(
|
|
243
|
-
`Unexpected: received non-Uint8Array/ArrayBuffer (${
|
|
244
|
-
(bytes as any).constructor.name
|
|
245
|
-
}) in a web platform.`,
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
throw new Error(`Unexpected: neither Buffer nor TextDecoder are available as globals.`);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
258
|
/**
|
|
253
259
|
* Most browsers don't yet have async iterable support for ReadableStream,
|
|
254
260
|
* and Node has a very different way of reading bytes from its "ReadableStream".
|
|
255
261
|
*
|
|
256
|
-
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-
|
|
257
|
-
*
|
|
258
|
-
* We make extensive use of "any" here to avoid pulling in either "node" or "dom" types
|
|
259
|
-
* to library users' type scopes.
|
|
262
|
+
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
|
260
263
|
*/
|
|
261
264
|
function readableStreamAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {
|
|
262
|
-
if (stream[Symbol.asyncIterator])
|
|
263
|
-
return stream[Symbol.asyncIterator];
|
|
264
|
-
}
|
|
265
|
+
if (stream[Symbol.asyncIterator]) return stream;
|
|
265
266
|
|
|
266
267
|
const reader = stream.getReader();
|
|
267
|
-
|
|
268
268
|
return {
|
|
269
|
-
next() {
|
|
270
|
-
|
|
269
|
+
async next() {
|
|
270
|
+
try {
|
|
271
|
+
const result = await reader.read();
|
|
272
|
+
if (result?.done) reader.releaseLock(); // release lock when stream becomes closed
|
|
273
|
+
return result;
|
|
274
|
+
} catch (e) {
|
|
275
|
+
reader.releaseLock(); // release lock when stream becomes errored
|
|
276
|
+
throw e;
|
|
277
|
+
}
|
|
271
278
|
},
|
|
272
279
|
async return() {
|
|
280
|
+
const cancelPromise = reader.cancel();
|
|
273
281
|
reader.releaseLock();
|
|
282
|
+
await cancelPromise;
|
|
274
283
|
return { done: true, value: undefined };
|
|
275
284
|
},
|
|
276
285
|
[Symbol.asyncIterator]() {
|
package/src/uploads.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type RequestOptions } from './core';
|
|
2
|
-
import { type Readable } from '
|
|
3
|
-
import { type BodyInit } from '
|
|
4
|
-
import { FormData, File, type FilePropertyBag } from '
|
|
5
|
-
import { getMultipartRequestOptions } from '
|
|
6
|
-
import { fileFromPath } from '
|
|
7
|
-
import { type FsReadStream, isFsReadStream } from '
|
|
2
|
+
import { type Readable } from './_shims/node-readable';
|
|
3
|
+
import { type BodyInit } from './_shims/fetch.js';
|
|
4
|
+
import { FormData, File, type FilePropertyBag } from './_shims/formdata.js';
|
|
5
|
+
import { getMultipartRequestOptions } from './_shims/getMultipartRequestOptions';
|
|
6
|
+
import { fileFromPath } from './_shims/fileFromPath';
|
|
7
|
+
import { type FsReadStream, isFsReadStream } from './_shims/node-readable';
|
|
8
8
|
|
|
9
9
|
export { fileFromPath };
|
|
10
10
|
|
|
@@ -96,7 +96,7 @@ export type ToFileInput = Uploadable | Exclude<BlobPart, string> | AsyncIterable
|
|
|
96
96
|
* @returns a {@link File} with the given properties
|
|
97
97
|
*/
|
|
98
98
|
export async function toFile(
|
|
99
|
-
value: ToFileInput
|
|
99
|
+
value: ToFileInput | PromiseLike<ToFileInput>,
|
|
100
100
|
name?: string | null | undefined,
|
|
101
101
|
options: FilePropertyBag | undefined = {},
|
|
102
102
|
): Promise<FileLike> {
|
|
@@ -121,8 +121,9 @@ export async function toFile(
|
|
|
121
121
|
return new File(bits, name, options);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
async function getBytes(value: ToFileInput): Promise<Array<BlobPart>> {
|
|
125
|
-
|
|
124
|
+
async function getBytes(value: ToFileInput | PromiseLike<ToFileInput>): Promise<Array<BlobPart>> {
|
|
125
|
+
// resolve input promise or promiselike object
|
|
126
|
+
value = await value;
|
|
126
127
|
|
|
127
128
|
let parts: Array<BlobPart> = [];
|
|
128
129
|
if (
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.5.
|
|
1
|
+
export const VERSION = '0.5.4'; // x-release-please-version
|
package/streaming.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["src/streaming.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAyB,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["src/streaming.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAyB,MAAM,QAAQ,CAAC;AAarE,qBAAa,MAAM,CAAC,IAAI,CAAE,YAAW,aAAa,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjF,6GAA6G;IAC7G,QAAQ,EAAE,QAAQ,CAAC;IACnB,+FAA+F;IAC/F,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,eAAe,CAAC;IAE5B,OAAO,CAAC,OAAO,CAAa;gBAEhB,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe;YAO5C,YAAY;IAqBpB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC;CAkCrE"}
|
package/streaming.js
CHANGED
|
@@ -4,45 +4,6 @@ exports.Stream = void 0;
|
|
|
4
4
|
const core_1 = require('./core.js');
|
|
5
5
|
const core_2 = require('@anthropic-ai/sdk/core');
|
|
6
6
|
const error_1 = require('@anthropic-ai/sdk/error');
|
|
7
|
-
class SSEDecoder {
|
|
8
|
-
constructor() {
|
|
9
|
-
this.event = null;
|
|
10
|
-
this.data = [];
|
|
11
|
-
this.chunks = [];
|
|
12
|
-
}
|
|
13
|
-
decode(line) {
|
|
14
|
-
if (line.endsWith('\r')) {
|
|
15
|
-
line = line.substring(0, line.length - 1);
|
|
16
|
-
}
|
|
17
|
-
if (!line) {
|
|
18
|
-
// empty line and we didn't previously encounter any messages
|
|
19
|
-
if (!this.event && !this.data.length) return null;
|
|
20
|
-
const sse = {
|
|
21
|
-
event: this.event,
|
|
22
|
-
data: this.data.join('\n'),
|
|
23
|
-
raw: this.chunks,
|
|
24
|
-
};
|
|
25
|
-
this.event = null;
|
|
26
|
-
this.data = [];
|
|
27
|
-
this.chunks = [];
|
|
28
|
-
return sse;
|
|
29
|
-
}
|
|
30
|
-
this.chunks.push(line);
|
|
31
|
-
if (line.startsWith(':')) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
let [fieldname, _, value] = partition(line, ':');
|
|
35
|
-
if (value.startsWith(' ')) {
|
|
36
|
-
value = value.substring(1);
|
|
37
|
-
}
|
|
38
|
-
if (fieldname === 'event') {
|
|
39
|
-
this.event = value;
|
|
40
|
-
} else if (fieldname === 'data') {
|
|
41
|
-
this.data.push(value);
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
7
|
class Stream {
|
|
47
8
|
constructor(response, controller) {
|
|
48
9
|
this.response = response;
|
|
@@ -58,8 +19,7 @@ class Stream {
|
|
|
58
19
|
const lineDecoder = new LineDecoder();
|
|
59
20
|
const iter = readableStreamAsyncIterable(this.response.body);
|
|
60
21
|
for await (const chunk of iter) {
|
|
61
|
-
const
|
|
62
|
-
for (const line of lineDecoder.decode(text)) {
|
|
22
|
+
for (const line of lineDecoder.decode(chunk)) {
|
|
63
23
|
const sse = this.decoder.decode(line);
|
|
64
24
|
if (sse) yield sse;
|
|
65
25
|
}
|
|
@@ -102,7 +62,45 @@ class Stream {
|
|
|
102
62
|
}
|
|
103
63
|
}
|
|
104
64
|
exports.Stream = Stream;
|
|
105
|
-
|
|
65
|
+
class SSEDecoder {
|
|
66
|
+
constructor() {
|
|
67
|
+
this.event = null;
|
|
68
|
+
this.data = [];
|
|
69
|
+
this.chunks = [];
|
|
70
|
+
}
|
|
71
|
+
decode(line) {
|
|
72
|
+
if (line.endsWith('\r')) {
|
|
73
|
+
line = line.substring(0, line.length - 1);
|
|
74
|
+
}
|
|
75
|
+
if (!line) {
|
|
76
|
+
// empty line and we didn't previously encounter any messages
|
|
77
|
+
if (!this.event && !this.data.length) return null;
|
|
78
|
+
const sse = {
|
|
79
|
+
event: this.event,
|
|
80
|
+
data: this.data.join('\n'),
|
|
81
|
+
raw: this.chunks,
|
|
82
|
+
};
|
|
83
|
+
this.event = null;
|
|
84
|
+
this.data = [];
|
|
85
|
+
this.chunks = [];
|
|
86
|
+
return sse;
|
|
87
|
+
}
|
|
88
|
+
this.chunks.push(line);
|
|
89
|
+
if (line.startsWith(':')) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
let [fieldname, _, value] = partition(line, ':');
|
|
93
|
+
if (value.startsWith(' ')) {
|
|
94
|
+
value = value.substring(1);
|
|
95
|
+
}
|
|
96
|
+
if (fieldname === 'event') {
|
|
97
|
+
this.event = value;
|
|
98
|
+
} else if (fieldname === 'data') {
|
|
99
|
+
this.data.push(value);
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
106
104
|
/**
|
|
107
105
|
* A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
|
|
108
106
|
* reading lines from text.
|
|
@@ -114,7 +112,8 @@ class LineDecoder {
|
|
|
114
112
|
this.buffer = [];
|
|
115
113
|
this.trailingCR = false;
|
|
116
114
|
}
|
|
117
|
-
decode(
|
|
115
|
+
decode(chunk) {
|
|
116
|
+
let text = this.decodeText(chunk);
|
|
118
117
|
if (this.trailingCR) {
|
|
119
118
|
text = '\r' + text;
|
|
120
119
|
this.trailingCR = false;
|
|
@@ -126,9 +125,9 @@ class LineDecoder {
|
|
|
126
125
|
if (!text) {
|
|
127
126
|
return [];
|
|
128
127
|
}
|
|
129
|
-
const
|
|
130
|
-
let lines = text.split(
|
|
131
|
-
if (lines.length === 1 && !
|
|
128
|
+
const trailingNewline = LineDecoder.NEWLINE_CHARS.has(text[text.length - 1] || '');
|
|
129
|
+
let lines = text.split(LineDecoder.NEWLINE_REGEXP);
|
|
130
|
+
if (lines.length === 1 && !trailingNewline) {
|
|
132
131
|
this.buffer.push(lines[0]);
|
|
133
132
|
return [];
|
|
134
133
|
}
|
|
@@ -136,11 +135,41 @@ class LineDecoder {
|
|
|
136
135
|
lines = [this.buffer.join('') + lines[0], ...lines.slice(1)];
|
|
137
136
|
this.buffer = [];
|
|
138
137
|
}
|
|
139
|
-
if (!
|
|
138
|
+
if (!trailingNewline) {
|
|
140
139
|
this.buffer = [lines.pop() || ''];
|
|
141
140
|
}
|
|
142
141
|
return lines;
|
|
143
142
|
}
|
|
143
|
+
decodeText(bytes) {
|
|
144
|
+
var _a;
|
|
145
|
+
if (bytes == null) return '';
|
|
146
|
+
if (typeof bytes === 'string') return bytes;
|
|
147
|
+
// Node:
|
|
148
|
+
if (typeof Buffer !== 'undefined') {
|
|
149
|
+
if (bytes instanceof Buffer) {
|
|
150
|
+
return bytes.toString();
|
|
151
|
+
}
|
|
152
|
+
if (bytes instanceof Uint8Array) {
|
|
153
|
+
return Buffer.from(bytes).toString();
|
|
154
|
+
}
|
|
155
|
+
throw new Error(
|
|
156
|
+
`Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
// Browser
|
|
160
|
+
if (typeof TextDecoder !== 'undefined') {
|
|
161
|
+
if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {
|
|
162
|
+
(_a = this.textDecoder) !== null && _a !== void 0 ? _a : (this.textDecoder = new TextDecoder('utf8'));
|
|
163
|
+
return this.textDecoder.decode(bytes);
|
|
164
|
+
}
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Unexpected: received non-Uint8Array/ArrayBuffer (${bytes.constructor.name}) in a web platform. Please report this error.`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
144
173
|
flush() {
|
|
145
174
|
if (!this.buffer.length && !this.trailingCR) {
|
|
146
175
|
return [];
|
|
@@ -151,6 +180,9 @@ class LineDecoder {
|
|
|
151
180
|
return lines;
|
|
152
181
|
}
|
|
153
182
|
}
|
|
183
|
+
// prettier-ignore
|
|
184
|
+
LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r', '\x0b', '\x0c', '\x1c', '\x1d', '\x1e', '\x85', '\u2028', '\u2029']);
|
|
185
|
+
LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r\x0b\x0c\x1c\x1d\x1e\x85\u2028\u2029]/g;
|
|
154
186
|
function partition(str, delimiter) {
|
|
155
187
|
const index = str.indexOf(delimiter);
|
|
156
188
|
if (index !== -1) {
|
|
@@ -158,54 +190,30 @@ function partition(str, delimiter) {
|
|
|
158
190
|
}
|
|
159
191
|
return [str, '', ''];
|
|
160
192
|
}
|
|
161
|
-
let _textDecoder;
|
|
162
|
-
function decodeText(bytes) {
|
|
163
|
-
if (bytes == null) return '';
|
|
164
|
-
if (typeof bytes === 'string') return bytes;
|
|
165
|
-
// Node:
|
|
166
|
-
if (typeof Buffer !== 'undefined') {
|
|
167
|
-
if (bytes instanceof Buffer) {
|
|
168
|
-
return bytes.toString();
|
|
169
|
-
}
|
|
170
|
-
if (bytes instanceof Uint8Array) {
|
|
171
|
-
return Buffer.from(bytes).toString();
|
|
172
|
-
}
|
|
173
|
-
throw new Error(`Unexpected: received non-Uint8Array (${bytes.constructor.name}) in Node.`);
|
|
174
|
-
}
|
|
175
|
-
// Browser
|
|
176
|
-
if (typeof TextDecoder !== 'undefined') {
|
|
177
|
-
if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {
|
|
178
|
-
_textDecoder !== null && _textDecoder !== void 0 ?
|
|
179
|
-
_textDecoder
|
|
180
|
-
: (_textDecoder = new TextDecoder('utf8'));
|
|
181
|
-
return _textDecoder.decode(bytes);
|
|
182
|
-
}
|
|
183
|
-
throw new Error(
|
|
184
|
-
`Unexpected: received non-Uint8Array/ArrayBuffer (${bytes.constructor.name}) in a web platform.`,
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
throw new Error(`Unexpected: neither Buffer nor TextDecoder are available as globals.`);
|
|
188
|
-
}
|
|
189
193
|
/**
|
|
190
194
|
* Most browsers don't yet have async iterable support for ReadableStream,
|
|
191
195
|
* and Node has a very different way of reading bytes from its "ReadableStream".
|
|
192
196
|
*
|
|
193
|
-
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-
|
|
194
|
-
*
|
|
195
|
-
* We make extensive use of "any" here to avoid pulling in either "node" or "dom" types
|
|
196
|
-
* to library users' type scopes.
|
|
197
|
+
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
|
197
198
|
*/
|
|
198
199
|
function readableStreamAsyncIterable(stream) {
|
|
199
|
-
if (stream[Symbol.asyncIterator])
|
|
200
|
-
return stream[Symbol.asyncIterator];
|
|
201
|
-
}
|
|
200
|
+
if (stream[Symbol.asyncIterator]) return stream;
|
|
202
201
|
const reader = stream.getReader();
|
|
203
202
|
return {
|
|
204
|
-
next() {
|
|
205
|
-
|
|
203
|
+
async next() {
|
|
204
|
+
try {
|
|
205
|
+
const result = await reader.read();
|
|
206
|
+
if (result === null || result === void 0 ? void 0 : result.done) reader.releaseLock(); // release lock when stream becomes closed
|
|
207
|
+
return result;
|
|
208
|
+
} catch (e) {
|
|
209
|
+
reader.releaseLock(); // release lock when stream becomes errored
|
|
210
|
+
throw e;
|
|
211
|
+
}
|
|
206
212
|
},
|
|
207
213
|
async return() {
|
|
214
|
+
const cancelPromise = reader.cancel();
|
|
208
215
|
reader.releaseLock();
|
|
216
|
+
await cancelPromise;
|
|
209
217
|
return { done: true, value: undefined };
|
|
210
218
|
},
|
|
211
219
|
[Symbol.asyncIterator]() {
|
package/streaming.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["src/streaming.ts"],"names":[],"mappings":";;;AAEA,oCAAqE;AAErE,iDAAkD;AAClD,mDAAmD;AAUnD,
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["src/streaming.ts"],"names":[],"mappings":"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"}
|