@assistant-ui/react-data-stream 0.11.14 → 0.12.2
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/converters/toLanguageModelMessages.d.ts +6 -5
- package/dist/converters/toLanguageModelMessages.d.ts.map +1 -1
- package/dist/converters/toLanguageModelMessages.js +87 -136
- package/dist/converters/toLanguageModelMessages.js.map +1 -1
- package/dist/useDataStreamRuntime.d.ts +10 -0
- package/dist/useDataStreamRuntime.d.ts.map +1 -1
- package/dist/useDataStreamRuntime.js +12 -19
- package/dist/useDataStreamRuntime.js.map +1 -1
- package/package.json +8 -8
- package/src/converters/toLanguageModelMessages.ts +111 -165
- package/src/useDataStreamRuntime.ts +32 -28
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ThreadMessage } from "@assistant-ui/react";
|
|
1
|
+
import type { LanguageModelV2Message } from "@ai-sdk/provider";
|
|
2
|
+
import type { ThreadMessage } from "@assistant-ui/react";
|
|
3
3
|
/**
|
|
4
|
-
* @deprecated
|
|
4
|
+
* @deprecated Use `toGenericMessages` from `assistant-stream` for framework-agnostic conversion.
|
|
5
|
+
* This function is kept for AI SDK compatibility.
|
|
5
6
|
*/
|
|
6
|
-
export declare function toLanguageModelMessages(
|
|
7
|
+
export declare function toLanguageModelMessages(messages: readonly ThreadMessage[], options?: {
|
|
7
8
|
unstable_includeId?: boolean | undefined;
|
|
8
|
-
}):
|
|
9
|
+
}): LanguageModelV2Message[];
|
|
9
10
|
//# sourceMappingURL=toLanguageModelMessages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toLanguageModelMessages.d.ts","sourceRoot":"","sources":["../../src/converters/toLanguageModelMessages.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"toLanguageModelMessages.d.ts","sourceRoot":"","sources":["../../src/converters/toLanguageModelMessages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,sBAAsB,EAIvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAiFzD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,OAAO,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAO,GACzD,sBAAsB,EAAE,CAoC1B"}
|
|
@@ -1,144 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
1
|
+
import { toGenericMessages, } from "assistant-stream";
|
|
2
|
+
function toUrl(value) {
|
|
3
|
+
if (value instanceof URL)
|
|
4
|
+
return value;
|
|
5
|
+
try {
|
|
6
|
+
return new URL(value);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
// For relative URLs, create URL with a dummy base
|
|
10
|
+
return new URL(value, "file://");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function convertUserContent(content) {
|
|
14
|
+
return content.content.map((part) => {
|
|
15
|
+
if (part.type === "text") {
|
|
16
|
+
return part;
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
type: "file",
|
|
20
|
+
data: toUrl(part.data),
|
|
21
|
+
mediaType: part.mediaType,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function convertAssistantContent(content) {
|
|
26
|
+
return content.map((part) => {
|
|
27
|
+
if (part.type === "text") {
|
|
28
|
+
return part;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
type: "tool-call",
|
|
32
|
+
toolCallId: part.toolCallId,
|
|
33
|
+
toolName: part.toolName,
|
|
34
|
+
input: part.args,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function convertToolContent(content) {
|
|
39
|
+
return content.map((part) => ({
|
|
40
|
+
type: "tool-result",
|
|
41
|
+
toolCallId: part.toolCallId,
|
|
42
|
+
toolName: part.toolName,
|
|
43
|
+
output: part.isError
|
|
44
|
+
? { type: "error-json", value: part.result }
|
|
45
|
+
: { type: "json", value: part.result },
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
function convertGenericToLanguageModel(generic) {
|
|
49
|
+
switch (generic.role) {
|
|
50
|
+
case "system":
|
|
51
|
+
return { role: "system", content: generic.content };
|
|
52
|
+
case "user":
|
|
53
|
+
return { role: "user", content: convertUserContent(generic) };
|
|
54
|
+
case "assistant":
|
|
55
|
+
return {
|
|
56
|
+
role: "assistant",
|
|
57
|
+
content: convertAssistantContent(generic.content),
|
|
58
|
+
};
|
|
59
|
+
case "tool":
|
|
60
|
+
return { role: "tool", content: convertToolContent(generic.content) };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
53
63
|
/**
|
|
54
|
-
* @deprecated
|
|
64
|
+
* @deprecated Use `toGenericMessages` from `assistant-stream` for framework-agnostic conversion.
|
|
65
|
+
* This function is kept for AI SDK compatibility.
|
|
55
66
|
*/
|
|
56
|
-
export function toLanguageModelMessages(
|
|
67
|
+
export function toLanguageModelMessages(messages, options = {}) {
|
|
57
68
|
const includeId = options.unstable_includeId ?? false;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
const genericMessages = toGenericMessages(messages);
|
|
70
|
+
if (!includeId) {
|
|
71
|
+
return genericMessages.map(convertGenericToLanguageModel);
|
|
72
|
+
}
|
|
73
|
+
// When includeId is true, we need to map back to original message IDs
|
|
74
|
+
const result = [];
|
|
75
|
+
let messageIndex = 0;
|
|
76
|
+
for (const generic of genericMessages) {
|
|
77
|
+
const converted = convertGenericToLanguageModel(generic);
|
|
78
|
+
// Tool messages are synthesized from assistant message tool calls,
|
|
79
|
+
// they don't have a corresponding original message
|
|
80
|
+
if (generic.role !== "tool") {
|
|
81
|
+
// Find the corresponding original message for ID
|
|
82
|
+
while (messageIndex < messages.length &&
|
|
83
|
+
messages[messageIndex].role !== generic.role) {
|
|
84
|
+
messageIndex++;
|
|
71
85
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
...message.content,
|
|
76
|
-
...attachments.map((a) => a.content).flat(),
|
|
77
|
-
];
|
|
78
|
-
const msg = {
|
|
79
|
-
...(includeId ? { unstable_id: message.id } : {}),
|
|
80
|
-
role: "user",
|
|
81
|
-
content: content.map((part) => {
|
|
82
|
-
const type = part.type;
|
|
83
|
-
switch (type) {
|
|
84
|
-
case "text": {
|
|
85
|
-
return part;
|
|
86
|
-
}
|
|
87
|
-
case "image": {
|
|
88
|
-
return {
|
|
89
|
-
type: "image",
|
|
90
|
-
image: new URL(part.image),
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
case "file": {
|
|
94
|
-
return {
|
|
95
|
-
type: "file",
|
|
96
|
-
data: new URL(part.data),
|
|
97
|
-
mimeType: part.mimeType,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
default: {
|
|
101
|
-
const unhandledType = type;
|
|
102
|
-
throw new Error(`Unspported message part type: ${unhandledType}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}),
|
|
106
|
-
};
|
|
107
|
-
return [msg];
|
|
108
|
-
}
|
|
109
|
-
case "assistant": {
|
|
110
|
-
const splitter = assistantMessageSplitter();
|
|
111
|
-
for (const part of message.content) {
|
|
112
|
-
const type = part.type;
|
|
113
|
-
switch (type) {
|
|
114
|
-
case "reasoning":
|
|
115
|
-
case "source":
|
|
116
|
-
case "file":
|
|
117
|
-
case "data":
|
|
118
|
-
case "image": {
|
|
119
|
-
break; // reasoning, source, file, and image parts are omitted
|
|
120
|
-
}
|
|
121
|
-
case "text": {
|
|
122
|
-
splitter.addTextMessagePart(part);
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
case "tool-call": {
|
|
126
|
-
splitter.addToolCallPart(part);
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
default: {
|
|
130
|
-
const unhandledType = type;
|
|
131
|
-
throw new Error(`Unhandled message part type: ${unhandledType}`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return splitter.getMessages();
|
|
136
|
-
}
|
|
137
|
-
default: {
|
|
138
|
-
const unhandledRole = role;
|
|
139
|
-
throw new Error(`Unknown message role: ${unhandledRole}`);
|
|
86
|
+
if (messageIndex < messages.length) {
|
|
87
|
+
converted.unstable_id = messages[messageIndex].id;
|
|
88
|
+
messageIndex++;
|
|
140
89
|
}
|
|
141
90
|
}
|
|
142
|
-
|
|
91
|
+
result.push(converted);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
143
94
|
}
|
|
144
95
|
//# sourceMappingURL=toLanguageModelMessages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toLanguageModelMessages.js","sourceRoot":"","sources":["../../src/converters/toLanguageModelMessages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"toLanguageModelMessages.js","sourceRoot":"","sources":["../../src/converters/toLanguageModelMessages.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { type AssistantRuntime, type LocalRuntimeOptions, type ThreadMessage } from "@assistant-ui/react";
|
|
2
2
|
type HeadersValue = Record<string, string> | Headers;
|
|
3
|
+
export type DataStreamProtocol = "ui-message-stream" | "data-stream";
|
|
3
4
|
export type UseDataStreamRuntimeOptions = {
|
|
4
5
|
api: string;
|
|
6
|
+
/** Defaults to "ui-message-stream". Use "data-stream" for legacy AI SDK. */
|
|
7
|
+
protocol?: DataStreamProtocol;
|
|
8
|
+
/** Callback for data-* parts (ui-message-stream only). */
|
|
9
|
+
onData?: (data: {
|
|
10
|
+
type: string;
|
|
11
|
+
name: string;
|
|
12
|
+
data: unknown;
|
|
13
|
+
transient?: boolean;
|
|
14
|
+
}) => void;
|
|
5
15
|
onResponse?: (response: Response) => void | Promise<void>;
|
|
6
16
|
onFinish?: (message: ThreadMessage) => void;
|
|
7
17
|
onError?: (error: Error) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDataStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useDataStreamRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,gBAAgB,EAIrB,KAAK,mBAAmB,EACxB,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"useDataStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useDataStreamRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,gBAAgB,EAIrB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAC;AAY7B,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;AAErD,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAErE,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,OAAO,CAAC;QACd,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,KAAK,IAAI,CAAC;IACX,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,YAAY,GAAG,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACpD,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,GAAG,mBAAmB,CAAC;AAqHxB,eAAO,MAAM,oBAAoB,GAC/B,SAAS,2BAA2B,KACnC,gBAQF,CAAC"}
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { toLanguageModelMessages } from "./converters/index.js";
|
|
3
3
|
import { INTERNAL, useLocalRuntime, } from "@assistant-ui/react";
|
|
4
|
-
import {
|
|
5
|
-
import { AssistantMessageAccumulator, DataStreamDecoder, unstable_toolResultStream, } from "assistant-stream";
|
|
4
|
+
import { AssistantMessageAccumulator, DataStreamDecoder, toToolsJSONSchema, UIMessageStreamDecoder, unstable_toolResultStream, } from "assistant-stream";
|
|
6
5
|
import { asAsyncIterableStream } from "assistant-stream/utils";
|
|
7
6
|
const { splitLocalRuntimeOptions } = INTERNAL;
|
|
8
|
-
const toAISDKTools = (tools) => {
|
|
9
|
-
return Object.fromEntries(Object.entries(tools).map(([name, tool]) => [
|
|
10
|
-
name,
|
|
11
|
-
{
|
|
12
|
-
...(tool.description ? { description: tool.description } : undefined),
|
|
13
|
-
parameters: (tool.parameters instanceof z.ZodType
|
|
14
|
-
? z.toJSONSchema(tool.parameters)
|
|
15
|
-
: tool.parameters),
|
|
16
|
-
},
|
|
17
|
-
]));
|
|
18
|
-
};
|
|
19
|
-
const getEnabledTools = (tools) => {
|
|
20
|
-
return Object.fromEntries(Object.entries(tools).filter(([, tool]) => !tool.disabled && tool.type !== "backend"));
|
|
21
|
-
};
|
|
22
7
|
class DataStreamRuntimeAdapter {
|
|
23
8
|
options;
|
|
24
9
|
constructor(options) {
|
|
25
10
|
this.options = options;
|
|
26
11
|
}
|
|
27
|
-
async *run({ messages, runConfig, abortSignal, context, unstable_assistantMessageId, unstable_getMessage, }) {
|
|
12
|
+
async *run({ messages, runConfig, abortSignal, context, unstable_assistantMessageId, unstable_threadId, unstable_parentId, unstable_getMessage, }) {
|
|
28
13
|
const headersValue = typeof this.options.headers === "function"
|
|
29
14
|
? await this.options.headers()
|
|
30
15
|
: this.options.headers;
|
|
@@ -46,8 +31,12 @@ class DataStreamRuntimeAdapter {
|
|
|
46
31
|
messages: toLanguageModelMessages(messages, {
|
|
47
32
|
unstable_includeId: this.options.sendExtraMessageFields,
|
|
48
33
|
}),
|
|
49
|
-
tools:
|
|
34
|
+
tools: toToolsJSONSchema(context.tools ?? {}),
|
|
50
35
|
...(unstable_assistantMessageId ? { unstable_assistantMessageId } : {}),
|
|
36
|
+
...(unstable_threadId ? { threadId: unstable_threadId } : {}),
|
|
37
|
+
...(unstable_parentId !== undefined
|
|
38
|
+
? { parentId: unstable_parentId }
|
|
39
|
+
: {}),
|
|
51
40
|
runConfig,
|
|
52
41
|
state: unstable_getMessage().metadata.unstable_state || undefined,
|
|
53
42
|
...context.callSettings,
|
|
@@ -64,8 +53,12 @@ class DataStreamRuntimeAdapter {
|
|
|
64
53
|
if (!result.body) {
|
|
65
54
|
throw new Error("Response body is null");
|
|
66
55
|
}
|
|
56
|
+
const protocol = this.options.protocol ?? "ui-message-stream";
|
|
57
|
+
const decoder = protocol === "ui-message-stream"
|
|
58
|
+
? new UIMessageStreamDecoder(this.options.onData ? { onData: this.options.onData } : {})
|
|
59
|
+
: new DataStreamDecoder();
|
|
67
60
|
const stream = result.body
|
|
68
|
-
.pipeThrough(
|
|
61
|
+
.pipeThrough(decoder)
|
|
69
62
|
.pipeThrough(unstable_toolResultStream(context.tools, abortSignal, () => {
|
|
70
63
|
throw new Error("Tool interrupt is not supported in data stream runtime");
|
|
71
64
|
}))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDataStreamRuntime.js","sourceRoot":"","sources":["../src/useDataStreamRuntime.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,uBAAuB,EAAE,8BAAqB;AACvD,OAAO,EAIL,QAAQ,
|
|
1
|
+
{"version":3,"file":"useDataStreamRuntime.js","sourceRoot":"","sources":["../src/useDataStreamRuntime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-data-stream",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "Data stream adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-stream",
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
],
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/provider": "^
|
|
33
|
-
"assistant-stream": "^0.
|
|
34
|
-
"zod": "^4.3.
|
|
32
|
+
"@ai-sdk/provider": "^3.0.5",
|
|
33
|
+
"assistant-stream": "^0.3.0",
|
|
34
|
+
"zod": "^4.3.6"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@assistant-ui/react": "^0.
|
|
37
|
+
"@assistant-ui/react": "^0.12.3",
|
|
38
38
|
"@types/react": "*",
|
|
39
39
|
"react": "^18 || ^19"
|
|
40
40
|
},
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/json-schema": "^7.0.15",
|
|
48
|
-
"@types/react": "^19.2.
|
|
49
|
-
"react": "^19.2.
|
|
50
|
-
"@assistant-ui/react": "0.
|
|
48
|
+
"@types/react": "^19.2.9",
|
|
49
|
+
"react": "^19.2.4",
|
|
50
|
+
"@assistant-ui/react": "0.12.3",
|
|
51
51
|
"@assistant-ui/x-buildutils": "0.0.1"
|
|
52
52
|
},
|
|
53
53
|
"publishConfig": {
|
|
@@ -1,187 +1,133 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import type {
|
|
2
|
+
JSONValue,
|
|
3
|
+
LanguageModelV2FilePart,
|
|
4
|
+
LanguageModelV2Message,
|
|
5
|
+
LanguageModelV2TextPart,
|
|
6
|
+
LanguageModelV2ToolCallPart,
|
|
7
|
+
LanguageModelV2ToolResultPart,
|
|
8
8
|
} from "@ai-sdk/provider";
|
|
9
|
+
import type { ThreadMessage } from "@assistant-ui/react";
|
|
9
10
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const stash: LanguageModelV1Message[] = [];
|
|
17
|
-
let assistantMessage = {
|
|
18
|
-
role: "assistant" as const,
|
|
19
|
-
content: [] as (LanguageModelV1TextPart | LanguageModelV1ToolCallPart)[],
|
|
20
|
-
};
|
|
21
|
-
let toolMessage = {
|
|
22
|
-
role: "tool" as const,
|
|
23
|
-
content: [] as LanguageModelV1ToolResultPart[],
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
addTextMessagePart: (part: TextMessagePart) => {
|
|
28
|
-
if (toolMessage.content.length > 0) {
|
|
29
|
-
stash.push(assistantMessage);
|
|
30
|
-
stash.push(toolMessage);
|
|
11
|
+
toGenericMessages,
|
|
12
|
+
type GenericMessage,
|
|
13
|
+
type GenericTextPart,
|
|
14
|
+
type GenericToolCallPart,
|
|
15
|
+
type GenericToolResultPart,
|
|
16
|
+
} from "assistant-stream";
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
18
|
+
function toUrl(value: string | URL): URL {
|
|
19
|
+
if (value instanceof URL) return value;
|
|
20
|
+
try {
|
|
21
|
+
return new URL(value);
|
|
22
|
+
} catch {
|
|
23
|
+
// For relative URLs, create URL with a dummy base
|
|
24
|
+
return new URL(value, "file://");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
28
|
+
function convertUserContent(
|
|
29
|
+
content: GenericMessage & { role: "user" },
|
|
30
|
+
): (LanguageModelV2TextPart | LanguageModelV2FilePart)[] {
|
|
31
|
+
return content.content.map((part) => {
|
|
32
|
+
if (part.type === "text") {
|
|
33
|
+
return part;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
type: "file",
|
|
37
|
+
data: toUrl(part.data),
|
|
38
|
+
mediaType: part.mediaType,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
function convertAssistantContent(
|
|
44
|
+
content: (GenericTextPart | GenericToolCallPart)[],
|
|
45
|
+
): (LanguageModelV2TextPart | LanguageModelV2ToolCallPart)[] {
|
|
46
|
+
return content.map((part) => {
|
|
47
|
+
if (part.type === "text") {
|
|
48
|
+
return part;
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
type: "tool-call",
|
|
52
|
+
toolCallId: part.toolCallId,
|
|
53
|
+
toolName: part.toolName,
|
|
54
|
+
input: part.args,
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
getMessages: () => {
|
|
69
|
-
if (toolMessage.content.length > 0) {
|
|
70
|
-
return [...stash, assistantMessage, toolMessage];
|
|
71
|
-
}
|
|
59
|
+
function convertToolContent(
|
|
60
|
+
content: GenericToolResultPart[],
|
|
61
|
+
): LanguageModelV2ToolResultPart[] {
|
|
62
|
+
return content.map((part) => ({
|
|
63
|
+
type: "tool-result",
|
|
64
|
+
toolCallId: part.toolCallId,
|
|
65
|
+
toolName: part.toolName,
|
|
66
|
+
output: part.isError
|
|
67
|
+
? { type: "error-json", value: part.result as JSONValue }
|
|
68
|
+
: { type: "json", value: part.result as JSONValue },
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
function convertGenericToLanguageModel(
|
|
73
|
+
generic: GenericMessage,
|
|
74
|
+
): LanguageModelV2Message {
|
|
75
|
+
switch (generic.role) {
|
|
76
|
+
case "system":
|
|
77
|
+
return { role: "system", content: generic.content };
|
|
78
|
+
case "user":
|
|
79
|
+
return { role: "user", content: convertUserContent(generic) };
|
|
80
|
+
case "assistant":
|
|
81
|
+
return {
|
|
82
|
+
role: "assistant",
|
|
83
|
+
content: convertAssistantContent(generic.content),
|
|
84
|
+
};
|
|
85
|
+
case "tool":
|
|
86
|
+
return { role: "tool", content: convertToolContent(generic.content) };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
77
89
|
|
|
78
90
|
/**
|
|
79
|
-
* @deprecated
|
|
91
|
+
* @deprecated Use `toGenericMessages` from `assistant-stream` for framework-agnostic conversion.
|
|
92
|
+
* This function is kept for AI SDK compatibility.
|
|
80
93
|
*/
|
|
81
94
|
export function toLanguageModelMessages(
|
|
82
|
-
|
|
95
|
+
messages: readonly ThreadMessage[],
|
|
83
96
|
options: { unstable_includeId?: boolean | undefined } = {},
|
|
84
|
-
):
|
|
97
|
+
): LanguageModelV2Message[] {
|
|
85
98
|
const includeId = options.unstable_includeId ?? false;
|
|
86
|
-
|
|
87
|
-
const role = message.role;
|
|
88
|
-
switch (role) {
|
|
89
|
-
case "system": {
|
|
90
|
-
return [
|
|
91
|
-
{
|
|
92
|
-
...(includeId
|
|
93
|
-
? { unstable_id: (message as ThreadMessage).id }
|
|
94
|
-
: {}),
|
|
95
|
-
role: "system",
|
|
96
|
-
content: message.content[0].text,
|
|
97
|
-
},
|
|
98
|
-
];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
case "user": {
|
|
102
|
-
const attachments = "attachments" in message ? message.attachments : [];
|
|
103
|
-
const content = [
|
|
104
|
-
...message.content,
|
|
105
|
-
...attachments.map((a) => a.content).flat(),
|
|
106
|
-
];
|
|
107
|
-
const msg: LanguageModelV1Message = {
|
|
108
|
-
...(includeId ? { unstable_id: (message as ThreadMessage).id } : {}),
|
|
109
|
-
role: "user",
|
|
110
|
-
content: content.map(
|
|
111
|
-
(
|
|
112
|
-
part,
|
|
113
|
-
):
|
|
114
|
-
| LanguageModelV1TextPart
|
|
115
|
-
| LanguageModelV1ImagePart
|
|
116
|
-
| LanguageModelV1FilePart => {
|
|
117
|
-
const type = part.type;
|
|
118
|
-
switch (type) {
|
|
119
|
-
case "text": {
|
|
120
|
-
return part;
|
|
121
|
-
}
|
|
99
|
+
const genericMessages = toGenericMessages(messages as any);
|
|
122
100
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
image: new URL(part.image),
|
|
127
|
-
};
|
|
128
|
-
}
|
|
101
|
+
if (!includeId) {
|
|
102
|
+
return genericMessages.map(convertGenericToLanguageModel);
|
|
103
|
+
}
|
|
129
104
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
data: new URL(part.data),
|
|
134
|
-
mimeType: part.mimeType,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
105
|
+
// When includeId is true, we need to map back to original message IDs
|
|
106
|
+
const result: LanguageModelV2Message[] = [];
|
|
107
|
+
let messageIndex = 0;
|
|
137
108
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
throw new Error(
|
|
141
|
-
`Unspported message part type: ${unhandledType}`,
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
),
|
|
147
|
-
};
|
|
148
|
-
return [msg];
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
case "assistant": {
|
|
152
|
-
const splitter = assistantMessageSplitter();
|
|
153
|
-
for (const part of message.content) {
|
|
154
|
-
const type = part.type;
|
|
155
|
-
switch (type) {
|
|
156
|
-
case "reasoning":
|
|
157
|
-
case "source":
|
|
158
|
-
case "file":
|
|
159
|
-
case "data":
|
|
160
|
-
case "image": {
|
|
161
|
-
break; // reasoning, source, file, and image parts are omitted
|
|
162
|
-
}
|
|
109
|
+
for (const generic of genericMessages) {
|
|
110
|
+
const converted = convertGenericToLanguageModel(generic);
|
|
163
111
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const unhandledType: never = type;
|
|
174
|
-
throw new Error(`Unhandled message part type: ${unhandledType}`);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return splitter.getMessages();
|
|
112
|
+
// Tool messages are synthesized from assistant message tool calls,
|
|
113
|
+
// they don't have a corresponding original message
|
|
114
|
+
if (generic.role !== "tool") {
|
|
115
|
+
// Find the corresponding original message for ID
|
|
116
|
+
while (
|
|
117
|
+
messageIndex < messages.length &&
|
|
118
|
+
messages[messageIndex]!.role !== generic.role
|
|
119
|
+
) {
|
|
120
|
+
messageIndex++;
|
|
179
121
|
}
|
|
180
122
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
123
|
+
if (messageIndex < messages.length) {
|
|
124
|
+
(converted as any).unstable_id = messages[messageIndex]!.id;
|
|
125
|
+
messageIndex++;
|
|
184
126
|
}
|
|
185
127
|
}
|
|
186
|
-
|
|
128
|
+
|
|
129
|
+
result.push(converted);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return result;
|
|
187
133
|
}
|
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
INTERNAL,
|
|
9
9
|
type LocalRuntimeOptions,
|
|
10
10
|
type ThreadMessage,
|
|
11
|
-
type Tool,
|
|
12
11
|
useLocalRuntime,
|
|
13
12
|
} from "@assistant-ui/react";
|
|
14
|
-
import { z } from "zod";
|
|
15
|
-
import type { JSONSchema7 } from "json-schema";
|
|
16
13
|
import {
|
|
17
14
|
AssistantMessageAccumulator,
|
|
18
15
|
DataStreamDecoder,
|
|
16
|
+
toToolsJSONSchema,
|
|
17
|
+
UIMessageStreamDecoder,
|
|
19
18
|
unstable_toolResultStream,
|
|
20
19
|
} from "assistant-stream";
|
|
21
20
|
import { asAsyncIterableStream } from "assistant-stream/utils";
|
|
@@ -24,8 +23,19 @@ const { splitLocalRuntimeOptions } = INTERNAL;
|
|
|
24
23
|
|
|
25
24
|
type HeadersValue = Record<string, string> | Headers;
|
|
26
25
|
|
|
26
|
+
export type DataStreamProtocol = "ui-message-stream" | "data-stream";
|
|
27
|
+
|
|
27
28
|
export type UseDataStreamRuntimeOptions = {
|
|
28
29
|
api: string;
|
|
30
|
+
/** Defaults to "ui-message-stream". Use "data-stream" for legacy AI SDK. */
|
|
31
|
+
protocol?: DataStreamProtocol;
|
|
32
|
+
/** Callback for data-* parts (ui-message-stream only). */
|
|
33
|
+
onData?: (data: {
|
|
34
|
+
type: string;
|
|
35
|
+
name: string;
|
|
36
|
+
data: unknown;
|
|
37
|
+
transient?: boolean;
|
|
38
|
+
}) => void;
|
|
29
39
|
onResponse?: (response: Response) => void | Promise<void>;
|
|
30
40
|
onFinish?: (message: ThreadMessage) => void;
|
|
31
41
|
onError?: (error: Error) => void;
|
|
@@ -42,31 +52,11 @@ type DataStreamRuntimeRequestOptions = {
|
|
|
42
52
|
system?: string | undefined;
|
|
43
53
|
runConfig?: any;
|
|
44
54
|
unstable_assistantMessageId?: string;
|
|
55
|
+
threadId?: string;
|
|
56
|
+
parentId?: string | null;
|
|
45
57
|
state?: any;
|
|
46
58
|
};
|
|
47
59
|
|
|
48
|
-
const toAISDKTools = (tools: Record<string, Tool>) => {
|
|
49
|
-
return Object.fromEntries(
|
|
50
|
-
Object.entries(tools).map(([name, tool]) => [
|
|
51
|
-
name,
|
|
52
|
-
{
|
|
53
|
-
...(tool.description ? { description: tool.description } : undefined),
|
|
54
|
-
parameters: (tool.parameters instanceof z.ZodType
|
|
55
|
-
? z.toJSONSchema(tool.parameters)
|
|
56
|
-
: tool.parameters) as JSONSchema7,
|
|
57
|
-
},
|
|
58
|
-
]),
|
|
59
|
-
);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const getEnabledTools = (tools: Record<string, Tool>) => {
|
|
63
|
-
return Object.fromEntries(
|
|
64
|
-
Object.entries(tools).filter(
|
|
65
|
-
([, tool]) => !tool.disabled && tool.type !== "backend",
|
|
66
|
-
),
|
|
67
|
-
);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
60
|
class DataStreamRuntimeAdapter implements ChatModelAdapter {
|
|
71
61
|
constructor(
|
|
72
62
|
private options: Omit<
|
|
@@ -81,6 +71,8 @@ class DataStreamRuntimeAdapter implements ChatModelAdapter {
|
|
|
81
71
|
abortSignal,
|
|
82
72
|
context,
|
|
83
73
|
unstable_assistantMessageId,
|
|
74
|
+
unstable_threadId,
|
|
75
|
+
unstable_parentId,
|
|
84
76
|
unstable_getMessage,
|
|
85
77
|
}: ChatModelRunOptions) {
|
|
86
78
|
const headersValue =
|
|
@@ -113,10 +105,14 @@ class DataStreamRuntimeAdapter implements ChatModelAdapter {
|
|
|
113
105
|
messages: toLanguageModelMessages(messages, {
|
|
114
106
|
unstable_includeId: this.options.sendExtraMessageFields,
|
|
115
107
|
}) as DataStreamRuntimeRequestOptions["messages"],
|
|
116
|
-
tools:
|
|
117
|
-
|
|
108
|
+
tools: toToolsJSONSchema(
|
|
109
|
+
context.tools ?? {},
|
|
118
110
|
) as unknown as DataStreamRuntimeRequestOptions["tools"],
|
|
119
111
|
...(unstable_assistantMessageId ? { unstable_assistantMessageId } : {}),
|
|
112
|
+
...(unstable_threadId ? { threadId: unstable_threadId } : {}),
|
|
113
|
+
...(unstable_parentId !== undefined
|
|
114
|
+
? { parentId: unstable_parentId }
|
|
115
|
+
: {}),
|
|
120
116
|
runConfig,
|
|
121
117
|
state: unstable_getMessage().metadata.unstable_state || undefined,
|
|
122
118
|
...context.callSettings,
|
|
@@ -136,8 +132,16 @@ class DataStreamRuntimeAdapter implements ChatModelAdapter {
|
|
|
136
132
|
throw new Error("Response body is null");
|
|
137
133
|
}
|
|
138
134
|
|
|
135
|
+
const protocol = this.options.protocol ?? "ui-message-stream";
|
|
136
|
+
const decoder =
|
|
137
|
+
protocol === "ui-message-stream"
|
|
138
|
+
? new UIMessageStreamDecoder(
|
|
139
|
+
this.options.onData ? { onData: this.options.onData } : {},
|
|
140
|
+
)
|
|
141
|
+
: new DataStreamDecoder();
|
|
142
|
+
|
|
139
143
|
const stream = result.body
|
|
140
|
-
.pipeThrough(
|
|
144
|
+
.pipeThrough(decoder)
|
|
141
145
|
.pipeThrough(
|
|
142
146
|
unstable_toolResultStream(context.tools, abortSignal, () => {
|
|
143
147
|
throw new Error(
|