@ai-sdk/svelte 3.0.0-canary.2 → 3.0.0-canary.21
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 +218 -0
- package/README.md +5 -5
- package/dist/chat.svelte.d.ts +12 -26
- package/dist/chat.svelte.d.ts.map +1 -1
- package/dist/chat.svelte.js +21 -58
- package/dist/completion.svelte.d.ts +2 -9
- package/dist/completion.svelte.d.ts.map +1 -1
- package/dist/completion.svelte.js +4 -22
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/structured-object-context.svelte.d.ts +1 -1
- package/dist/structured-object-context.svelte.d.ts.map +1 -1
- package/dist/structured-object.svelte.d.ts +1 -1
- package/dist/structured-object.svelte.d.ts.map +1 -1
- package/dist/structured-object.svelte.js +5 -5
- package/dist/tests/chat-synchronization.svelte.d.ts +2 -2
- package/dist/tests/structured-object-synchronization.svelte +1 -1
- package/dist/tests/structured-object-synchronization.svelte.d.ts +1 -1
- package/dist/tests/structured-object-synchronization.svelte.d.ts.map +1 -1
- package/package.json +10 -7
- package/src/chat-context.svelte.ts +10 -5
- package/src/chat.svelte.ts +61 -116
- package/src/completion-context.svelte.ts +1 -1
- package/src/completion.svelte.ts +11 -28
- package/src/index.ts +1 -2
- package/src/structured-object-context.svelte.ts +1 -1
- package/src/structured-object.svelte.ts +5 -5
- package/src/tests/structured-object-synchronization.svelte +1 -1
- package/dist/chat-context.svelte.d.ts +0 -14
- package/dist/chat-context.svelte.d.ts.map +0 -1
- package/dist/completion-context.svelte.d.ts +0 -15
- package/dist/completion-context.svelte.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateId, isAbortError, safeValidateTypes, } from '@ai-sdk/provider-utils';
|
|
2
|
-
import { asSchema, isDeepEqualData, parsePartialJson, } from '
|
|
2
|
+
import { asSchema, isDeepEqualData, parsePartialJson, } from 'ai';
|
|
3
3
|
import {} from 'zod';
|
|
4
4
|
import { getStructuredObjectContext, hasStructuredObjectContext, KeyedStructuredObjectStore, } from './structured-object-context.svelte.js';
|
|
5
5
|
export class StructuredObject {
|
|
@@ -82,23 +82,23 @@ export class StructuredObject {
|
|
|
82
82
|
let accumulatedText = '';
|
|
83
83
|
let latestObject = undefined;
|
|
84
84
|
await response.body.pipeThrough(new TextDecoderStream()).pipeTo(new WritableStream({
|
|
85
|
-
write: chunk => {
|
|
85
|
+
write: async (chunk) => {
|
|
86
86
|
if (abortController?.signal.aborted) {
|
|
87
87
|
throw new DOMException('Stream aborted', 'AbortError');
|
|
88
88
|
}
|
|
89
89
|
accumulatedText += chunk;
|
|
90
|
-
const { value } = parsePartialJson(accumulatedText);
|
|
90
|
+
const { value } = await parsePartialJson(accumulatedText);
|
|
91
91
|
const currentObject = value;
|
|
92
92
|
if (!isDeepEqualData(latestObject, currentObject)) {
|
|
93
93
|
latestObject = currentObject;
|
|
94
94
|
this.#store.object = currentObject;
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
|
-
close: () => {
|
|
97
|
+
close: async () => {
|
|
98
98
|
this.#store.loading = false;
|
|
99
99
|
this.#abortController = undefined;
|
|
100
100
|
if (this.#options.onFinish != null) {
|
|
101
|
-
const validationResult = safeValidateTypes({
|
|
101
|
+
const validationResult = await safeValidateTypes({
|
|
102
102
|
value: latestObject,
|
|
103
103
|
schema: asSchema(this.#options.schema),
|
|
104
104
|
});
|
|
@@ -3,8 +3,8 @@ type $$ComponentProps = {
|
|
|
3
3
|
id?: string;
|
|
4
4
|
};
|
|
5
5
|
declare const ChatSynchronization: import("svelte").Component<$$ComponentProps, {
|
|
6
|
-
chat1: Chat
|
|
7
|
-
chat2: Chat
|
|
6
|
+
chat1: Chat<unknown>;
|
|
7
|
+
chat2: Chat<unknown>;
|
|
8
8
|
}, "">;
|
|
9
9
|
type ChatSynchronization = ReturnType<typeof ChatSynchronization>;
|
|
10
10
|
export default ChatSynchronization;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" generics="RESULT">
|
|
2
2
|
import { createAIContext } from '../context-provider.js';
|
|
3
3
|
import { StructuredObject } from '../structured-object.svelte.js';
|
|
4
|
-
import type { Schema } from '
|
|
4
|
+
import type { Schema } from 'ai';
|
|
5
5
|
import type { z } from 'zod';
|
|
6
6
|
|
|
7
7
|
let {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-object-synchronization.svelte.d.ts","sourceRoot":"","sources":["../../src/tests/structured-object-synchronization.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"structured-object-synchronization.svelte.d.ts","sourceRoot":"","sources":["../../src/tests/structured-object-synchronization.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2B7B,cAAM,iBAAiB,CAAC,MAAM;IAC1B,KAAK;aArBA,MAAM;aACN,MAAM;;;IAuBX,MAAM;IAGN,KAAK;IAGL,QAAQ;IACR,OAAO;;;;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/Z,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1I,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,+BAA+B,EAAE,qBAAmC,CAAC;AACzD,KAAK,+BAA+B,CAAC,MAAM,IAAI,YAAY,CAAC,OAAO,+BAA+B,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9G,eAAe,+BAA+B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/svelte",
|
|
3
|
-
"version": "3.0.0-canary.
|
|
3
|
+
"version": "3.0.0-canary.21",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -36,10 +36,11 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"
|
|
40
|
-
"@ai-sdk/
|
|
39
|
+
"ai": "5.0.0-canary.22",
|
|
40
|
+
"@ai-sdk/provider-utils": "3.0.0-canary.17"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@types/node": "20.17.24",
|
|
43
44
|
"@eslint/compat": "^1.2.5",
|
|
44
45
|
"@eslint/js": "^9.18.0",
|
|
45
46
|
"@sveltejs/package": "^2.0.0",
|
|
@@ -57,9 +58,10 @@
|
|
|
57
58
|
"typescript-eslint": "^8.20.0",
|
|
58
59
|
"vite": "^6.0.0",
|
|
59
60
|
"vitest": "^3.0.0",
|
|
60
|
-
"zod": "3.23.8"
|
|
61
|
+
"zod": "3.23.8",
|
|
62
|
+
"@vercel/ai-tsconfig": "0.0.0"
|
|
61
63
|
},
|
|
62
|
-
"homepage": "https://sdk.
|
|
64
|
+
"homepage": "https://ai-sdk.dev/docs",
|
|
63
65
|
"repository": {
|
|
64
66
|
"type": "git",
|
|
65
67
|
"url": "git+https://github.com/vercel/ai.git",
|
|
@@ -74,7 +76,7 @@
|
|
|
74
76
|
],
|
|
75
77
|
"scripts": {
|
|
76
78
|
"build": "pnpm prepack",
|
|
77
|
-
"build:watch": "svelte-package --input=src --watch",
|
|
79
|
+
"build:watch": "pnpm clean && pnpm --filter svelte build && svelte-package --input=src --watch",
|
|
78
80
|
"preview": "vite preview",
|
|
79
81
|
"type-check": "svelte-check --tsconfig ./tsconfig.json",
|
|
80
82
|
"type-check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
|
@@ -82,7 +84,8 @@
|
|
|
82
84
|
"prettier-check": "prettier --check .",
|
|
83
85
|
"lint": "eslint .",
|
|
84
86
|
"test": "vitest --run",
|
|
87
|
+
"test:update": "vitest --run -u",
|
|
85
88
|
"test:watch": "vitest",
|
|
86
|
-
"clean": "rm -rf dist"
|
|
89
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
87
90
|
}
|
|
88
91
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import type { JSONValue, UIMessage } from '
|
|
1
|
+
import type { JSONValue, UIMessage } from 'ai';
|
|
2
2
|
import { createContext, KeyedStore } from './utils.svelte.js';
|
|
3
3
|
|
|
4
|
-
class ChatStore {
|
|
5
|
-
messages = $state<UIMessage[]>([]);
|
|
4
|
+
class ChatStore<MESSAGE_METADATA = unknown> {
|
|
5
|
+
messages = $state<UIMessage<MESSAGE_METADATA>[]>([]);
|
|
6
6
|
data = $state<JSONValue[]>();
|
|
7
7
|
status = $state<'submitted' | 'streaming' | 'ready' | 'error'>('ready');
|
|
8
8
|
error = $state<Error>();
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export class KeyedChatStore extends KeyedStore<
|
|
11
|
+
export class KeyedChatStore<MESSAGE_METADATA = unknown> extends KeyedStore<
|
|
12
|
+
ChatStore<MESSAGE_METADATA>
|
|
13
|
+
> {
|
|
12
14
|
constructor(
|
|
13
|
-
value?:
|
|
15
|
+
value?:
|
|
16
|
+
| Iterable<readonly [string, ChatStore<MESSAGE_METADATA>]>
|
|
17
|
+
| null
|
|
18
|
+
| undefined,
|
|
14
19
|
) {
|
|
15
20
|
super(ChatStore, value);
|
|
16
21
|
}
|
package/src/chat.svelte.ts
CHANGED
|
@@ -1,70 +1,52 @@
|
|
|
1
|
+
import { isAbortError } from '@ai-sdk/provider-utils';
|
|
1
2
|
import {
|
|
2
|
-
fillMessageParts,
|
|
3
|
-
generateId,
|
|
4
|
-
type UIMessage,
|
|
5
|
-
type UseChatOptions,
|
|
6
|
-
type JSONValue,
|
|
7
|
-
type ChatRequest,
|
|
8
|
-
extractMaxToolInvocationStep,
|
|
9
3
|
callChatApi,
|
|
4
|
+
convertFileListToFileUIParts,
|
|
5
|
+
extractMaxToolInvocationStep,
|
|
6
|
+
generateId,
|
|
7
|
+
getToolInvocations,
|
|
8
|
+
isAssistantMessageWithCompletedToolCalls,
|
|
10
9
|
shouldResubmitMessages,
|
|
11
|
-
type Message,
|
|
12
|
-
type CreateMessage,
|
|
13
|
-
type ChatRequestOptions,
|
|
14
|
-
prepareAttachmentsForRequest,
|
|
15
|
-
getMessageParts,
|
|
16
10
|
updateToolCallResult,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
type ChatRequestOptions,
|
|
12
|
+
type CreateUIMessage,
|
|
13
|
+
type UIMessage,
|
|
14
|
+
type UseChatOptions,
|
|
15
|
+
} from 'ai';
|
|
16
|
+
import { untrack } from 'svelte';
|
|
20
17
|
import {
|
|
21
18
|
KeyedChatStore,
|
|
22
19
|
getChatContext,
|
|
23
20
|
hasChatContext,
|
|
24
21
|
} from './chat-context.svelte.js';
|
|
25
|
-
import { untrack } from 'svelte';
|
|
26
22
|
|
|
27
|
-
export type ChatOptions = Readonly<
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Maximum number of sequential LLM calls (steps), e.g. when you use tool calls.
|
|
31
|
-
* Must be at least 1.
|
|
32
|
-
* A maximum number is required to prevent infinite loops in the case of misconfigured tools.
|
|
33
|
-
* By default, it's set to 1, which means that only a single LLM call is made.
|
|
34
|
-
* @default 1
|
|
35
|
-
*/
|
|
36
|
-
maxSteps?: number;
|
|
37
|
-
}
|
|
23
|
+
export type ChatOptions<MESSAGE_METADATA = unknown> = Readonly<
|
|
24
|
+
UseChatOptions<MESSAGE_METADATA>
|
|
38
25
|
>;
|
|
39
26
|
|
|
40
|
-
export type {
|
|
27
|
+
export type { CreateUIMessage, UIMessage };
|
|
41
28
|
|
|
42
|
-
export class Chat {
|
|
43
|
-
readonly #options: ChatOptions = {};
|
|
29
|
+
export class Chat<MESSAGE_METADATA = unknown> {
|
|
30
|
+
readonly #options: ChatOptions<MESSAGE_METADATA> = {};
|
|
44
31
|
readonly #api = $derived(this.#options.api ?? '/api/chat');
|
|
45
32
|
readonly #generateId = $derived(this.#options.generateId ?? generateId);
|
|
46
33
|
readonly #maxSteps = $derived(this.#options.maxSteps ?? 1);
|
|
47
|
-
readonly #streamProtocol = $derived(
|
|
48
|
-
|
|
34
|
+
readonly #streamProtocol = $derived(
|
|
35
|
+
this.#options.streamProtocol ?? 'ui-message',
|
|
36
|
+
);
|
|
37
|
+
readonly #keyedStore = $state<KeyedChatStore<MESSAGE_METADATA>>()!;
|
|
49
38
|
/**
|
|
50
39
|
* The id of the chat. If not provided through the constructor, a random ID will be generated
|
|
51
40
|
* using the provided `generateId` function, or a built-in function if not provided.
|
|
52
41
|
*/
|
|
53
42
|
readonly id = $derived(this.#options.id ?? this.#generateId());
|
|
54
43
|
readonly #store = $derived(this.#keyedStore.get(this.id));
|
|
55
|
-
#abortController: AbortController | undefined;
|
|
56
44
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
get data() {
|
|
63
|
-
return this.#store.data;
|
|
64
|
-
}
|
|
65
|
-
set data(value: JSONValue[] | undefined) {
|
|
66
|
-
this.#store.data = value;
|
|
67
|
-
}
|
|
45
|
+
readonly #messageMetadataSchema = $derived(
|
|
46
|
+
this.#options.messageMetadataSchema,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
#abortController: AbortController | undefined;
|
|
68
50
|
|
|
69
51
|
/**
|
|
70
52
|
* Hook status:
|
|
@@ -92,18 +74,18 @@ export class Chat {
|
|
|
92
74
|
* This is writable, which is useful when you want to edit the messages on the client, and then
|
|
93
75
|
* trigger {@link reload} to regenerate the AI response.
|
|
94
76
|
*/
|
|
95
|
-
get messages(): UIMessage[] {
|
|
77
|
+
get messages(): UIMessage<MESSAGE_METADATA>[] {
|
|
96
78
|
return this.#store.messages;
|
|
97
79
|
}
|
|
98
|
-
set messages(value:
|
|
99
|
-
untrack(() => (this.#store.messages =
|
|
80
|
+
set messages(value: UIMessage<MESSAGE_METADATA>[]) {
|
|
81
|
+
untrack(() => (this.#store.messages = value));
|
|
100
82
|
}
|
|
101
83
|
|
|
102
|
-
constructor(options: ChatOptions = {}) {
|
|
84
|
+
constructor(options: ChatOptions<MESSAGE_METADATA> = {}) {
|
|
103
85
|
if (hasChatContext()) {
|
|
104
|
-
this.#keyedStore = getChatContext()
|
|
86
|
+
this.#keyedStore = getChatContext() as KeyedChatStore<MESSAGE_METADATA>;
|
|
105
87
|
} else {
|
|
106
|
-
this.#keyedStore = new KeyedChatStore();
|
|
88
|
+
this.#keyedStore = new KeyedChatStore<MESSAGE_METADATA>();
|
|
107
89
|
}
|
|
108
90
|
|
|
109
91
|
this.#options = options;
|
|
@@ -118,23 +100,15 @@ export class Chat {
|
|
|
118
100
|
* @param options Additional options to pass to the API call
|
|
119
101
|
*/
|
|
120
102
|
append = async (
|
|
121
|
-
message:
|
|
122
|
-
{
|
|
103
|
+
message: UIMessage<MESSAGE_METADATA> | CreateUIMessage<MESSAGE_METADATA>,
|
|
104
|
+
{ headers, body }: ChatRequestOptions = {},
|
|
123
105
|
) => {
|
|
124
|
-
const attachmentsForRequest = await prepareAttachmentsForRequest(
|
|
125
|
-
experimental_attachments,
|
|
126
|
-
);
|
|
127
|
-
|
|
128
106
|
const messages = this.messages.concat({
|
|
129
107
|
...message,
|
|
130
108
|
id: message.id ?? this.#generateId(),
|
|
131
|
-
createdAt: message.createdAt ?? new Date(),
|
|
132
|
-
experimental_attachments:
|
|
133
|
-
attachmentsForRequest.length > 0 ? attachmentsForRequest : undefined,
|
|
134
|
-
parts: getMessageParts(message),
|
|
135
109
|
});
|
|
136
110
|
|
|
137
|
-
return this.#triggerRequest({ messages, headers, body
|
|
111
|
+
return this.#triggerRequest({ messages, headers, body });
|
|
138
112
|
};
|
|
139
113
|
|
|
140
114
|
/**
|
|
@@ -142,7 +116,7 @@ export class Chat {
|
|
|
142
116
|
* message isn't from the assistant, it will request the API to generate a
|
|
143
117
|
* new response.
|
|
144
118
|
*/
|
|
145
|
-
reload = async ({
|
|
119
|
+
reload = async ({ headers, body }: ChatRequestOptions = {}) => {
|
|
146
120
|
if (this.messages.length === 0) {
|
|
147
121
|
return;
|
|
148
122
|
}
|
|
@@ -155,7 +129,6 @@ export class Chat {
|
|
|
155
129
|
: this.messages,
|
|
156
130
|
headers,
|
|
157
131
|
body,
|
|
158
|
-
data,
|
|
159
132
|
});
|
|
160
133
|
};
|
|
161
134
|
|
|
@@ -176,33 +149,28 @@ export class Chat {
|
|
|
176
149
|
/** Form submission handler to automatically reset input and append a user message */
|
|
177
150
|
handleSubmit = async (
|
|
178
151
|
event?: { preventDefault?: () => void },
|
|
179
|
-
options: ChatRequestOptions = {},
|
|
152
|
+
options: ChatRequestOptions & { files?: FileList } = {},
|
|
180
153
|
) => {
|
|
181
154
|
event?.preventDefault?.();
|
|
182
|
-
if (!this.input && !options.allowEmptySubmit) return;
|
|
183
155
|
|
|
184
|
-
const
|
|
185
|
-
options.
|
|
186
|
-
|
|
156
|
+
const fileParts = Array.isArray(options?.files)
|
|
157
|
+
? options.files
|
|
158
|
+
: await convertFileListToFileUIParts(options?.files);
|
|
159
|
+
|
|
160
|
+
if (!this.input && fileParts.length === 0) return;
|
|
187
161
|
|
|
188
162
|
const messages = this.messages.concat({
|
|
189
163
|
id: this.#generateId(),
|
|
190
|
-
createdAt: new Date(),
|
|
191
164
|
role: 'user',
|
|
192
|
-
|
|
193
|
-
experimental_attachments:
|
|
194
|
-
attachmentsForRequest.length > 0 ? attachmentsForRequest : undefined,
|
|
195
|
-
parts: [{ type: 'text', text: this.input }],
|
|
165
|
+
parts: [...fileParts, { type: 'text', text: this.input }],
|
|
196
166
|
});
|
|
197
167
|
|
|
198
|
-
const
|
|
168
|
+
const request = this.#triggerRequest({
|
|
199
169
|
messages,
|
|
200
170
|
headers: options.headers,
|
|
201
171
|
body: options.body,
|
|
202
|
-
|
|
203
|
-
};
|
|
172
|
+
});
|
|
204
173
|
|
|
205
|
-
const request = this.#triggerRequest(chatRequest);
|
|
206
174
|
this.input = '';
|
|
207
175
|
await request;
|
|
208
176
|
};
|
|
@@ -234,14 +202,18 @@ export class Chat {
|
|
|
234
202
|
}
|
|
235
203
|
};
|
|
236
204
|
|
|
237
|
-
#triggerRequest = async (
|
|
205
|
+
#triggerRequest = async (
|
|
206
|
+
chatRequest: ChatRequestOptions & {
|
|
207
|
+
messages: UIMessage<MESSAGE_METADATA>[];
|
|
208
|
+
},
|
|
209
|
+
) => {
|
|
238
210
|
this.#store.status = 'submitted';
|
|
239
211
|
this.#store.error = undefined;
|
|
240
212
|
|
|
241
|
-
const messages =
|
|
213
|
+
const messages = chatRequest.messages;
|
|
242
214
|
const messageCount = messages.length;
|
|
243
215
|
const maxStep = extractMaxToolInvocationStep(
|
|
244
|
-
messages[messages.length - 1]
|
|
216
|
+
getToolInvocations(messages[messages.length - 1]),
|
|
245
217
|
);
|
|
246
218
|
|
|
247
219
|
try {
|
|
@@ -251,37 +223,11 @@ export class Chat {
|
|
|
251
223
|
// Optimistically update messages
|
|
252
224
|
this.messages = messages;
|
|
253
225
|
|
|
254
|
-
const constructedMessagesPayload = this.#options.sendExtraMessageFields
|
|
255
|
-
? messages
|
|
256
|
-
: messages.map(
|
|
257
|
-
({
|
|
258
|
-
role,
|
|
259
|
-
content,
|
|
260
|
-
experimental_attachments,
|
|
261
|
-
data,
|
|
262
|
-
annotations,
|
|
263
|
-
toolInvocations,
|
|
264
|
-
parts,
|
|
265
|
-
}) => ({
|
|
266
|
-
role,
|
|
267
|
-
content,
|
|
268
|
-
...(experimental_attachments !== undefined && {
|
|
269
|
-
experimental_attachments,
|
|
270
|
-
}),
|
|
271
|
-
...(data !== undefined && { data }),
|
|
272
|
-
...(annotations !== undefined && { annotations }),
|
|
273
|
-
...(toolInvocations !== undefined && { toolInvocations }),
|
|
274
|
-
...(parts !== undefined && { parts }),
|
|
275
|
-
}),
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
const existingData = this.data ?? [];
|
|
279
226
|
await callChatApi({
|
|
280
227
|
api: this.#api,
|
|
281
228
|
body: {
|
|
282
229
|
id: this.id,
|
|
283
|
-
messages
|
|
284
|
-
data: chatRequest.data,
|
|
230
|
+
messages,
|
|
285
231
|
...$state.snapshot(this.#options.body),
|
|
286
232
|
...chatRequest.body,
|
|
287
233
|
},
|
|
@@ -292,29 +238,28 @@ export class Chat {
|
|
|
292
238
|
...chatRequest.headers,
|
|
293
239
|
},
|
|
294
240
|
abortController: () => abortController,
|
|
295
|
-
|
|
296
|
-
onResponse: this.#options.onResponse,
|
|
297
|
-
onUpdate: ({ message, data, replaceLastMessage }) => {
|
|
241
|
+
onUpdate: ({ message }) => {
|
|
298
242
|
this.#store.status = 'streaming';
|
|
299
243
|
|
|
244
|
+
const replaceLastMessage =
|
|
245
|
+
message.id === messages[messages.length - 1].id;
|
|
246
|
+
|
|
300
247
|
this.messages = messages;
|
|
301
248
|
if (replaceLastMessage) {
|
|
302
249
|
this.messages[this.messages.length - 1] = message;
|
|
303
250
|
} else {
|
|
304
251
|
this.messages.push(message);
|
|
305
252
|
}
|
|
306
|
-
|
|
307
|
-
if (data?.length) {
|
|
308
|
-
this.data = existingData;
|
|
309
|
-
this.data.push(...data);
|
|
310
|
-
}
|
|
311
253
|
},
|
|
312
254
|
onToolCall: this.#options.onToolCall,
|
|
313
255
|
onFinish: this.#options.onFinish,
|
|
314
256
|
generateId: this.#generateId,
|
|
315
257
|
fetch: this.#options.fetch,
|
|
316
258
|
// callChatApi calls structuredClone on the message
|
|
317
|
-
lastMessage: $state.snapshot(
|
|
259
|
+
lastMessage: $state.snapshot(
|
|
260
|
+
this.messages[this.messages.length - 1],
|
|
261
|
+
) as UIMessage<MESSAGE_METADATA>,
|
|
262
|
+
messageMetadataSchema: this.#messageMetadataSchema,
|
|
318
263
|
});
|
|
319
264
|
|
|
320
265
|
this.#abortController = undefined;
|
package/src/completion.svelte.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
callCompletionApi,
|
|
2
3
|
generateId,
|
|
4
|
+
type CompletionRequestOptions,
|
|
3
5
|
type UseCompletionOptions,
|
|
4
|
-
|
|
5
|
-
type RequestOptions,
|
|
6
|
-
callCompletionApi,
|
|
7
|
-
} from '@ai-sdk/ui-utils';
|
|
6
|
+
} from 'ai';
|
|
8
7
|
import {
|
|
9
8
|
KeyedCompletionStore,
|
|
10
9
|
getCompletionContext,
|
|
@@ -30,18 +29,6 @@ export class Completion {
|
|
|
30
29
|
this.#store.completions.set(this.#id, value);
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
/**
|
|
34
|
-
* Additional data added on the server via StreamData.
|
|
35
|
-
*
|
|
36
|
-
* This is writable, so you can use it to transform or clear the chat data.
|
|
37
|
-
*/
|
|
38
|
-
get data() {
|
|
39
|
-
return this.#store.data;
|
|
40
|
-
}
|
|
41
|
-
set data(value: JSONValue[]) {
|
|
42
|
-
this.#store.data = value;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
32
|
/** The error object of the API request */
|
|
46
33
|
get error() {
|
|
47
34
|
return this.#store.error;
|
|
@@ -58,12 +45,9 @@ export class Completion {
|
|
|
58
45
|
}
|
|
59
46
|
|
|
60
47
|
constructor(options: CompletionOptions = {}) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.#keyedStore = new KeyedCompletionStore();
|
|
65
|
-
}
|
|
66
|
-
|
|
48
|
+
this.#keyedStore = hasCompletionContext()
|
|
49
|
+
? getCompletionContext()
|
|
50
|
+
: new KeyedCompletionStore();
|
|
67
51
|
this.#options = options;
|
|
68
52
|
this.completion = options.initialCompletion ?? '';
|
|
69
53
|
this.input = options.initialInput ?? '';
|
|
@@ -86,7 +70,7 @@ export class Completion {
|
|
|
86
70
|
/**
|
|
87
71
|
* Send a new prompt to the API endpoint and update the completion state.
|
|
88
72
|
*/
|
|
89
|
-
complete = async (prompt: string, options?:
|
|
73
|
+
complete = async (prompt: string, options?: CompletionRequestOptions) =>
|
|
90
74
|
this.#triggerRequest(prompt, options);
|
|
91
75
|
|
|
92
76
|
/** Form submission handler to automatically reset input and call the completion API */
|
|
@@ -97,7 +81,10 @@ export class Completion {
|
|
|
97
81
|
}
|
|
98
82
|
};
|
|
99
83
|
|
|
100
|
-
#triggerRequest = async (
|
|
84
|
+
#triggerRequest = async (
|
|
85
|
+
prompt: string,
|
|
86
|
+
options?: CompletionRequestOptions,
|
|
87
|
+
) => {
|
|
101
88
|
return callCompletionApi({
|
|
102
89
|
api: this.#api,
|
|
103
90
|
prompt,
|
|
@@ -113,9 +100,6 @@ export class Completion {
|
|
|
113
100
|
setCompletion: completion => {
|
|
114
101
|
this.completion = completion;
|
|
115
102
|
},
|
|
116
|
-
onData: data => {
|
|
117
|
-
this.data.push(...data);
|
|
118
|
-
},
|
|
119
103
|
setLoading: loading => {
|
|
120
104
|
this.#store.loading = loading;
|
|
121
105
|
},
|
|
@@ -125,7 +109,6 @@ export class Completion {
|
|
|
125
109
|
setAbortController: abortController => {
|
|
126
110
|
this.#abortController = abortController ?? undefined;
|
|
127
111
|
},
|
|
128
|
-
onResponse: this.#options.onResponse,
|
|
129
112
|
onFinish: this.#options.onFinish,
|
|
130
113
|
onError: this.#options.onError,
|
|
131
114
|
});
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
parsePartialJson,
|
|
11
11
|
type DeepPartial,
|
|
12
12
|
type Schema,
|
|
13
|
-
} from '
|
|
13
|
+
} from 'ai';
|
|
14
14
|
import { type z } from 'zod';
|
|
15
15
|
import {
|
|
16
16
|
getStructuredObjectContext,
|
|
@@ -177,13 +177,13 @@ export class StructuredObject<RESULT, INPUT = unknown> {
|
|
|
177
177
|
|
|
178
178
|
await response.body.pipeThrough(new TextDecoderStream()).pipeTo(
|
|
179
179
|
new WritableStream<string>({
|
|
180
|
-
write: chunk => {
|
|
180
|
+
write: async chunk => {
|
|
181
181
|
if (abortController?.signal.aborted) {
|
|
182
182
|
throw new DOMException('Stream aborted', 'AbortError');
|
|
183
183
|
}
|
|
184
184
|
accumulatedText += chunk;
|
|
185
185
|
|
|
186
|
-
const { value } = parsePartialJson(accumulatedText);
|
|
186
|
+
const { value } = await parsePartialJson(accumulatedText);
|
|
187
187
|
const currentObject = value as DeepPartial<RESULT>;
|
|
188
188
|
|
|
189
189
|
if (!isDeepEqualData(latestObject, currentObject)) {
|
|
@@ -193,12 +193,12 @@ export class StructuredObject<RESULT, INPUT = unknown> {
|
|
|
193
193
|
}
|
|
194
194
|
},
|
|
195
195
|
|
|
196
|
-
close: () => {
|
|
196
|
+
close: async () => {
|
|
197
197
|
this.#store.loading = false;
|
|
198
198
|
this.#abortController = undefined;
|
|
199
199
|
|
|
200
200
|
if (this.#options.onFinish != null) {
|
|
201
|
-
const validationResult = safeValidateTypes({
|
|
201
|
+
const validationResult = await safeValidateTypes({
|
|
202
202
|
value: latestObject,
|
|
203
203
|
schema: asSchema(this.#options.schema),
|
|
204
204
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" generics="RESULT">
|
|
2
2
|
import { createAIContext } from '../context-provider.js';
|
|
3
3
|
import { StructuredObject } from '../structured-object.svelte.js';
|
|
4
|
-
import type { Schema } from '
|
|
4
|
+
import type { Schema } from 'ai';
|
|
5
5
|
import type { z } from 'zod';
|
|
6
6
|
|
|
7
7
|
let {
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { JSONValue, UIMessage } from '@ai-sdk/ui-utils';
|
|
2
|
-
import { KeyedStore } from './utils.svelte.js';
|
|
3
|
-
declare class ChatStore {
|
|
4
|
-
messages: UIMessage[];
|
|
5
|
-
data: JSONValue[] | undefined;
|
|
6
|
-
status: "submitted" | "streaming" | "ready" | "error";
|
|
7
|
-
error: Error | undefined;
|
|
8
|
-
}
|
|
9
|
-
export declare class KeyedChatStore extends KeyedStore<ChatStore> {
|
|
10
|
-
constructor(value?: Iterable<readonly [string, ChatStore]> | null | undefined);
|
|
11
|
-
}
|
|
12
|
-
export declare const hasChatContext: () => boolean, getChatContext: () => KeyedChatStore, setChatContext: (value: KeyedChatStore) => KeyedChatStore;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=chat-context.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat-context.svelte.d.ts","sourceRoot":"","sources":["../src/chat-context.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAiB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE9D,cAAM,SAAS;IACb,QAAQ,cAA2B;IACnC,IAAI,0BAAyB;IAC7B,MAAM,gDAAkE;IACxE,KAAK,oBAAmB;CACzB;AAED,qBAAa,cAAe,SAAQ,UAAU,CAAC,SAAS,CAAC;gBAErD,KAAK,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS;CAIpE;AAED,eAAO,MACO,cAAc,iBACd,cAAc,wBACd,cAAc,2CACa,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { JSONValue } from '@ai-sdk/ui-utils';
|
|
2
|
-
import { SvelteMap } from 'svelte/reactivity';
|
|
3
|
-
import { KeyedStore } from './utils.svelte.js';
|
|
4
|
-
declare class CompletionStore {
|
|
5
|
-
completions: SvelteMap<string, string>;
|
|
6
|
-
data: JSONValue[];
|
|
7
|
-
loading: boolean;
|
|
8
|
-
error: Error | undefined;
|
|
9
|
-
}
|
|
10
|
-
export declare class KeyedCompletionStore extends KeyedStore<CompletionStore> {
|
|
11
|
-
constructor(value?: Iterable<readonly [string, CompletionStore]> | null | undefined);
|
|
12
|
-
}
|
|
13
|
-
export declare const hasCompletionContext: () => boolean, getCompletionContext: () => KeyedCompletionStore, setCompletionContext: (value: KeyedCompletionStore) => KeyedCompletionStore;
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=completion-context.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"completion-context.svelte.d.ts","sourceRoot":"","sources":["../src/completion-context.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAiB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE9D,cAAM,eAAe;IACnB,WAAW,4BAAmC;IAC9C,IAAI,cAA2B;IAC/B,OAAO,UAAiB;IACxB,KAAK,oBAAmB;CACzB;AAED,qBAAa,oBAAqB,SAAQ,UAAU,CAAC,eAAe,CAAC;gBAEjE,KAAK,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS;CAI1E;AAED,eAAO,MACO,oBAAoB,iBACpB,oBAAoB,8BACpB,oBAAoB,uDACmB,CAAC"}
|