ai 2.2.18 → 2.2.20
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/dist/index.d.ts +30 -1
- package/dist/index.js +45 -5
- package/dist/index.mjs +44 -5
- package/package.json +2 -1
- package/prompts/dist/index.d.ts +1 -0
- package/react/dist/index.d.ts +28 -1
- package/react/dist/index.js +146 -97
- package/react/dist/index.mjs +146 -97
- package/solid/dist/index.d.ts +1 -0
- package/solid/dist/index.js +1 -1
- package/solid/dist/index.mjs +1 -1
- package/svelte/dist/index.d.ts +1 -0
- package/svelte/dist/index.js +1 -1
- package/svelte/dist/index.mjs +1 -1
- package/vue/dist/index.d.ts +1 -0
- package/vue/dist/index.js +1 -1
- package/vue/dist/index.mjs +1 -1
package/dist/index.d.ts
CHANGED
@@ -42,6 +42,7 @@ interface Message {
|
|
42
42
|
id: string;
|
43
43
|
createdAt?: Date;
|
44
44
|
content: string;
|
45
|
+
ui?: string | JSX.Element | JSX.Element[] | null | undefined;
|
45
46
|
role: 'system' | 'user' | 'assistant' | 'function';
|
46
47
|
/**
|
47
48
|
* If the message has a role of `function`, the `name` field is the name of the function.
|
@@ -601,4 +602,32 @@ declare const getStreamStringTypeAndValue: (line: string) => {
|
|
601
602
|
*/
|
602
603
|
declare const COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
603
604
|
|
604
|
-
|
605
|
+
/**
|
606
|
+
* This is a naive implementation of the streaming React response API.
|
607
|
+
* Currently, it can carry the original raw content, data payload and a special
|
608
|
+
* UI payload and stream them via "rows" (nested promises).
|
609
|
+
* It must be used inside Server Actions so Flight can encode the React elements.
|
610
|
+
*
|
611
|
+
* It is naive as unlike the StreamingTextResponse, it does not send the diff
|
612
|
+
* between the rows, but flushing the full payload on each row.
|
613
|
+
*/
|
614
|
+
type UINode = string | JSX.Element | JSX.Element[] | null | undefined;
|
615
|
+
type Payload = {
|
616
|
+
ui: UINode | Promise<UINode>;
|
617
|
+
content: string;
|
618
|
+
};
|
619
|
+
type ReactResponseRow = Payload & {
|
620
|
+
next: null | Promise<ReactResponseRow>;
|
621
|
+
};
|
622
|
+
/**
|
623
|
+
* A utility class for streaming React responses.
|
624
|
+
*/
|
625
|
+
declare class experimental_StreamingReactResponse {
|
626
|
+
constructor(res: ReadableStream, options?: {
|
627
|
+
ui?: (message: {
|
628
|
+
content: string;
|
629
|
+
}) => UINode | Promise<UINode>;
|
630
|
+
});
|
631
|
+
}
|
632
|
+
|
633
|
+
export { AIStream, AIStreamCallbacksAndOptions, AIStreamParser, AnthropicStream, COMPLEX_HEADER, ChatRequest, ChatRequestOptions, CohereStream, CompletionUsage, CreateMessage, FunctionCall, FunctionCallHandler, FunctionCallPayload, HuggingFaceStream, JSONValue, LangChainStream, Message, OpenAIStream, OpenAIStreamCallbacks, ReactResponseRow, ReplicateStream, RequestOptions, StreamString, StreamStringPrefixes, StreamingTextResponse, UseChatOptions, UseCompletionOptions, createCallbacksTransformer, createChunkDecoder, createEventStreamTransformer, createStreamDataTransformer, experimental_StreamData, experimental_StreamingReactResponse, getStreamString, getStreamStringTypeAndValue, isStreamStringEqualToType, nanoid, readableFromAsyncIterable, streamToResponse, trimStartOfStreamHelper };
|
package/dist/index.js
CHANGED
@@ -35,6 +35,7 @@ __export(streams_exports, {
|
|
35
35
|
createEventStreamTransformer: () => createEventStreamTransformer,
|
36
36
|
createStreamDataTransformer: () => createStreamDataTransformer,
|
37
37
|
experimental_StreamData: () => experimental_StreamData,
|
38
|
+
experimental_StreamingReactResponse: () => experimental_StreamingReactResponse,
|
38
39
|
getStreamString: () => getStreamString,
|
39
40
|
getStreamStringTypeAndValue: () => getStreamStringTypeAndValue,
|
40
41
|
isStreamStringEqualToType: () => isStreamStringEqualToType,
|
@@ -177,7 +178,7 @@ function createChunkDecoder(complex) {
|
|
177
178
|
};
|
178
179
|
}
|
179
180
|
return function(chunk) {
|
180
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
181
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
181
182
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
182
183
|
};
|
183
184
|
}
|
@@ -231,7 +232,6 @@ var experimental_StreamData = class {
|
|
231
232
|
self.controller = controller;
|
232
233
|
},
|
233
234
|
transform: async (chunk, controller) => {
|
234
|
-
controller.enqueue(chunk);
|
235
235
|
if (self.data.length > 0) {
|
236
236
|
const encodedData = self.encoder.encode(
|
237
237
|
getStreamString("data", JSON.stringify(self.data))
|
@@ -239,6 +239,7 @@ var experimental_StreamData = class {
|
|
239
239
|
self.data = [];
|
240
240
|
controller.enqueue(encodedData);
|
241
241
|
}
|
242
|
+
controller.enqueue(chunk);
|
242
243
|
},
|
243
244
|
async flush(controller) {
|
244
245
|
const warningTimeout = process.env.NODE_ENV === "development" ? setTimeout(() => {
|
@@ -551,9 +552,7 @@ var utf8Decoder = new TextDecoder("utf-8");
|
|
551
552
|
async function processLines(lines, controller) {
|
552
553
|
for (const line of lines) {
|
553
554
|
const { text, is_finished } = JSON.parse(line);
|
554
|
-
if (is_finished
|
555
|
-
controller.close();
|
556
|
-
} else {
|
555
|
+
if (!is_finished) {
|
557
556
|
controller.enqueue(text);
|
558
557
|
}
|
559
558
|
}
|
@@ -713,6 +712,46 @@ async function ReplicateStream(res, cb) {
|
|
713
712
|
createStreamDataTransformer(cb == null ? void 0 : cb.experimental_streamData)
|
714
713
|
);
|
715
714
|
}
|
715
|
+
|
716
|
+
// streams/streaming-react-response.ts
|
717
|
+
var experimental_StreamingReactResponse = class {
|
718
|
+
constructor(res, options) {
|
719
|
+
let resolveFunc = () => {
|
720
|
+
};
|
721
|
+
let next = new Promise((resolve) => {
|
722
|
+
resolveFunc = resolve;
|
723
|
+
});
|
724
|
+
let content = "";
|
725
|
+
const decode = createChunkDecoder();
|
726
|
+
const reader = res.getReader();
|
727
|
+
async function readChunk() {
|
728
|
+
var _a;
|
729
|
+
const { done, value } = await reader.read();
|
730
|
+
if (!done) {
|
731
|
+
content += decode(value);
|
732
|
+
}
|
733
|
+
const ui = ((_a = options == null ? void 0 : options.ui) == null ? void 0 : _a.call(options, { content })) || content;
|
734
|
+
const payload = {
|
735
|
+
ui,
|
736
|
+
content
|
737
|
+
};
|
738
|
+
const resolvePrevious = resolveFunc;
|
739
|
+
const nextRow = done ? null : new Promise((resolve) => {
|
740
|
+
resolveFunc = resolve;
|
741
|
+
});
|
742
|
+
resolvePrevious({
|
743
|
+
next: nextRow,
|
744
|
+
...payload
|
745
|
+
});
|
746
|
+
if (done) {
|
747
|
+
return;
|
748
|
+
}
|
749
|
+
await readChunk();
|
750
|
+
}
|
751
|
+
readChunk();
|
752
|
+
return next;
|
753
|
+
}
|
754
|
+
};
|
716
755
|
// Annotate the CommonJS export names for ESM import in node:
|
717
756
|
0 && (module.exports = {
|
718
757
|
AIStream,
|
@@ -730,6 +769,7 @@ async function ReplicateStream(res, cb) {
|
|
730
769
|
createEventStreamTransformer,
|
731
770
|
createStreamDataTransformer,
|
732
771
|
experimental_StreamData,
|
772
|
+
experimental_StreamingReactResponse,
|
733
773
|
getStreamString,
|
734
774
|
getStreamStringTypeAndValue,
|
735
775
|
isStreamStringEqualToType,
|
package/dist/index.mjs
CHANGED
@@ -132,7 +132,7 @@ function createChunkDecoder(complex) {
|
|
132
132
|
};
|
133
133
|
}
|
134
134
|
return function(chunk) {
|
135
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
135
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
136
136
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
137
137
|
};
|
138
138
|
}
|
@@ -186,7 +186,6 @@ var experimental_StreamData = class {
|
|
186
186
|
self.controller = controller;
|
187
187
|
},
|
188
188
|
transform: async (chunk, controller) => {
|
189
|
-
controller.enqueue(chunk);
|
190
189
|
if (self.data.length > 0) {
|
191
190
|
const encodedData = self.encoder.encode(
|
192
191
|
getStreamString("data", JSON.stringify(self.data))
|
@@ -194,6 +193,7 @@ var experimental_StreamData = class {
|
|
194
193
|
self.data = [];
|
195
194
|
controller.enqueue(encodedData);
|
196
195
|
}
|
196
|
+
controller.enqueue(chunk);
|
197
197
|
},
|
198
198
|
async flush(controller) {
|
199
199
|
const warningTimeout = process.env.NODE_ENV === "development" ? setTimeout(() => {
|
@@ -506,9 +506,7 @@ var utf8Decoder = new TextDecoder("utf-8");
|
|
506
506
|
async function processLines(lines, controller) {
|
507
507
|
for (const line of lines) {
|
508
508
|
const { text, is_finished } = JSON.parse(line);
|
509
|
-
if (is_finished
|
510
|
-
controller.close();
|
511
|
-
} else {
|
509
|
+
if (!is_finished) {
|
512
510
|
controller.enqueue(text);
|
513
511
|
}
|
514
512
|
}
|
@@ -668,6 +666,46 @@ async function ReplicateStream(res, cb) {
|
|
668
666
|
createStreamDataTransformer(cb == null ? void 0 : cb.experimental_streamData)
|
669
667
|
);
|
670
668
|
}
|
669
|
+
|
670
|
+
// streams/streaming-react-response.ts
|
671
|
+
var experimental_StreamingReactResponse = class {
|
672
|
+
constructor(res, options) {
|
673
|
+
let resolveFunc = () => {
|
674
|
+
};
|
675
|
+
let next = new Promise((resolve) => {
|
676
|
+
resolveFunc = resolve;
|
677
|
+
});
|
678
|
+
let content = "";
|
679
|
+
const decode = createChunkDecoder();
|
680
|
+
const reader = res.getReader();
|
681
|
+
async function readChunk() {
|
682
|
+
var _a;
|
683
|
+
const { done, value } = await reader.read();
|
684
|
+
if (!done) {
|
685
|
+
content += decode(value);
|
686
|
+
}
|
687
|
+
const ui = ((_a = options == null ? void 0 : options.ui) == null ? void 0 : _a.call(options, { content })) || content;
|
688
|
+
const payload = {
|
689
|
+
ui,
|
690
|
+
content
|
691
|
+
};
|
692
|
+
const resolvePrevious = resolveFunc;
|
693
|
+
const nextRow = done ? null : new Promise((resolve) => {
|
694
|
+
resolveFunc = resolve;
|
695
|
+
});
|
696
|
+
resolvePrevious({
|
697
|
+
next: nextRow,
|
698
|
+
...payload
|
699
|
+
});
|
700
|
+
if (done) {
|
701
|
+
return;
|
702
|
+
}
|
703
|
+
await readChunk();
|
704
|
+
}
|
705
|
+
readChunk();
|
706
|
+
return next;
|
707
|
+
}
|
708
|
+
};
|
671
709
|
export {
|
672
710
|
AIStream,
|
673
711
|
AnthropicStream,
|
@@ -684,6 +722,7 @@ export {
|
|
684
722
|
createEventStreamTransformer,
|
685
723
|
createStreamDataTransformer,
|
686
724
|
experimental_StreamData,
|
725
|
+
experimental_StreamingReactResponse,
|
687
726
|
getStreamString,
|
688
727
|
getStreamStringTypeAndValue,
|
689
728
|
isStreamStringEqualToType,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ai",
|
3
|
-
"version": "2.2.
|
3
|
+
"version": "2.2.20",
|
4
4
|
"license": "Apache-2.0",
|
5
5
|
"sideEffects": false,
|
6
6
|
"main": "./dist/index.js",
|
@@ -75,6 +75,7 @@
|
|
75
75
|
"@types/react-dom": "^18.2.0",
|
76
76
|
"eslint": "^7.32.0",
|
77
77
|
"jest": "29.2.1",
|
78
|
+
"langchain": "0.0.172",
|
78
79
|
"ts-jest": "29.0.3",
|
79
80
|
"tsup": "^6.7.0",
|
80
81
|
"typescript": "5.1.3",
|
package/prompts/dist/index.d.ts
CHANGED
@@ -18,6 +18,7 @@ interface Message {
|
|
18
18
|
id: string;
|
19
19
|
createdAt?: Date;
|
20
20
|
content: string;
|
21
|
+
ui?: string | JSX.Element | JSX.Element[] | null | undefined;
|
21
22
|
role: 'system' | 'user' | 'assistant' | 'function';
|
22
23
|
/**
|
23
24
|
* If the message has a role of `function`, the `name` field is the name of the function.
|
package/react/dist/index.d.ts
CHANGED
@@ -40,6 +40,7 @@ interface Message {
|
|
40
40
|
id: string;
|
41
41
|
createdAt?: Date;
|
42
42
|
content: string;
|
43
|
+
ui?: string | JSX.Element | JSX.Element[] | null | undefined;
|
43
44
|
role: 'system' | 'user' | 'assistant' | 'function';
|
44
45
|
/**
|
45
46
|
* If the message has a role of `function`, the `name` field is the name of the function.
|
@@ -197,6 +198,27 @@ type UseCompletionOptions = {
|
|
197
198
|
body?: object;
|
198
199
|
};
|
199
200
|
|
201
|
+
/**
|
202
|
+
* This is a naive implementation of the streaming React response API.
|
203
|
+
* Currently, it can carry the original raw content, data payload and a special
|
204
|
+
* UI payload and stream them via "rows" (nested promises).
|
205
|
+
* It must be used inside Server Actions so Flight can encode the React elements.
|
206
|
+
*
|
207
|
+
* It is naive as unlike the StreamingTextResponse, it does not send the diff
|
208
|
+
* between the rows, but flushing the full payload on each row.
|
209
|
+
*/
|
210
|
+
type UINode = string | JSX.Element | JSX.Element[] | null | undefined;
|
211
|
+
/**
|
212
|
+
* A utility class for streaming React responses.
|
213
|
+
*/
|
214
|
+
declare class experimental_StreamingReactResponse {
|
215
|
+
constructor(res: ReadableStream, options?: {
|
216
|
+
ui?: (message: {
|
217
|
+
content: string;
|
218
|
+
}) => UINode | Promise<UINode>;
|
219
|
+
});
|
220
|
+
}
|
221
|
+
|
200
222
|
type UseChatHelpers = {
|
201
223
|
/** Current messages in the chat */
|
202
224
|
messages: Message[];
|
@@ -239,7 +261,12 @@ type UseChatHelpers = {
|
|
239
261
|
/** Additional data added on the server via StreamData */
|
240
262
|
data?: any;
|
241
263
|
};
|
242
|
-
|
264
|
+
type StreamingReactResponseAction = (payload: {
|
265
|
+
messages: Message[];
|
266
|
+
}) => Promise<experimental_StreamingReactResponse>;
|
267
|
+
declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, onResponse, onFinish, onError, credentials, headers, body, }?: Omit<UseChatOptions, 'api'> & {
|
268
|
+
api?: string | StreamingReactResponseAction;
|
269
|
+
}): UseChatHelpers;
|
243
270
|
|
244
271
|
type UseCompletionHelpers = {
|
245
272
|
/** The current completion result */
|
package/react/dist/index.js
CHANGED
@@ -56,7 +56,7 @@ function createChunkDecoder(complex) {
|
|
56
56
|
};
|
57
57
|
}
|
58
58
|
return function(chunk) {
|
59
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
59
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
60
60
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
61
61
|
};
|
62
62
|
}
|
@@ -86,24 +86,151 @@ var getStreamStringTypeAndValue = (line) => {
|
|
86
86
|
};
|
87
87
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
88
88
|
|
89
|
+
// react/parseComplexResponse.ts
|
90
|
+
async function parseComplexResponse({
|
91
|
+
reader,
|
92
|
+
abortControllerRef,
|
93
|
+
update
|
94
|
+
}) {
|
95
|
+
const decode = createChunkDecoder(true);
|
96
|
+
const createdAt = /* @__PURE__ */ new Date();
|
97
|
+
const prefixMap = {};
|
98
|
+
const NEWLINE = "\n".charCodeAt(0);
|
99
|
+
let chunks = [];
|
100
|
+
let totalLength = 0;
|
101
|
+
while (true) {
|
102
|
+
const { value } = await reader.read();
|
103
|
+
if (value) {
|
104
|
+
chunks.push(value);
|
105
|
+
totalLength += value.length;
|
106
|
+
if (value[value.length - 1] !== NEWLINE) {
|
107
|
+
continue;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
if (chunks.length === 0) {
|
111
|
+
break;
|
112
|
+
}
|
113
|
+
let concatenatedChunks = new Uint8Array(totalLength);
|
114
|
+
let offset = 0;
|
115
|
+
for (const chunk of chunks) {
|
116
|
+
concatenatedChunks.set(chunk, offset);
|
117
|
+
offset += chunk.length;
|
118
|
+
}
|
119
|
+
chunks.length = 0;
|
120
|
+
totalLength = 0;
|
121
|
+
const lines = decode(concatenatedChunks);
|
122
|
+
if (typeof lines === "string") {
|
123
|
+
throw new Error(
|
124
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
125
|
+
);
|
126
|
+
}
|
127
|
+
for (const { type, value: value2 } of lines) {
|
128
|
+
if (type === "text") {
|
129
|
+
if (prefixMap["text"]) {
|
130
|
+
prefixMap["text"] = {
|
131
|
+
...prefixMap["text"],
|
132
|
+
content: (prefixMap["text"].content || "") + value2
|
133
|
+
};
|
134
|
+
} else {
|
135
|
+
prefixMap["text"] = {
|
136
|
+
id: nanoid(),
|
137
|
+
role: "assistant",
|
138
|
+
content: value2,
|
139
|
+
createdAt
|
140
|
+
};
|
141
|
+
}
|
142
|
+
}
|
143
|
+
let functionCallMessage = null;
|
144
|
+
if (type === "function_call") {
|
145
|
+
prefixMap["function_call"] = value2;
|
146
|
+
let functionCall = prefixMap["function_call"];
|
147
|
+
if (functionCall && typeof functionCall === "string") {
|
148
|
+
const parsedFunctionCall = JSON.parse(
|
149
|
+
functionCall
|
150
|
+
).function_call;
|
151
|
+
functionCallMessage = {
|
152
|
+
id: nanoid(),
|
153
|
+
role: "assistant",
|
154
|
+
content: "",
|
155
|
+
function_call: parsedFunctionCall,
|
156
|
+
name: parsedFunctionCall.name,
|
157
|
+
createdAt
|
158
|
+
};
|
159
|
+
prefixMap["function_call"] = functionCallMessage;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
if (type === "data") {
|
163
|
+
const parsedValue = JSON.parse(value2);
|
164
|
+
if (prefixMap["data"]) {
|
165
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
166
|
+
} else {
|
167
|
+
prefixMap["data"] = parsedValue;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
const data = prefixMap["data"];
|
171
|
+
const responseMessage = prefixMap["text"];
|
172
|
+
const merged = [functionCallMessage, responseMessage].filter(
|
173
|
+
Boolean
|
174
|
+
);
|
175
|
+
update(merged, data);
|
176
|
+
if (abortControllerRef.current === null) {
|
177
|
+
reader.cancel();
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
return prefixMap;
|
183
|
+
}
|
184
|
+
|
89
185
|
// react/use-chat.ts
|
90
186
|
var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
91
187
|
var _a, _b;
|
92
188
|
const previousMessages = messagesRef.current;
|
93
189
|
mutate(chatRequest.messages, false);
|
190
|
+
const constructedMessagesPayload = sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(({ role, content, name, function_call }) => ({
|
191
|
+
role,
|
192
|
+
content,
|
193
|
+
...name !== void 0 && { name },
|
194
|
+
...function_call !== void 0 && {
|
195
|
+
function_call
|
196
|
+
}
|
197
|
+
}));
|
198
|
+
if (typeof api !== "string") {
|
199
|
+
const replyId = nanoid();
|
200
|
+
const createdAt = /* @__PURE__ */ new Date();
|
201
|
+
let responseMessage = {
|
202
|
+
id: replyId,
|
203
|
+
createdAt,
|
204
|
+
content: "",
|
205
|
+
role: "assistant"
|
206
|
+
};
|
207
|
+
async function readRow(promise) {
|
208
|
+
const { content, ui, next } = await promise;
|
209
|
+
responseMessage["content"] = content;
|
210
|
+
responseMessage["ui"] = await ui;
|
211
|
+
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
212
|
+
if (next) {
|
213
|
+
await readRow(next);
|
214
|
+
}
|
215
|
+
}
|
216
|
+
try {
|
217
|
+
const promise = api({
|
218
|
+
messages: constructedMessagesPayload
|
219
|
+
});
|
220
|
+
await readRow(promise);
|
221
|
+
} catch (e) {
|
222
|
+
mutate(previousMessages, false);
|
223
|
+
throw e;
|
224
|
+
}
|
225
|
+
if (onFinish) {
|
226
|
+
onFinish(responseMessage);
|
227
|
+
}
|
228
|
+
return responseMessage;
|
229
|
+
}
|
94
230
|
const res = await fetch(api, {
|
95
231
|
method: "POST",
|
96
232
|
body: JSON.stringify({
|
97
|
-
messages:
|
98
|
-
({ role, content, name, function_call }) => ({
|
99
|
-
role,
|
100
|
-
content,
|
101
|
-
...name !== void 0 && { name },
|
102
|
-
...function_call !== void 0 && {
|
103
|
-
function_call
|
104
|
-
}
|
105
|
-
})
|
106
|
-
),
|
233
|
+
messages: constructedMessagesPayload,
|
107
234
|
...extraMetadataRef.current.body,
|
108
235
|
...(_a = chatRequest.options) == null ? void 0 : _a.body,
|
109
236
|
...chatRequest.functions !== void 0 && {
|
@@ -140,98 +267,18 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
140
267
|
throw new Error("The response body is empty.");
|
141
268
|
}
|
142
269
|
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
143
|
-
const createdAt = /* @__PURE__ */ new Date();
|
144
|
-
const reader = res.body.getReader();
|
145
|
-
const decode = createChunkDecoder(isComplexMode);
|
146
270
|
let responseMessages = [];
|
271
|
+
const reader = res.body.getReader();
|
147
272
|
let responseData = [];
|
148
|
-
const prefixMap = {};
|
149
|
-
const NEWLINE = "\n".charCodeAt(0);
|
150
|
-
let chunks = [];
|
151
|
-
let totalLength = 0;
|
152
273
|
if (isComplexMode) {
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
totalLength += value.length;
|
158
|
-
if (value[value.length - 1] !== NEWLINE) {
|
159
|
-
continue;
|
160
|
-
}
|
161
|
-
}
|
162
|
-
if (chunks.length === 0) {
|
163
|
-
break;
|
164
|
-
}
|
165
|
-
let concatenatedChunks = new Uint8Array(totalLength);
|
166
|
-
let offset = 0;
|
167
|
-
for (const chunk of chunks) {
|
168
|
-
concatenatedChunks.set(chunk, offset);
|
169
|
-
offset += chunk.length;
|
170
|
-
}
|
171
|
-
chunks.length = 0;
|
172
|
-
totalLength = 0;
|
173
|
-
const lines = decode(concatenatedChunks);
|
174
|
-
if (typeof lines === "string") {
|
175
|
-
throw new Error(
|
176
|
-
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
177
|
-
);
|
178
|
-
}
|
179
|
-
for (const { type, value: value2 } of lines) {
|
180
|
-
if (type === "text") {
|
181
|
-
if (prefixMap["text"]) {
|
182
|
-
prefixMap["text"] = {
|
183
|
-
...prefixMap["text"],
|
184
|
-
content: (prefixMap["text"].content || "") + value2
|
185
|
-
};
|
186
|
-
} else {
|
187
|
-
prefixMap["text"] = {
|
188
|
-
id: nanoid(),
|
189
|
-
role: "assistant",
|
190
|
-
content: value2,
|
191
|
-
createdAt
|
192
|
-
};
|
193
|
-
}
|
194
|
-
}
|
195
|
-
let functionCallMessage = null;
|
196
|
-
if (type === "function_call") {
|
197
|
-
prefixMap["function_call"] = value2;
|
198
|
-
let functionCall = prefixMap["function_call"];
|
199
|
-
if (functionCall && typeof functionCall === "string") {
|
200
|
-
const parsedFunctionCall = JSON.parse(
|
201
|
-
functionCall
|
202
|
-
).function_call;
|
203
|
-
functionCallMessage = {
|
204
|
-
id: nanoid(),
|
205
|
-
role: "assistant",
|
206
|
-
content: "",
|
207
|
-
function_call: parsedFunctionCall,
|
208
|
-
name: parsedFunctionCall.name,
|
209
|
-
createdAt
|
210
|
-
};
|
211
|
-
prefixMap["function_call"] = functionCallMessage;
|
212
|
-
}
|
213
|
-
}
|
214
|
-
if (type === "data") {
|
215
|
-
const parsedValue = JSON.parse(value2);
|
216
|
-
if (prefixMap["data"]) {
|
217
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
218
|
-
} else {
|
219
|
-
prefixMap["data"] = parsedValue;
|
220
|
-
}
|
221
|
-
}
|
222
|
-
const data = prefixMap["data"];
|
223
|
-
const responseMessage = prefixMap["text"];
|
224
|
-
const merged = [functionCallMessage, responseMessage].filter(
|
225
|
-
Boolean
|
226
|
-
);
|
274
|
+
const prefixMap = await parseComplexResponse({
|
275
|
+
reader,
|
276
|
+
abortControllerRef,
|
277
|
+
update(merged, data) {
|
227
278
|
mutate([...chatRequest.messages, ...merged], false);
|
228
279
|
mutateStreamData([...existingData || [], ...data || []], false);
|
229
|
-
if (abortControllerRef.current === null) {
|
230
|
-
reader.cancel();
|
231
|
-
break;
|
232
|
-
}
|
233
280
|
}
|
234
|
-
}
|
281
|
+
});
|
235
282
|
for (const [type, item] of Object.entries(prefixMap)) {
|
236
283
|
if (onFinish && type === "text") {
|
237
284
|
onFinish(item);
|
@@ -244,6 +291,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
244
291
|
}
|
245
292
|
return { messages: responseMessages, data: responseData };
|
246
293
|
} else {
|
294
|
+
const createdAt = /* @__PURE__ */ new Date();
|
295
|
+
const decode = createChunkDecoder(false);
|
247
296
|
let streamedResponse = "";
|
248
297
|
const replyId = nanoid();
|
249
298
|
let responseMessage = {
|
package/react/dist/index.mjs
CHANGED
@@ -20,7 +20,7 @@ function createChunkDecoder(complex) {
|
|
20
20
|
};
|
21
21
|
}
|
22
22
|
return function(chunk) {
|
23
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
23
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
24
24
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
25
25
|
};
|
26
26
|
}
|
@@ -50,24 +50,151 @@ var getStreamStringTypeAndValue = (line) => {
|
|
50
50
|
};
|
51
51
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
52
52
|
|
53
|
+
// react/parseComplexResponse.ts
|
54
|
+
async function parseComplexResponse({
|
55
|
+
reader,
|
56
|
+
abortControllerRef,
|
57
|
+
update
|
58
|
+
}) {
|
59
|
+
const decode = createChunkDecoder(true);
|
60
|
+
const createdAt = /* @__PURE__ */ new Date();
|
61
|
+
const prefixMap = {};
|
62
|
+
const NEWLINE = "\n".charCodeAt(0);
|
63
|
+
let chunks = [];
|
64
|
+
let totalLength = 0;
|
65
|
+
while (true) {
|
66
|
+
const { value } = await reader.read();
|
67
|
+
if (value) {
|
68
|
+
chunks.push(value);
|
69
|
+
totalLength += value.length;
|
70
|
+
if (value[value.length - 1] !== NEWLINE) {
|
71
|
+
continue;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
if (chunks.length === 0) {
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
let concatenatedChunks = new Uint8Array(totalLength);
|
78
|
+
let offset = 0;
|
79
|
+
for (const chunk of chunks) {
|
80
|
+
concatenatedChunks.set(chunk, offset);
|
81
|
+
offset += chunk.length;
|
82
|
+
}
|
83
|
+
chunks.length = 0;
|
84
|
+
totalLength = 0;
|
85
|
+
const lines = decode(concatenatedChunks);
|
86
|
+
if (typeof lines === "string") {
|
87
|
+
throw new Error(
|
88
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
89
|
+
);
|
90
|
+
}
|
91
|
+
for (const { type, value: value2 } of lines) {
|
92
|
+
if (type === "text") {
|
93
|
+
if (prefixMap["text"]) {
|
94
|
+
prefixMap["text"] = {
|
95
|
+
...prefixMap["text"],
|
96
|
+
content: (prefixMap["text"].content || "") + value2
|
97
|
+
};
|
98
|
+
} else {
|
99
|
+
prefixMap["text"] = {
|
100
|
+
id: nanoid(),
|
101
|
+
role: "assistant",
|
102
|
+
content: value2,
|
103
|
+
createdAt
|
104
|
+
};
|
105
|
+
}
|
106
|
+
}
|
107
|
+
let functionCallMessage = null;
|
108
|
+
if (type === "function_call") {
|
109
|
+
prefixMap["function_call"] = value2;
|
110
|
+
let functionCall = prefixMap["function_call"];
|
111
|
+
if (functionCall && typeof functionCall === "string") {
|
112
|
+
const parsedFunctionCall = JSON.parse(
|
113
|
+
functionCall
|
114
|
+
).function_call;
|
115
|
+
functionCallMessage = {
|
116
|
+
id: nanoid(),
|
117
|
+
role: "assistant",
|
118
|
+
content: "",
|
119
|
+
function_call: parsedFunctionCall,
|
120
|
+
name: parsedFunctionCall.name,
|
121
|
+
createdAt
|
122
|
+
};
|
123
|
+
prefixMap["function_call"] = functionCallMessage;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
if (type === "data") {
|
127
|
+
const parsedValue = JSON.parse(value2);
|
128
|
+
if (prefixMap["data"]) {
|
129
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
130
|
+
} else {
|
131
|
+
prefixMap["data"] = parsedValue;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
const data = prefixMap["data"];
|
135
|
+
const responseMessage = prefixMap["text"];
|
136
|
+
const merged = [functionCallMessage, responseMessage].filter(
|
137
|
+
Boolean
|
138
|
+
);
|
139
|
+
update(merged, data);
|
140
|
+
if (abortControllerRef.current === null) {
|
141
|
+
reader.cancel();
|
142
|
+
break;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
return prefixMap;
|
147
|
+
}
|
148
|
+
|
53
149
|
// react/use-chat.ts
|
54
150
|
var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
55
151
|
var _a, _b;
|
56
152
|
const previousMessages = messagesRef.current;
|
57
153
|
mutate(chatRequest.messages, false);
|
154
|
+
const constructedMessagesPayload = sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(({ role, content, name, function_call }) => ({
|
155
|
+
role,
|
156
|
+
content,
|
157
|
+
...name !== void 0 && { name },
|
158
|
+
...function_call !== void 0 && {
|
159
|
+
function_call
|
160
|
+
}
|
161
|
+
}));
|
162
|
+
if (typeof api !== "string") {
|
163
|
+
const replyId = nanoid();
|
164
|
+
const createdAt = /* @__PURE__ */ new Date();
|
165
|
+
let responseMessage = {
|
166
|
+
id: replyId,
|
167
|
+
createdAt,
|
168
|
+
content: "",
|
169
|
+
role: "assistant"
|
170
|
+
};
|
171
|
+
async function readRow(promise) {
|
172
|
+
const { content, ui, next } = await promise;
|
173
|
+
responseMessage["content"] = content;
|
174
|
+
responseMessage["ui"] = await ui;
|
175
|
+
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
176
|
+
if (next) {
|
177
|
+
await readRow(next);
|
178
|
+
}
|
179
|
+
}
|
180
|
+
try {
|
181
|
+
const promise = api({
|
182
|
+
messages: constructedMessagesPayload
|
183
|
+
});
|
184
|
+
await readRow(promise);
|
185
|
+
} catch (e) {
|
186
|
+
mutate(previousMessages, false);
|
187
|
+
throw e;
|
188
|
+
}
|
189
|
+
if (onFinish) {
|
190
|
+
onFinish(responseMessage);
|
191
|
+
}
|
192
|
+
return responseMessage;
|
193
|
+
}
|
58
194
|
const res = await fetch(api, {
|
59
195
|
method: "POST",
|
60
196
|
body: JSON.stringify({
|
61
|
-
messages:
|
62
|
-
({ role, content, name, function_call }) => ({
|
63
|
-
role,
|
64
|
-
content,
|
65
|
-
...name !== void 0 && { name },
|
66
|
-
...function_call !== void 0 && {
|
67
|
-
function_call
|
68
|
-
}
|
69
|
-
})
|
70
|
-
),
|
197
|
+
messages: constructedMessagesPayload,
|
71
198
|
...extraMetadataRef.current.body,
|
72
199
|
...(_a = chatRequest.options) == null ? void 0 : _a.body,
|
73
200
|
...chatRequest.functions !== void 0 && {
|
@@ -104,98 +231,18 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
104
231
|
throw new Error("The response body is empty.");
|
105
232
|
}
|
106
233
|
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
107
|
-
const createdAt = /* @__PURE__ */ new Date();
|
108
|
-
const reader = res.body.getReader();
|
109
|
-
const decode = createChunkDecoder(isComplexMode);
|
110
234
|
let responseMessages = [];
|
235
|
+
const reader = res.body.getReader();
|
111
236
|
let responseData = [];
|
112
|
-
const prefixMap = {};
|
113
|
-
const NEWLINE = "\n".charCodeAt(0);
|
114
|
-
let chunks = [];
|
115
|
-
let totalLength = 0;
|
116
237
|
if (isComplexMode) {
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
totalLength += value.length;
|
122
|
-
if (value[value.length - 1] !== NEWLINE) {
|
123
|
-
continue;
|
124
|
-
}
|
125
|
-
}
|
126
|
-
if (chunks.length === 0) {
|
127
|
-
break;
|
128
|
-
}
|
129
|
-
let concatenatedChunks = new Uint8Array(totalLength);
|
130
|
-
let offset = 0;
|
131
|
-
for (const chunk of chunks) {
|
132
|
-
concatenatedChunks.set(chunk, offset);
|
133
|
-
offset += chunk.length;
|
134
|
-
}
|
135
|
-
chunks.length = 0;
|
136
|
-
totalLength = 0;
|
137
|
-
const lines = decode(concatenatedChunks);
|
138
|
-
if (typeof lines === "string") {
|
139
|
-
throw new Error(
|
140
|
-
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
141
|
-
);
|
142
|
-
}
|
143
|
-
for (const { type, value: value2 } of lines) {
|
144
|
-
if (type === "text") {
|
145
|
-
if (prefixMap["text"]) {
|
146
|
-
prefixMap["text"] = {
|
147
|
-
...prefixMap["text"],
|
148
|
-
content: (prefixMap["text"].content || "") + value2
|
149
|
-
};
|
150
|
-
} else {
|
151
|
-
prefixMap["text"] = {
|
152
|
-
id: nanoid(),
|
153
|
-
role: "assistant",
|
154
|
-
content: value2,
|
155
|
-
createdAt
|
156
|
-
};
|
157
|
-
}
|
158
|
-
}
|
159
|
-
let functionCallMessage = null;
|
160
|
-
if (type === "function_call") {
|
161
|
-
prefixMap["function_call"] = value2;
|
162
|
-
let functionCall = prefixMap["function_call"];
|
163
|
-
if (functionCall && typeof functionCall === "string") {
|
164
|
-
const parsedFunctionCall = JSON.parse(
|
165
|
-
functionCall
|
166
|
-
).function_call;
|
167
|
-
functionCallMessage = {
|
168
|
-
id: nanoid(),
|
169
|
-
role: "assistant",
|
170
|
-
content: "",
|
171
|
-
function_call: parsedFunctionCall,
|
172
|
-
name: parsedFunctionCall.name,
|
173
|
-
createdAt
|
174
|
-
};
|
175
|
-
prefixMap["function_call"] = functionCallMessage;
|
176
|
-
}
|
177
|
-
}
|
178
|
-
if (type === "data") {
|
179
|
-
const parsedValue = JSON.parse(value2);
|
180
|
-
if (prefixMap["data"]) {
|
181
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
182
|
-
} else {
|
183
|
-
prefixMap["data"] = parsedValue;
|
184
|
-
}
|
185
|
-
}
|
186
|
-
const data = prefixMap["data"];
|
187
|
-
const responseMessage = prefixMap["text"];
|
188
|
-
const merged = [functionCallMessage, responseMessage].filter(
|
189
|
-
Boolean
|
190
|
-
);
|
238
|
+
const prefixMap = await parseComplexResponse({
|
239
|
+
reader,
|
240
|
+
abortControllerRef,
|
241
|
+
update(merged, data) {
|
191
242
|
mutate([...chatRequest.messages, ...merged], false);
|
192
243
|
mutateStreamData([...existingData || [], ...data || []], false);
|
193
|
-
if (abortControllerRef.current === null) {
|
194
|
-
reader.cancel();
|
195
|
-
break;
|
196
|
-
}
|
197
244
|
}
|
198
|
-
}
|
245
|
+
});
|
199
246
|
for (const [type, item] of Object.entries(prefixMap)) {
|
200
247
|
if (onFinish && type === "text") {
|
201
248
|
onFinish(item);
|
@@ -208,6 +255,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
208
255
|
}
|
209
256
|
return { messages: responseMessages, data: responseData };
|
210
257
|
} else {
|
258
|
+
const createdAt = /* @__PURE__ */ new Date();
|
259
|
+
const decode = createChunkDecoder(false);
|
211
260
|
let streamedResponse = "";
|
212
261
|
const replyId = nanoid();
|
213
262
|
let responseMessage = {
|
package/solid/dist/index.d.ts
CHANGED
@@ -42,6 +42,7 @@ interface Message {
|
|
42
42
|
id: string;
|
43
43
|
createdAt?: Date;
|
44
44
|
content: string;
|
45
|
+
ui?: string | JSX.Element | JSX.Element[] | null | undefined;
|
45
46
|
role: 'system' | 'user' | 'assistant' | 'function';
|
46
47
|
/**
|
47
48
|
* If the message has a role of `function`, the `name` field is the name of the function.
|
package/solid/dist/index.js
CHANGED
@@ -46,7 +46,7 @@ function createChunkDecoder(complex) {
|
|
46
46
|
};
|
47
47
|
}
|
48
48
|
return function(chunk) {
|
49
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
49
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
50
50
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
51
51
|
};
|
52
52
|
}
|
package/solid/dist/index.mjs
CHANGED
@@ -19,7 +19,7 @@ function createChunkDecoder(complex) {
|
|
19
19
|
};
|
20
20
|
}
|
21
21
|
return function(chunk) {
|
22
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
22
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
23
23
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
24
24
|
};
|
25
25
|
}
|
package/svelte/dist/index.d.ts
CHANGED
@@ -42,6 +42,7 @@ interface Message {
|
|
42
42
|
id: string;
|
43
43
|
createdAt?: Date;
|
44
44
|
content: string;
|
45
|
+
ui?: string | JSX.Element | JSX.Element[] | null | undefined;
|
45
46
|
role: 'system' | 'user' | 'assistant' | 'function';
|
46
47
|
/**
|
47
48
|
* If the message has a role of `function`, the `name` field is the name of the function.
|
package/svelte/dist/index.js
CHANGED
@@ -541,7 +541,7 @@ function createChunkDecoder(complex) {
|
|
541
541
|
};
|
542
542
|
}
|
543
543
|
return function(chunk) {
|
544
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
544
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
545
545
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
546
546
|
};
|
547
547
|
}
|
package/svelte/dist/index.mjs
CHANGED
@@ -514,7 +514,7 @@ function createChunkDecoder(complex) {
|
|
514
514
|
};
|
515
515
|
}
|
516
516
|
return function(chunk) {
|
517
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
517
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
518
518
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
519
519
|
};
|
520
520
|
}
|
package/vue/dist/index.d.ts
CHANGED
@@ -42,6 +42,7 @@ interface Message {
|
|
42
42
|
id: string;
|
43
43
|
createdAt?: Date;
|
44
44
|
content: string;
|
45
|
+
ui?: string | JSX.Element | JSX.Element[] | null | undefined;
|
45
46
|
role: 'system' | 'user' | 'assistant' | 'function';
|
46
47
|
/**
|
47
48
|
* If the message has a role of `function`, the `name` field is the name of the function.
|
package/vue/dist/index.js
CHANGED
@@ -55,7 +55,7 @@ function createChunkDecoder(complex) {
|
|
55
55
|
};
|
56
56
|
}
|
57
57
|
return function(chunk) {
|
58
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
58
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
59
59
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
60
60
|
};
|
61
61
|
}
|
package/vue/dist/index.mjs
CHANGED
@@ -18,7 +18,7 @@ function createChunkDecoder(complex) {
|
|
18
18
|
};
|
19
19
|
}
|
20
20
|
return function(chunk) {
|
21
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
21
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
22
22
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
23
23
|
};
|
24
24
|
}
|