@ai-sdk/ui-utils
Advanced tools
Comparing version 1.0.0-canary.7 to 1.0.0-canary.8
# @ai-sdk/ui-utils | ||
## 1.0.0-canary.8 | ||
### Patch Changes | ||
- b053413: chore (ui): refactorings & README update | ||
## 1.0.0-canary.7 | ||
@@ -4,0 +10,0 @@ |
@@ -10,3 +10,3 @@ import { LanguageModelV1FinishReason, JSONValue as JSONValue$1 } from '@ai-sdk/provider'; | ||
*/ | ||
type CompletionTokenUsage = { | ||
type LanguageModelUsage = { | ||
/** | ||
@@ -227,3 +227,3 @@ The number of tokens used in the prompt. | ||
onFinish?: (message: Message, options: { | ||
usage: CompletionTokenUsage; | ||
usage: LanguageModelUsage; | ||
finishReason: LanguageModelV1FinishReason; | ||
@@ -367,2 +367,34 @@ }) => void; | ||
type AssistantStreamString = `${(typeof StreamStringPrefixes)[keyof typeof StreamStringPrefixes]}:${string}\n`; | ||
interface AssistantStreamPart<CODE extends string, NAME extends string, TYPE> { | ||
code: CODE; | ||
name: NAME; | ||
parse: (value: JSONValue) => { | ||
type: NAME; | ||
value: TYPE; | ||
}; | ||
} | ||
declare const textStreamPart$1: AssistantStreamPart<'0', 'text', string>; | ||
declare const errorStreamPart$1: AssistantStreamPart<'3', 'error', string>; | ||
declare const assistantMessageStreamPart: AssistantStreamPart<'4', 'assistant_message', AssistantMessage>; | ||
declare const assistantControlDataStreamPart: AssistantStreamPart<'5', 'assistant_control_data', { | ||
threadId: string; | ||
messageId: string; | ||
}>; | ||
declare const dataMessageStreamPart: AssistantStreamPart<'6', 'data_message', DataMessage>; | ||
type AssistantStreamParts = typeof textStreamPart$1 | typeof errorStreamPart$1 | typeof assistantMessageStreamPart | typeof assistantControlDataStreamPart | typeof dataMessageStreamPart; | ||
type AssistantStreamPartValueType = { | ||
[P in AssistantStreamParts as P['name']]: ReturnType<P['parse']>['value']; | ||
}; | ||
type AssistantStreamPartType = ReturnType<typeof textStreamPart$1.parse> | ReturnType<typeof errorStreamPart$1.parse> | ReturnType<typeof assistantMessageStreamPart.parse> | ReturnType<typeof assistantControlDataStreamPart.parse> | ReturnType<typeof dataMessageStreamPart.parse>; | ||
declare const StreamStringPrefixes: { | ||
readonly text: "0"; | ||
readonly error: "3"; | ||
readonly assistant_message: "4"; | ||
readonly assistant_control_data: "5"; | ||
readonly data_message: "6"; | ||
}; | ||
declare const parseAssistantStreamPart: (line: string) => AssistantStreamPartType; | ||
declare function formatAssistantStreamPart<T extends keyof AssistantStreamPartValueType>(type: T, value: AssistantStreamPartValueType[T]): AssistantStreamString; | ||
declare const getOriginalFetch$1: () => typeof fetch; | ||
@@ -383,14 +415,3 @@ declare function callChatApi({ api, body, streamProtocol, credentials, headers, abortController, restoreMessagesOnFailure, onResponse, onUpdate, onFinish, onToolCall, generateId, fetch, }: { | ||
fetch: ReturnType<typeof getOriginalFetch$1> | undefined; | ||
}): Promise<{ | ||
messages: Message[]; | ||
data: JSONValue[]; | ||
} | { | ||
messages: { | ||
id: string; | ||
createdAt: Date; | ||
role: "assistant"; | ||
content: string; | ||
}[]; | ||
data: never[]; | ||
}>; | ||
}): Promise<void>; | ||
@@ -416,4 +437,4 @@ declare const getOriginalFetch: () => typeof fetch; | ||
type StreamString = `${(typeof StreamStringPrefixes)[keyof typeof StreamStringPrefixes]}:${string}\n`; | ||
interface StreamPart<CODE extends string, NAME extends string, TYPE> { | ||
type DataStreamString = `${(typeof DataStreamStringPrefixes)[keyof typeof DataStreamStringPrefixes]}:${string}\n`; | ||
interface DataStreamPart<CODE extends string, NAME extends string, TYPE> { | ||
code: CODE; | ||
@@ -426,23 +447,17 @@ name: NAME; | ||
} | ||
declare const textStreamPart: StreamPart<'0', 'text', string>; | ||
declare const dataStreamPart: StreamPart<'2', 'data', Array<JSONValue>>; | ||
declare const errorStreamPart: StreamPart<'3', 'error', string>; | ||
declare const assistantMessageStreamPart: StreamPart<'4', 'assistant_message', AssistantMessage>; | ||
declare const assistantControlDataStreamPart: StreamPart<'5', 'assistant_control_data', { | ||
threadId: string; | ||
messageId: string; | ||
}>; | ||
declare const dataMessageStreamPart: StreamPart<'6', 'data_message', DataMessage>; | ||
declare const messageAnnotationsStreamPart: StreamPart<'8', 'message_annotations', Array<JSONValue>>; | ||
declare const toolCallStreamPart: StreamPart<'9', 'tool_call', ToolCall<string, any>>; | ||
declare const toolResultStreamPart: StreamPart<'a', 'tool_result', Omit<ToolResult<string, any, any>, 'args' | 'toolName'>>; | ||
declare const toolCallStreamingStartStreamPart: StreamPart<'b', 'tool_call_streaming_start', { | ||
declare const textStreamPart: DataStreamPart<'0', 'text', string>; | ||
declare const dataStreamPart: DataStreamPart<'2', 'data', Array<JSONValue>>; | ||
declare const errorStreamPart: DataStreamPart<'3', 'error', string>; | ||
declare const messageAnnotationsStreamPart: DataStreamPart<'8', 'message_annotations', Array<JSONValue>>; | ||
declare const toolCallStreamPart: DataStreamPart<'9', 'tool_call', ToolCall<string, any>>; | ||
declare const toolResultStreamPart: DataStreamPart<'a', 'tool_result', Omit<ToolResult<string, any, any>, 'args' | 'toolName'>>; | ||
declare const toolCallStreamingStartStreamPart: DataStreamPart<'b', 'tool_call_streaming_start', { | ||
toolCallId: string; | ||
toolName: string; | ||
}>; | ||
declare const toolCallDeltaStreamPart: StreamPart<'c', 'tool_call_delta', { | ||
declare const toolCallDeltaStreamPart: DataStreamPart<'c', 'tool_call_delta', { | ||
toolCallId: string; | ||
argsTextDelta: string; | ||
}>; | ||
declare const finishMessageStreamPart: StreamPart<'d', 'finish_message', { | ||
declare const finishMessageStreamPart: DataStreamPart<'d', 'finish_message', { | ||
finishReason: LanguageModelV1FinishReason; | ||
@@ -454,3 +469,3 @@ usage?: { | ||
}>; | ||
declare const finishStepStreamPart: StreamPart<'e', 'finish_step', { | ||
declare const finishStepStreamPart: DataStreamPart<'e', 'finish_step', { | ||
isContinued: boolean; | ||
@@ -463,10 +478,10 @@ finishReason: LanguageModelV1FinishReason; | ||
}>; | ||
type StreamParts = typeof textStreamPart | typeof dataStreamPart | typeof errorStreamPart | typeof assistantMessageStreamPart | typeof assistantControlDataStreamPart | typeof dataMessageStreamPart | typeof messageAnnotationsStreamPart | typeof toolCallStreamPart | typeof toolResultStreamPart | typeof toolCallStreamingStartStreamPart | typeof toolCallDeltaStreamPart | typeof finishMessageStreamPart | typeof finishStepStreamPart; | ||
type DataStreamParts = typeof textStreamPart | typeof dataStreamPart | typeof errorStreamPart | typeof messageAnnotationsStreamPart | typeof toolCallStreamPart | typeof toolResultStreamPart | typeof toolCallStreamingStartStreamPart | typeof toolCallDeltaStreamPart | typeof finishMessageStreamPart | typeof finishStepStreamPart; | ||
/** | ||
* Maps the type of a stream part to its value type. | ||
*/ | ||
type StreamPartValueType = { | ||
[P in StreamParts as P['name']]: ReturnType<P['parse']>['value']; | ||
type DataStreamPartValueType = { | ||
[P in DataStreamParts as P['name']]: ReturnType<P['parse']>['value']; | ||
}; | ||
type StreamPartType = ReturnType<typeof textStreamPart.parse> | ReturnType<typeof dataStreamPart.parse> | ReturnType<typeof errorStreamPart.parse> | ReturnType<typeof assistantMessageStreamPart.parse> | ReturnType<typeof assistantControlDataStreamPart.parse> | ReturnType<typeof dataMessageStreamPart.parse> | ReturnType<typeof messageAnnotationsStreamPart.parse> | ReturnType<typeof toolCallStreamPart.parse> | ReturnType<typeof toolResultStreamPart.parse> | ReturnType<typeof toolCallStreamingStartStreamPart.parse> | ReturnType<typeof toolCallDeltaStreamPart.parse> | ReturnType<typeof finishMessageStreamPart.parse> | ReturnType<typeof finishStepStreamPart.parse>; | ||
type DataStreamPartType = ReturnType<typeof textStreamPart.parse> | ReturnType<typeof dataStreamPart.parse> | ReturnType<typeof errorStreamPart.parse> | ReturnType<typeof messageAnnotationsStreamPart.parse> | ReturnType<typeof toolCallStreamPart.parse> | ReturnType<typeof toolResultStreamPart.parse> | ReturnType<typeof toolCallStreamingStartStreamPart.parse> | ReturnType<typeof toolCallDeltaStreamPart.parse> | ReturnType<typeof finishMessageStreamPart.parse> | ReturnType<typeof finishStepStreamPart.parse>; | ||
/** | ||
@@ -494,9 +509,6 @@ * The map of prefixes for data in the stream | ||
*/ | ||
declare const StreamStringPrefixes: { | ||
declare const DataStreamStringPrefixes: { | ||
readonly text: "0"; | ||
readonly data: "2"; | ||
readonly error: "3"; | ||
readonly assistant_message: "4"; | ||
readonly assistant_control_data: "5"; | ||
readonly data_message: "6"; | ||
readonly message_annotations: "8"; | ||
@@ -517,3 +529,3 @@ readonly tool_call: "9"; | ||
*/ | ||
declare const parseStreamPart: (line: string) => StreamPartType; | ||
declare const parseDataStreamPart: (line: string) => DataStreamPartType; | ||
/** | ||
@@ -525,9 +537,4 @@ Prepends a string with a prefix from the `StreamChunkPrefixes`, JSON-ifies it, | ||
*/ | ||
declare function formatStreamPart<T extends keyof StreamPartValueType>(type: T, value: StreamPartValueType[T]): StreamString; | ||
declare function formatDataStreamPart<T extends keyof DataStreamPartValueType>(type: T, value: DataStreamPartValueType[T]): DataStreamString; | ||
declare function createChunkDecoder(): (chunk: Uint8Array | undefined) => string; | ||
declare function createChunkDecoder(complex: false): (chunk: Uint8Array | undefined) => string; | ||
declare function createChunkDecoder(complex: true): (chunk: Uint8Array | undefined) => StreamPartType[]; | ||
declare function createChunkDecoder(complex?: boolean): (chunk: Uint8Array | undefined) => StreamPartType[] | string; | ||
/** | ||
@@ -564,25 +571,2 @@ * Converts a data URL of type text/* to a text string. | ||
declare function processDataProtocolResponse({ reader, abortControllerRef, update, onToolCall, onFinish, generateId, getCurrentDate, }: { | ||
reader: ReadableStreamDefaultReader<Uint8Array>; | ||
abortControllerRef?: { | ||
current: AbortController | null; | ||
}; | ||
update: (newMessages: Message[], data: JSONValue[] | undefined) => void; | ||
onToolCall?: UseChatOptions['onToolCall']; | ||
onFinish?: (options: { | ||
message: Message | undefined; | ||
finishReason: LanguageModelV1FinishReason; | ||
usage: { | ||
completionTokens: number; | ||
promptTokens: number; | ||
totalTokens: number; | ||
}; | ||
}) => void; | ||
generateId?: () => string; | ||
getCurrentDate?: () => Date; | ||
}): Promise<{ | ||
messages: Message[]; | ||
data: JSONValue[]; | ||
}>; | ||
declare function parsePartialJson(jsonText: string | undefined): { | ||
@@ -593,17 +577,46 @@ value: JSONValue$1 | undefined; | ||
/** | ||
Converts a ReadableStreamDefaultReader into an async generator that yields | ||
StreamPart objects. | ||
declare function processAssistantStream({ stream, onStreamPart, }: { | ||
stream: ReadableStream<Uint8Array>; | ||
onStreamPart: (streamPart: AssistantStreamPartType) => Promise<void> | void; | ||
}): Promise<void>; | ||
@param reader | ||
Reader for the stream to read from. | ||
@param isAborted | ||
Optional function that returns true if the request has been aborted. | ||
If the function returns true, the generator will stop reading the stream. | ||
If the function is not provided, the generator will not stop reading the stream. | ||
*/ | ||
declare function readDataStream(reader: ReadableStreamDefaultReader<Uint8Array>, { isAborted, }?: { | ||
isAborted?: () => boolean; | ||
}): AsyncGenerator<StreamPartType>; | ||
declare function processDataStream({ stream, onTextPart, onDataPart, onErrorPart, onToolCallStreamingStartPart, onToolCallDeltaPart, onToolCallPart, onToolResultPart, onMessageAnnotationsPart, onFinishMessagePart, onFinishStepPart, }: { | ||
stream: ReadableStream<Uint8Array>; | ||
onTextPart?: (streamPart: (DataStreamPartType & { | ||
type: 'text'; | ||
})['value']) => Promise<void> | void; | ||
onDataPart?: (streamPart: (DataStreamPartType & { | ||
type: 'data'; | ||
})['value']) => Promise<void> | void; | ||
onErrorPart?: (streamPart: (DataStreamPartType & { | ||
type: 'error'; | ||
})['value']) => Promise<void> | void; | ||
onToolCallStreamingStartPart?: (streamPart: (DataStreamPartType & { | ||
type: 'tool_call_streaming_start'; | ||
})['value']) => Promise<void> | void; | ||
onToolCallDeltaPart?: (streamPart: (DataStreamPartType & { | ||
type: 'tool_call_delta'; | ||
})['value']) => Promise<void> | void; | ||
onToolCallPart?: (streamPart: (DataStreamPartType & { | ||
type: 'tool_call'; | ||
})['value']) => Promise<void> | void; | ||
onToolResultPart?: (streamPart: (DataStreamPartType & { | ||
type: 'tool_result'; | ||
})['value']) => Promise<void> | void; | ||
onMessageAnnotationsPart?: (streamPart: (DataStreamPartType & { | ||
type: 'message_annotations'; | ||
})['value']) => Promise<void> | void; | ||
onFinishMessagePart?: (streamPart: (DataStreamPartType & { | ||
type: 'finish_message'; | ||
})['value']) => Promise<void> | void; | ||
onFinishStepPart?: (streamPart: (DataStreamPartType & { | ||
type: 'finish_step'; | ||
})['value']) => Promise<void> | void; | ||
}): Promise<void>; | ||
declare function processTextStream({ stream, onTextPart, }: { | ||
stream: ReadableStream<Uint8Array>; | ||
onTextPart: (chunk: string) => Promise<void> | void; | ||
}): Promise<void>; | ||
/** | ||
@@ -645,2 +658,2 @@ * Used to mark schemas so we can support both Zod and custom schemas. | ||
export { type AssistantMessage, type AssistantStatus, type Attachment, type ChatRequest, type ChatRequestOptions, type CreateMessage, type DataMessage, type DeepPartial, type IdGenerator, type JSONValue, type Message, type RequestOptions, type Schema, type StreamPart, type StreamString, type ToolInvocation, type UseAssistantOptions, type UseChatOptions, type UseCompletionOptions, asSchema, callChatApi, callCompletionApi, createChunkDecoder, formatStreamPart, getTextFromDataUrl, isDeepEqualData, jsonSchema, parsePartialJson, parseStreamPart, processDataProtocolResponse, readDataStream, zodSchema }; | ||
export { type AssistantMessage, type AssistantStatus, type AssistantStreamPart, type AssistantStreamString, type Attachment, type ChatRequest, type ChatRequestOptions, type CreateMessage, type DataMessage, type DataStreamPart, type DataStreamString, type DeepPartial, type IdGenerator, type JSONValue, type Message, type RequestOptions, type Schema, type ToolInvocation, type UseAssistantOptions, type UseChatOptions, type UseCompletionOptions, asSchema, callChatApi, callCompletionApi, formatAssistantStreamPart, formatDataStreamPart, getTextFromDataUrl, isDeepEqualData, jsonSchema, parseAssistantStreamPart, parseDataStreamPart, parsePartialJson, processAssistantStream, processDataStream, processTextStream, zodSchema }; |
@@ -36,4 +36,4 @@ "use strict"; | ||
callCompletionApi: () => callCompletionApi, | ||
createChunkDecoder: () => createChunkDecoder, | ||
formatStreamPart: () => formatStreamPart, | ||
formatAssistantStreamPart: () => formatAssistantStreamPart, | ||
formatDataStreamPart: () => formatDataStreamPart, | ||
generateId: () => import_provider_utils4.generateId, | ||
@@ -43,6 +43,8 @@ getTextFromDataUrl: () => getTextFromDataUrl, | ||
jsonSchema: () => jsonSchema, | ||
parseAssistantStreamPart: () => parseAssistantStreamPart, | ||
parseDataStreamPart: () => parseDataStreamPart, | ||
parsePartialJson: () => parsePartialJson, | ||
parseStreamPart: () => parseStreamPart, | ||
processDataProtocolResponse: () => processDataProtocolResponse, | ||
readDataStream: () => readDataStream, | ||
processAssistantStream: () => processAssistantStream, | ||
processDataStream: () => processDataStream, | ||
processTextStream: () => processTextStream, | ||
zodSchema: () => zodSchema | ||
@@ -53,3 +55,119 @@ }); | ||
// src/process-data-protocol-response.ts | ||
// src/assistant-stream-parts.ts | ||
var textStreamPart = { | ||
code: "0", | ||
name: "text", | ||
parse: (value) => { | ||
if (typeof value !== "string") { | ||
throw new Error('"text" parts expect a string value.'); | ||
} | ||
return { type: "text", value }; | ||
} | ||
}; | ||
var errorStreamPart = { | ||
code: "3", | ||
name: "error", | ||
parse: (value) => { | ||
if (typeof value !== "string") { | ||
throw new Error('"error" parts expect a string value.'); | ||
} | ||
return { type: "error", value }; | ||
} | ||
}; | ||
var assistantMessageStreamPart = { | ||
code: "4", | ||
name: "assistant_message", | ||
parse: (value) => { | ||
if (value == null || typeof value !== "object" || !("id" in value) || !("role" in value) || !("content" in value) || typeof value.id !== "string" || typeof value.role !== "string" || value.role !== "assistant" || !Array.isArray(value.content) || !value.content.every( | ||
(item) => item != null && typeof item === "object" && "type" in item && item.type === "text" && "text" in item && item.text != null && typeof item.text === "object" && "value" in item.text && typeof item.text.value === "string" | ||
)) { | ||
throw new Error( | ||
'"assistant_message" parts expect an object with an "id", "role", and "content" property.' | ||
); | ||
} | ||
return { | ||
type: "assistant_message", | ||
value | ||
}; | ||
} | ||
}; | ||
var assistantControlDataStreamPart = { | ||
code: "5", | ||
name: "assistant_control_data", | ||
parse: (value) => { | ||
if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") { | ||
throw new Error( | ||
'"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.' | ||
); | ||
} | ||
return { | ||
type: "assistant_control_data", | ||
value: { | ||
threadId: value.threadId, | ||
messageId: value.messageId | ||
} | ||
}; | ||
} | ||
}; | ||
var dataMessageStreamPart = { | ||
code: "6", | ||
name: "data_message", | ||
parse: (value) => { | ||
if (value == null || typeof value !== "object" || !("role" in value) || !("data" in value) || typeof value.role !== "string" || value.role !== "data") { | ||
throw new Error( | ||
'"data_message" parts expect an object with a "role" and "data" property.' | ||
); | ||
} | ||
return { | ||
type: "data_message", | ||
value | ||
}; | ||
} | ||
}; | ||
var assistantStreamParts = [ | ||
textStreamPart, | ||
errorStreamPart, | ||
assistantMessageStreamPart, | ||
assistantControlDataStreamPart, | ||
dataMessageStreamPart | ||
]; | ||
var assistantStreamPartsByCode = { | ||
[textStreamPart.code]: textStreamPart, | ||
[errorStreamPart.code]: errorStreamPart, | ||
[assistantMessageStreamPart.code]: assistantMessageStreamPart, | ||
[assistantControlDataStreamPart.code]: assistantControlDataStreamPart, | ||
[dataMessageStreamPart.code]: dataMessageStreamPart | ||
}; | ||
var StreamStringPrefixes = { | ||
[textStreamPart.name]: textStreamPart.code, | ||
[errorStreamPart.name]: errorStreamPart.code, | ||
[assistantMessageStreamPart.name]: assistantMessageStreamPart.code, | ||
[assistantControlDataStreamPart.name]: assistantControlDataStreamPart.code, | ||
[dataMessageStreamPart.name]: dataMessageStreamPart.code | ||
}; | ||
var validCodes = assistantStreamParts.map((part) => part.code); | ||
var parseAssistantStreamPart = (line) => { | ||
const firstSeparatorIndex = line.indexOf(":"); | ||
if (firstSeparatorIndex === -1) { | ||
throw new Error("Failed to parse stream string. No separator found."); | ||
} | ||
const prefix = line.slice(0, firstSeparatorIndex); | ||
if (!validCodes.includes(prefix)) { | ||
throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`); | ||
} | ||
const code = prefix; | ||
const textValue = line.slice(firstSeparatorIndex + 1); | ||
const jsonValue = JSON.parse(textValue); | ||
return assistantStreamPartsByCode[code].parse(jsonValue); | ||
}; | ||
function formatAssistantStreamPart(type, value) { | ||
const streamPart = assistantStreamParts.find((part) => part.name === type); | ||
if (!streamPart) { | ||
throw new Error(`Invalid stream part type: ${type}`); | ||
} | ||
return `${streamPart.code}:${JSON.stringify(value)} | ||
`; | ||
} | ||
// src/process-chat-response.ts | ||
var import_provider_utils2 = require("@ai-sdk/provider-utils"); | ||
@@ -394,4 +512,4 @@ | ||
// src/stream-parts.ts | ||
var textStreamPart = { | ||
// src/data-stream-parts.ts | ||
var textStreamPart2 = { | ||
code: "0", | ||
@@ -416,3 +534,3 @@ name: "text", | ||
}; | ||
var errorStreamPart = { | ||
var errorStreamPart2 = { | ||
code: "3", | ||
@@ -427,52 +545,2 @@ name: "error", | ||
}; | ||
var assistantMessageStreamPart = { | ||
code: "4", | ||
name: "assistant_message", | ||
parse: (value) => { | ||
if (value == null || typeof value !== "object" || !("id" in value) || !("role" in value) || !("content" in value) || typeof value.id !== "string" || typeof value.role !== "string" || value.role !== "assistant" || !Array.isArray(value.content) || !value.content.every( | ||
(item) => item != null && typeof item === "object" && "type" in item && item.type === "text" && "text" in item && item.text != null && typeof item.text === "object" && "value" in item.text && typeof item.text.value === "string" | ||
)) { | ||
throw new Error( | ||
'"assistant_message" parts expect an object with an "id", "role", and "content" property.' | ||
); | ||
} | ||
return { | ||
type: "assistant_message", | ||
value | ||
}; | ||
} | ||
}; | ||
var assistantControlDataStreamPart = { | ||
code: "5", | ||
name: "assistant_control_data", | ||
parse: (value) => { | ||
if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") { | ||
throw new Error( | ||
'"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.' | ||
); | ||
} | ||
return { | ||
type: "assistant_control_data", | ||
value: { | ||
threadId: value.threadId, | ||
messageId: value.messageId | ||
} | ||
}; | ||
} | ||
}; | ||
var dataMessageStreamPart = { | ||
code: "6", | ||
name: "data_message", | ||
parse: (value) => { | ||
if (value == null || typeof value !== "object" || !("role" in value) || !("data" in value) || typeof value.role !== "string" || value.role !== "data") { | ||
throw new Error( | ||
'"data_message" parts expect an object with a "role" and "data" property.' | ||
); | ||
} | ||
return { | ||
type: "data_message", | ||
value | ||
}; | ||
} | ||
}; | ||
var messageAnnotationsStreamPart = { | ||
@@ -600,9 +668,6 @@ code: "8", | ||
}; | ||
var streamParts = [ | ||
textStreamPart, | ||
var dataStreamParts = [ | ||
textStreamPart2, | ||
dataStreamPart, | ||
errorStreamPart, | ||
assistantMessageStreamPart, | ||
assistantControlDataStreamPart, | ||
dataMessageStreamPart, | ||
errorStreamPart2, | ||
messageAnnotationsStreamPart, | ||
@@ -616,9 +681,6 @@ toolCallStreamPart, | ||
]; | ||
var streamPartsByCode = { | ||
[textStreamPart.code]: textStreamPart, | ||
var dataStreamPartsByCode = { | ||
[textStreamPart2.code]: textStreamPart2, | ||
[dataStreamPart.code]: dataStreamPart, | ||
[errorStreamPart.code]: errorStreamPart, | ||
[assistantMessageStreamPart.code]: assistantMessageStreamPart, | ||
[assistantControlDataStreamPart.code]: assistantControlDataStreamPart, | ||
[dataMessageStreamPart.code]: dataMessageStreamPart, | ||
[errorStreamPart2.code]: errorStreamPart2, | ||
[messageAnnotationsStreamPart.code]: messageAnnotationsStreamPart, | ||
@@ -632,9 +694,6 @@ [toolCallStreamPart.code]: toolCallStreamPart, | ||
}; | ||
var StreamStringPrefixes = { | ||
[textStreamPart.name]: textStreamPart.code, | ||
var DataStreamStringPrefixes = { | ||
[textStreamPart2.name]: textStreamPart2.code, | ||
[dataStreamPart.name]: dataStreamPart.code, | ||
[errorStreamPart.name]: errorStreamPart.code, | ||
[assistantMessageStreamPart.name]: assistantMessageStreamPart.code, | ||
[assistantControlDataStreamPart.name]: assistantControlDataStreamPart.code, | ||
[dataMessageStreamPart.name]: dataMessageStreamPart.code, | ||
[errorStreamPart2.name]: errorStreamPart2.code, | ||
[messageAnnotationsStreamPart.name]: messageAnnotationsStreamPart.code, | ||
@@ -648,4 +707,4 @@ [toolCallStreamPart.name]: toolCallStreamPart.code, | ||
}; | ||
var validCodes = streamParts.map((part) => part.code); | ||
var parseStreamPart = (line) => { | ||
var validCodes2 = dataStreamParts.map((part) => part.code); | ||
var parseDataStreamPart = (line) => { | ||
const firstSeparatorIndex = line.indexOf(":"); | ||
@@ -656,3 +715,3 @@ if (firstSeparatorIndex === -1) { | ||
const prefix = line.slice(0, firstSeparatorIndex); | ||
if (!validCodes.includes(prefix)) { | ||
if (!validCodes2.includes(prefix)) { | ||
throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`); | ||
@@ -663,6 +722,6 @@ } | ||
const jsonValue = JSON.parse(textValue); | ||
return streamPartsByCode[code].parse(jsonValue); | ||
return dataStreamPartsByCode[code].parse(jsonValue); | ||
}; | ||
function formatStreamPart(type, value) { | ||
const streamPart = streamParts.find((part) => part.name === type); | ||
function formatDataStreamPart(type, value) { | ||
const streamPart = dataStreamParts.find((part) => part.name === type); | ||
if (!streamPart) { | ||
@@ -675,3 +734,3 @@ throw new Error(`Invalid stream part type: ${type}`); | ||
// src/read-data-stream.ts | ||
// src/process-data-stream.ts | ||
var NEWLINE = "\n".charCodeAt(0); | ||
@@ -688,5 +747,16 @@ function concatChunks(chunks, totalLength) { | ||
} | ||
async function* readDataStream(reader, { | ||
isAborted | ||
} = {}) { | ||
async function processDataStream({ | ||
stream, | ||
onTextPart, | ||
onDataPart, | ||
onErrorPart, | ||
onToolCallStreamingStartPart, | ||
onToolCallDeltaPart, | ||
onToolCallPart, | ||
onToolResultPart, | ||
onMessageAnnotationsPart, | ||
onFinishMessagePart, | ||
onFinishStepPart | ||
}) { | ||
const reader = stream.getReader(); | ||
const decoder = new TextDecoder(); | ||
@@ -709,22 +779,59 @@ const chunks = []; | ||
totalLength = 0; | ||
const streamParts2 = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseStreamPart); | ||
for (const streamPart of streamParts2) { | ||
yield streamPart; | ||
const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseDataStreamPart); | ||
for (const { type, value: value2 } of streamParts) { | ||
switch (type) { | ||
case "text": | ||
await (onTextPart == null ? void 0 : onTextPart(value2)); | ||
break; | ||
case "data": | ||
await (onDataPart == null ? void 0 : onDataPart(value2)); | ||
break; | ||
case "error": | ||
await (onErrorPart == null ? void 0 : onErrorPart(value2)); | ||
break; | ||
case "message_annotations": | ||
await (onMessageAnnotationsPart == null ? void 0 : onMessageAnnotationsPart(value2)); | ||
break; | ||
case "tool_call_streaming_start": | ||
await (onToolCallStreamingStartPart == null ? void 0 : onToolCallStreamingStartPart(value2)); | ||
break; | ||
case "tool_call_delta": | ||
await (onToolCallDeltaPart == null ? void 0 : onToolCallDeltaPart(value2)); | ||
break; | ||
case "tool_call": | ||
await (onToolCallPart == null ? void 0 : onToolCallPart(value2)); | ||
break; | ||
case "tool_result": | ||
await (onToolResultPart == null ? void 0 : onToolResultPart(value2)); | ||
break; | ||
case "finish_message": | ||
await (onFinishMessagePart == null ? void 0 : onFinishMessagePart(value2)); | ||
break; | ||
case "finish_step": | ||
await (onFinishStepPart == null ? void 0 : onFinishStepPart(value2)); | ||
break; | ||
default: { | ||
const exhaustiveCheck = type; | ||
throw new Error(`Unknown stream part type: ${exhaustiveCheck}`); | ||
} | ||
} | ||
} | ||
if (isAborted == null ? void 0 : isAborted()) { | ||
reader.cancel(); | ||
break; | ||
} | ||
} | ||
} | ||
// src/process-data-protocol-response.ts | ||
function assignAnnotationsToMessage(message, annotations) { | ||
if (!message || !annotations || !annotations.length) | ||
return message; | ||
return { ...message, annotations: [...annotations] }; | ||
// src/duplicated/usage.ts | ||
function calculateLanguageModelUsage({ | ||
promptTokens, | ||
completionTokens | ||
}) { | ||
return { | ||
promptTokens, | ||
completionTokens, | ||
totalTokens: promptTokens + completionTokens | ||
}; | ||
} | ||
async function processDataProtocolResponse({ | ||
reader, | ||
abortControllerRef, | ||
// src/process-chat-response.ts | ||
async function processChatResponse({ | ||
stream, | ||
update, | ||
@@ -736,6 +843,5 @@ onToolCall, | ||
}) { | ||
var _a; | ||
const createdAt = getCurrentDate(); | ||
let currentMessage = {}; | ||
let nextMessage = void 0; | ||
let currentMessage = void 0; | ||
let createNewMessage = true; | ||
const previousMessages = []; | ||
@@ -751,66 +857,53 @@ const data = []; | ||
let finishReason = "unknown"; | ||
for await (const { type, value } of readDataStream(reader, { | ||
isAborted: () => (abortControllerRef == null ? void 0 : abortControllerRef.current) === null | ||
})) { | ||
if (type === "error") { | ||
throw new Error(value); | ||
function execUpdate() { | ||
const copiedData = [...data]; | ||
if (currentMessage == null) { | ||
update(previousMessages, copiedData); | ||
return; | ||
} | ||
if (type === "finish_step") { | ||
if (!value.isContinued) { | ||
nextMessage = {}; | ||
} | ||
continue; | ||
if (messageAnnotations == null ? void 0 : messageAnnotations.length) { | ||
currentMessage.annotations = messageAnnotations; | ||
} | ||
if (type === "finish_message") { | ||
finishReason = value.finishReason; | ||
if (value.usage != null) { | ||
const { completionTokens, promptTokens } = value.usage; | ||
usage = { | ||
completionTokens, | ||
promptTokens, | ||
totalTokens: completionTokens + promptTokens | ||
}; | ||
const copiedMessage = { | ||
...currentMessage, | ||
revisionId: generateId2() | ||
}; | ||
update([...previousMessages, copiedMessage], copiedData); | ||
} | ||
function getMessage() { | ||
if (createNewMessage || currentMessage == null) { | ||
if (currentMessage != null) { | ||
previousMessages.push(currentMessage); | ||
} | ||
continue; | ||
createNewMessage = false; | ||
currentMessage = { | ||
id: generateId2(), | ||
role: "assistant", | ||
content: "", | ||
createdAt | ||
}; | ||
} | ||
if (nextMessage != null && (type === "text" || type === "tool_call" || type === "tool_call_streaming_start" || type === "tool_call_delta" || type === "tool_result")) { | ||
if (currentMessage.message) { | ||
previousMessages.push(currentMessage.message); | ||
return currentMessage; | ||
} | ||
await processDataStream({ | ||
stream, | ||
onTextPart(value) { | ||
const activeMessage = getMessage(); | ||
currentMessage = { | ||
...activeMessage, | ||
content: activeMessage.content + value | ||
}; | ||
execUpdate(); | ||
}, | ||
onToolCallStreamingStartPart(value) { | ||
const activeMessage = getMessage(); | ||
if (activeMessage.toolInvocations == null) { | ||
activeMessage.toolInvocations = []; | ||
} | ||
currentMessage = nextMessage; | ||
nextMessage = void 0; | ||
} | ||
if (type === "text") { | ||
if (currentMessage["message"]) { | ||
currentMessage["message"] = { | ||
...currentMessage["message"], | ||
content: (currentMessage["message"].content || "") + value | ||
}; | ||
} else { | ||
currentMessage["message"] = { | ||
id: generateId2(), | ||
role: "assistant", | ||
content: value, | ||
createdAt | ||
}; | ||
} | ||
} | ||
if (type === "tool_call_streaming_start") { | ||
if (currentMessage.message == null) { | ||
currentMessage.message = { | ||
id: generateId2(), | ||
role: "assistant", | ||
content: "", | ||
createdAt | ||
}; | ||
} | ||
if (currentMessage.message.toolInvocations == null) { | ||
currentMessage.message.toolInvocations = []; | ||
} | ||
partialToolCalls[value.toolCallId] = { | ||
text: "", | ||
toolName: value.toolName, | ||
prefixMapIndex: currentMessage.message.toolInvocations.length | ||
index: activeMessage.toolInvocations.length | ||
}; | ||
currentMessage.message.toolInvocations.push({ | ||
activeMessage.toolInvocations.push({ | ||
state: "partial-call", | ||
@@ -821,7 +914,10 @@ toolCallId: value.toolCallId, | ||
}); | ||
} else if (type === "tool_call_delta") { | ||
execUpdate(); | ||
}, | ||
onToolCallDeltaPart(value) { | ||
const activeMessage = getMessage(); | ||
const partialToolCall = partialToolCalls[value.toolCallId]; | ||
partialToolCall.text += value.argsTextDelta; | ||
const { value: partialArgs } = parsePartialJson(partialToolCall.text); | ||
currentMessage.message.toolInvocations[partialToolCall.prefixMapIndex] = { | ||
activeMessage.toolInvocations[partialToolCall.index] = { | ||
state: "partial-call", | ||
@@ -832,19 +928,13 @@ toolCallId: value.toolCallId, | ||
}; | ||
currentMessage.message.internalUpdateId = generateId2(); | ||
} else if (type === "tool_call") { | ||
execUpdate(); | ||
}, | ||
async onToolCallPart(value) { | ||
const activeMessage = getMessage(); | ||
if (partialToolCalls[value.toolCallId] != null) { | ||
currentMessage.message.toolInvocations[partialToolCalls[value.toolCallId].prefixMapIndex] = { state: "call", ...value }; | ||
activeMessage.toolInvocations[partialToolCalls[value.toolCallId].index] = { state: "call", ...value }; | ||
} else { | ||
if (currentMessage.message == null) { | ||
currentMessage.message = { | ||
id: generateId2(), | ||
role: "assistant", | ||
content: "", | ||
createdAt | ||
}; | ||
if (activeMessage.toolInvocations == null) { | ||
activeMessage.toolInvocations = []; | ||
} | ||
if (currentMessage.message.toolInvocations == null) { | ||
currentMessage.message.toolInvocations = []; | ||
} | ||
currentMessage.message.toolInvocations.push({ | ||
activeMessage.toolInvocations.push({ | ||
state: "call", | ||
@@ -854,11 +944,13 @@ ...value | ||
} | ||
currentMessage.message.internalUpdateId = generateId2(); | ||
if (onToolCall) { | ||
const result = await onToolCall({ toolCall: value }); | ||
if (result != null) { | ||
currentMessage.message.toolInvocations[currentMessage.message.toolInvocations.length - 1] = { state: "result", ...value, result }; | ||
activeMessage.toolInvocations[activeMessage.toolInvocations.length - 1] = { state: "result", ...value, result }; | ||
} | ||
} | ||
} else if (type === "tool_result") { | ||
const toolInvocations = (_a = currentMessage.message) == null ? void 0 : _a.toolInvocations; | ||
execUpdate(); | ||
}, | ||
onToolResultPart(value) { | ||
const activeMessage = getMessage(); | ||
const toolInvocations = activeMessage.toolInvocations; | ||
if (toolInvocations == null) { | ||
@@ -880,8 +972,10 @@ throw new Error("tool_result must be preceded by a tool_call"); | ||
}; | ||
} | ||
if (type === "data") { | ||
execUpdate(); | ||
}, | ||
onDataPart(value) { | ||
data.push(...value); | ||
} | ||
if (type === "message_annotations") { | ||
if (!messageAnnotations) { | ||
execUpdate(); | ||
}, | ||
onMessageAnnotationsPart(value) { | ||
if (messageAnnotations == null) { | ||
messageAnnotations = [...value]; | ||
@@ -891,23 +985,33 @@ } else { | ||
} | ||
currentMessage.message = assignAnnotationsToMessage( | ||
currentMessage.message, | ||
messageAnnotations | ||
); | ||
if (currentMessage.message != null) { | ||
currentMessage.message.internalUpdateId = generateId2(); | ||
execUpdate(); | ||
}, | ||
onFinishStepPart(value) { | ||
createNewMessage = !value.isContinued; | ||
}, | ||
onFinishMessagePart(value) { | ||
finishReason = value.finishReason; | ||
if (value.usage != null) { | ||
usage = calculateLanguageModelUsage(value.usage); | ||
} | ||
}, | ||
onErrorPart(error) { | ||
throw new Error(error); | ||
} | ||
if ((messageAnnotations == null ? void 0 : messageAnnotations.length) && currentMessage.message) { | ||
currentMessage.message.annotations = [...messageAnnotations]; | ||
}); | ||
onFinish == null ? void 0 : onFinish({ message: currentMessage, finishReason, usage }); | ||
} | ||
// src/process-text-stream.ts | ||
async function processTextStream({ | ||
stream, | ||
onTextPart | ||
}) { | ||
const reader = stream.pipeThrough(new TextDecoderStream()).getReader(); | ||
while (true) { | ||
const { done, value } = await reader.read(); | ||
if (done) { | ||
break; | ||
} | ||
const merged = [currentMessage.message].filter(Boolean).map((message) => ({ | ||
...assignAnnotationsToMessage(message, messageAnnotations) | ||
})); | ||
update([...previousMessages, ...merged], [...data]); | ||
await onTextPart(value); | ||
} | ||
onFinish == null ? void 0 : onFinish({ message: currentMessage.message, finishReason, usage }); | ||
return { | ||
messages: [currentMessage.message].filter(Boolean), | ||
data | ||
}; | ||
} | ||
@@ -962,6 +1066,4 @@ | ||
} | ||
const reader = response.body.getReader(); | ||
switch (streamProtocol) { | ||
case "text": { | ||
const decoder = createChunkDecoder(); | ||
const resultMessage = { | ||
@@ -973,14 +1075,9 @@ id: generateId2(), | ||
}; | ||
while (true) { | ||
const { done, value } = await reader.read(); | ||
if (done) { | ||
break; | ||
await processTextStream({ | ||
stream: response.body, | ||
onTextPart: (chunk) => { | ||
resultMessage.content += chunk; | ||
onUpdate([{ ...resultMessage }], []); | ||
} | ||
resultMessage.content += decoder(value); | ||
onUpdate([{ ...resultMessage }], []); | ||
if ((abortController == null ? void 0 : abortController()) === null) { | ||
reader.cancel(); | ||
break; | ||
} | ||
} | ||
}); | ||
onFinish == null ? void 0 : onFinish(resultMessage, { | ||
@@ -990,11 +1087,7 @@ usage: { completionTokens: NaN, promptTokens: NaN, totalTokens: NaN }, | ||
}); | ||
return { | ||
messages: [resultMessage], | ||
data: [] | ||
}; | ||
return; | ||
} | ||
case "data": { | ||
return await processDataProtocolResponse({ | ||
reader, | ||
abortControllerRef: abortController != null ? { current: abortController() } : void 0, | ||
await processChatResponse({ | ||
stream: response.body, | ||
update: onUpdate, | ||
@@ -1009,2 +1102,3 @@ onToolCall, | ||
}); | ||
return; | ||
} | ||
@@ -1037,2 +1131,3 @@ default: { | ||
}) { | ||
var _a; | ||
try { | ||
@@ -1044,3 +1139,3 @@ setLoading(true); | ||
setCompletion(""); | ||
const res = await fetch2(api, { | ||
const response = await fetch2(api, { | ||
method: "POST", | ||
@@ -1062,3 +1157,3 @@ body: JSON.stringify({ | ||
try { | ||
await onResponse(res); | ||
await onResponse(response); | ||
} catch (err) { | ||
@@ -1068,45 +1163,36 @@ throw err; | ||
} | ||
if (!res.ok) { | ||
if (!response.ok) { | ||
throw new Error( | ||
await res.text() || "Failed to fetch the chat response." | ||
(_a = await response.text()) != null ? _a : "Failed to fetch the chat response." | ||
); | ||
} | ||
if (!res.body) { | ||
if (!response.body) { | ||
throw new Error("The response body is empty."); | ||
} | ||
let result = ""; | ||
const reader = res.body.getReader(); | ||
switch (streamProtocol) { | ||
case "text": { | ||
const decoder = createChunkDecoder(); | ||
while (true) { | ||
const { done, value } = await reader.read(); | ||
if (done) { | ||
break; | ||
await processTextStream({ | ||
stream: response.body, | ||
onTextPart: (chunk) => { | ||
result += chunk; | ||
setCompletion(result); | ||
} | ||
result += decoder(value); | ||
setCompletion(result); | ||
if (abortController === null) { | ||
reader.cancel(); | ||
break; | ||
} | ||
} | ||
}); | ||
break; | ||
} | ||
case "data": { | ||
for await (const { type, value } of readDataStream(reader, { | ||
isAborted: () => abortController === null | ||
})) { | ||
switch (type) { | ||
case "text": { | ||
result += value; | ||
setCompletion(result); | ||
break; | ||
} | ||
case "data": { | ||
onData == null ? void 0 : onData(value); | ||
break; | ||
} | ||
await processDataStream({ | ||
stream: response.body, | ||
onTextPart(value) { | ||
result += value; | ||
setCompletion(result); | ||
}, | ||
onDataPart(value) { | ||
onData == null ? void 0 : onData(value); | ||
}, | ||
onErrorPart(value) { | ||
throw new Error(value); | ||
} | ||
} | ||
}); | ||
break; | ||
@@ -1140,18 +1226,2 @@ } | ||
// src/create-chunk-decoder.ts | ||
function createChunkDecoder(complex) { | ||
const decoder = new TextDecoder(); | ||
if (!complex) { | ||
return function(chunk) { | ||
if (!chunk) | ||
return ""; | ||
return decoder.decode(chunk, { stream: true }); | ||
}; | ||
} | ||
return function(chunk) { | ||
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== ""); | ||
return decoded.map(parseStreamPart).filter(Boolean); | ||
}; | ||
} | ||
// src/data-url.ts | ||
@@ -1206,2 +1276,43 @@ function getTextFromDataUrl(dataUrl) { | ||
// src/process-assistant-stream.ts | ||
var NEWLINE2 = "\n".charCodeAt(0); | ||
function concatChunks2(chunks, totalLength) { | ||
const concatenatedChunks = new Uint8Array(totalLength); | ||
let offset = 0; | ||
for (const chunk of chunks) { | ||
concatenatedChunks.set(chunk, offset); | ||
offset += chunk.length; | ||
} | ||
chunks.length = 0; | ||
return concatenatedChunks; | ||
} | ||
async function processAssistantStream({ | ||
stream, | ||
onStreamPart | ||
}) { | ||
const reader = stream.getReader(); | ||
const decoder = new TextDecoder(); | ||
const chunks = []; | ||
let totalLength = 0; | ||
while (true) { | ||
const { value } = await reader.read(); | ||
if (value) { | ||
chunks.push(value); | ||
totalLength += value.length; | ||
if (value[value.length - 1] !== NEWLINE2) { | ||
continue; | ||
} | ||
} | ||
if (chunks.length === 0) { | ||
break; | ||
} | ||
const concatenatedChunks = concatChunks2(chunks, totalLength); | ||
totalLength = 0; | ||
const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseAssistantStreamPart); | ||
for (const streamPart of streamParts) { | ||
await onStreamPart(streamPart); | ||
} | ||
} | ||
} | ||
// src/schema.ts | ||
@@ -1246,4 +1357,4 @@ var import_provider_utils3 = require("@ai-sdk/provider-utils"); | ||
callCompletionApi, | ||
createChunkDecoder, | ||
formatStreamPart, | ||
formatAssistantStreamPart, | ||
formatDataStreamPart, | ||
generateId, | ||
@@ -1253,8 +1364,10 @@ getTextFromDataUrl, | ||
jsonSchema, | ||
parseAssistantStreamPart, | ||
parseDataStreamPart, | ||
parsePartialJson, | ||
parseStreamPart, | ||
processDataProtocolResponse, | ||
readDataStream, | ||
processAssistantStream, | ||
processDataStream, | ||
processTextStream, | ||
zodSchema | ||
}); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@ai-sdk/ui-utils", | ||
"version": "1.0.0-canary.7", | ||
"version": "1.0.0-canary.8", | ||
"license": "Apache-2.0", | ||
@@ -5,0 +5,0 @@ "sideEffects": false, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
315542
3513