chore: merge with web UI project

This commit is contained in:
Li Xin
2025-04-17 12:02:23 +08:00
parent 3aebb67e2b
commit fd7a803753
58 changed files with 10290 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
export * from "./types";
export * from "./merge-message";

View File

@@ -0,0 +1,93 @@
import type {
ChatEvent,
InterruptEvent,
MessageChunkEvent,
ToolCallChunksEvent,
ToolCallResultEvent,
ToolCallsEvent,
} from "../api";
import { deepClone } from "../utils/deep-clone";
import type { Message } from "./types";
export function mergeMessage(message: Message, event: ChatEvent) {
if (event.type === "message_chunk") {
mergeTextMessage(message, event);
} else if (event.type === "tool_calls" || event.type === "tool_call_chunks") {
mergeToolCallMessage(message, event);
} else if (event.type === "tool_call_result") {
mergeToolCallResultMessage(message, event);
} else if (event.type === "interrupt") {
mergeInterruptMessage(message, event);
}
if (event.data.finish_reason) {
message.finishReason = event.data.finish_reason;
message.isStreaming = false;
if (message.toolCalls) {
message.toolCalls.forEach((toolCall) => {
if (toolCall.argsChunks?.length) {
toolCall.args = JSON.parse(toolCall.argsChunks.join(""));
delete toolCall.argsChunks;
}
});
}
}
return deepClone(message);
}
function mergeTextMessage(message: Message, event: MessageChunkEvent) {
if (event.data.content) {
message.content += event.data.content;
message.contentChunks.push(event.data.content);
}
}
function mergeToolCallMessage(
message: Message,
event: ToolCallsEvent | ToolCallChunksEvent,
) {
if (event.type === "tool_calls" && event.data.tool_calls[0]?.name) {
message.toolCalls = event.data.tool_calls.map((raw) => ({
id: raw.id,
name: raw.name,
args: raw.args,
result: undefined,
}));
}
message.toolCalls ??= [];
for (const chunk of event.data.tool_call_chunks) {
if (chunk.id) {
const toolCall = message.toolCalls.find(
(toolCall) => toolCall.id === chunk.id,
);
if (toolCall) {
toolCall.argsChunks = [chunk.args];
}
} else {
const streamingToolCall = message.toolCalls.find(
(toolCall) => toolCall.argsChunks?.length,
);
if (streamingToolCall) {
streamingToolCall.argsChunks!.push(chunk.args);
}
}
}
}
function mergeToolCallResultMessage(
message: Message,
event: ToolCallResultEvent,
) {
const toolCall = message.toolCalls?.find(
(toolCall) => toolCall.id === event.data.tool_call_id,
);
if (toolCall) {
toolCall.result = event.data.content;
}
}
function mergeInterruptMessage(message: Message, event: InterruptEvent) {
message.isStreaming = false;
message.options = event.data.options;
}

View File

@@ -0,0 +1,28 @@
export type MessageRole = "user" | "assistant" | "tool";
export interface Message {
id: string;
threadId: string;
agent?: "coordinator" | "planner" | "researcher" | "coder" | "reporter";
role: MessageRole;
isStreaming?: boolean;
content: string;
contentChunks: string[];
toolCalls?: ToolCallRuntime[];
options?: Option[];
finishReason?: "stop" | "interrupt" | "tool_calls";
interruptFeedback?: string;
}
export interface Option {
text: string;
value: string;
}
export interface ToolCallRuntime {
id: string;
name: string;
args: Record<string, unknown>;
argsChunks?: string[];
result?: string;
}