106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
|
|
import type { AssistantMessageKind, ChatMessage } from "../../store/chat.ts"
|
||
|
|
import { parseToolCallsFromContent, parseToolCallsValue } from "./tool-calls.ts"
|
||
|
|
|
||
|
|
type AssistantToolCalls = ChatMessage["toolCalls"]
|
||
|
|
type ExistingAssistantMessageState = Pick<ChatMessage, "kind" | "toolCalls">
|
||
|
|
|
||
|
|
export interface AssistantMessageCreateState {
|
||
|
|
content: string
|
||
|
|
kind: AssistantMessageKind
|
||
|
|
toolCalls?: AssistantToolCalls
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface AssistantMessageUpdateState {
|
||
|
|
content: string
|
||
|
|
kind?: AssistantMessageKind
|
||
|
|
toolCalls?: AssistantToolCalls
|
||
|
|
}
|
||
|
|
|
||
|
|
function parseAssistantMessageKind(
|
||
|
|
payload: Record<string, unknown>,
|
||
|
|
toolCalls?: AssistantToolCalls,
|
||
|
|
): AssistantMessageKind {
|
||
|
|
if (payload.thought === true) {
|
||
|
|
return "thought"
|
||
|
|
}
|
||
|
|
if (payload.kind === "tool_calls" || toolCalls) {
|
||
|
|
return "tool_calls"
|
||
|
|
}
|
||
|
|
return "normal"
|
||
|
|
}
|
||
|
|
|
||
|
|
function hasExplicitAssistantKindPayload(
|
||
|
|
payload: Record<string, unknown>,
|
||
|
|
): boolean {
|
||
|
|
return (
|
||
|
|
typeof payload.thought === "boolean" ||
|
||
|
|
payload.kind === "tool_calls" ||
|
||
|
|
payload.tool_calls !== undefined
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
function parseAssistantToolCalls(
|
||
|
|
payload: Record<string, unknown>,
|
||
|
|
content: string,
|
||
|
|
): AssistantToolCalls {
|
||
|
|
return (
|
||
|
|
parseToolCallsValue(payload.tool_calls) ??
|
||
|
|
parseToolCallsFromContent(content)
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
export function parseAssistantMessageCreateState(
|
||
|
|
payload: Record<string, unknown>,
|
||
|
|
): AssistantMessageCreateState {
|
||
|
|
const content = typeof payload.content === "string" ? payload.content : ""
|
||
|
|
const toolCalls = parseAssistantToolCalls(payload, content)
|
||
|
|
|
||
|
|
return {
|
||
|
|
content,
|
||
|
|
kind: parseAssistantMessageKind(payload, toolCalls),
|
||
|
|
toolCalls,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function parseAssistantMessageUpdateState(
|
||
|
|
payload: Record<string, unknown>,
|
||
|
|
existing?: ExistingAssistantMessageState,
|
||
|
|
): AssistantMessageUpdateState {
|
||
|
|
const content = typeof payload.content === "string" ? payload.content : ""
|
||
|
|
const toolCalls = parseAssistantToolCalls(payload, content)
|
||
|
|
|
||
|
|
if (hasExplicitAssistantKindPayload(payload)) {
|
||
|
|
const kind = parseAssistantMessageKind(payload, toolCalls)
|
||
|
|
return {
|
||
|
|
content,
|
||
|
|
kind,
|
||
|
|
toolCalls: kind === "tool_calls" ? toolCalls : undefined,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (toolCalls) {
|
||
|
|
return {
|
||
|
|
content,
|
||
|
|
kind: "tool_calls",
|
||
|
|
toolCalls,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (existing?.kind === "thought" || existing?.kind === "tool_calls") {
|
||
|
|
return {
|
||
|
|
content,
|
||
|
|
kind: "normal",
|
||
|
|
toolCalls: undefined,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (existing?.toolCalls) {
|
||
|
|
return {
|
||
|
|
content,
|
||
|
|
toolCalls: undefined,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return { content }
|
||
|
|
}
|