Refactor UUID generation, remove unused logger and encryption utilities, and clean up request handling
- Updated `generateUUID` function for improved readability and performance. - Deleted `logger.ts`, `other.ts`, `request.ts`, `storage.ts`, `tansParams.ts`, and `validate.ts` as they were no longer needed. - Simplified TypeScript configuration by removing unnecessary paths and aliases. - Enhanced Vite configuration for better project structure and maintainability.
This commit is contained in:
173
runtime-shared/shared/chat-model.ts
Normal file
173
runtime-shared/shared/chat-model.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
export interface AttachedFileMeta {
|
||||
fileName: string;
|
||||
mimeType: string;
|
||||
fileSize: number;
|
||||
preview: string | null;
|
||||
filePath?: string;
|
||||
source?: 'user-upload' | 'tool-result' | 'message-ref';
|
||||
}
|
||||
|
||||
export interface ContentBlockSource {
|
||||
type: string;
|
||||
media_type?: string;
|
||||
data?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface ContentBlock {
|
||||
type: 'text' | 'image' | 'thinking' | 'tool_use' | 'tool_result' | 'toolCall' | 'toolResult';
|
||||
text?: string;
|
||||
thinking?: string;
|
||||
source?: ContentBlockSource;
|
||||
data?: string;
|
||||
mimeType?: string;
|
||||
id?: string;
|
||||
name?: string;
|
||||
input?: unknown;
|
||||
arguments?: unknown;
|
||||
content?: string | ContentBlock[];
|
||||
}
|
||||
|
||||
export type RawMessageRole = 'user' | 'assistant' | 'system' | 'toolresult' | 'tool_result';
|
||||
|
||||
export interface RawMessage {
|
||||
role: RawMessageRole;
|
||||
content: string | ContentBlock[];
|
||||
timestamp?: number;
|
||||
id?: string;
|
||||
toolCallId?: string;
|
||||
toolName?: string;
|
||||
details?: unknown;
|
||||
isError?: boolean;
|
||||
question?: string[];
|
||||
toolCall?: Record<string, unknown> | null;
|
||||
_attachedFiles?: AttachedFileMeta[];
|
||||
}
|
||||
|
||||
export interface ToolStatus {
|
||||
id?: string;
|
||||
toolCallId?: string;
|
||||
name: string;
|
||||
status: 'running' | 'completed' | 'error';
|
||||
durationMs?: number;
|
||||
summary?: string;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export interface ChatSession {
|
||||
key: string;
|
||||
label?: string;
|
||||
displayName?: string;
|
||||
thinkingLevel?: string;
|
||||
model?: string;
|
||||
updatedAt?: number;
|
||||
}
|
||||
|
||||
export function extractText(message?: RawMessage | null): string {
|
||||
if (!message) return '';
|
||||
|
||||
if (typeof message.content === 'string') {
|
||||
return message.content;
|
||||
}
|
||||
|
||||
return message.content
|
||||
.filter((block) => block.type === 'text' && typeof block.text === 'string')
|
||||
.map((block) => block.text ?? '')
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
export function extractThinking(message?: RawMessage | null): string | null {
|
||||
if (!message || !Array.isArray(message.content)) return null;
|
||||
|
||||
const thinkingBlock = message.content.find((block) => block.type === 'thinking');
|
||||
return thinkingBlock?.thinking ?? null;
|
||||
}
|
||||
|
||||
export function extractImages(message?: RawMessage | null): Array<{ url?: string; data?: string; mimeType: string }> {
|
||||
if (!message || !Array.isArray(message.content)) return [];
|
||||
|
||||
const images: Array<{ url?: string; data?: string; mimeType: string }> = [];
|
||||
|
||||
for (const block of message.content) {
|
||||
if (block.type === 'image') {
|
||||
if (block.source?.type === 'base64' && block.source.data) {
|
||||
images.push({
|
||||
data: block.source.data,
|
||||
mimeType: block.source.media_type || 'image/jpeg',
|
||||
});
|
||||
} else if (block.source?.type === 'url' && block.source.url) {
|
||||
images.push({
|
||||
url: block.source.url,
|
||||
mimeType: block.source.media_type || 'image/jpeg',
|
||||
});
|
||||
} else if (block.data) {
|
||||
images.push({
|
||||
data: block.data,
|
||||
mimeType: block.mimeType || 'image/jpeg',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ((block.type === 'tool_result' || block.type === 'toolResult') && Array.isArray(block.content)) {
|
||||
images.push(...extractImages({ role: 'toolresult', content: block.content }));
|
||||
}
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
export function extractToolUse(message?: RawMessage | null): Array<{ id?: string; name: string; input?: unknown }> {
|
||||
if (!message || !Array.isArray(message.content)) return [];
|
||||
|
||||
return message.content
|
||||
.filter((block) => block.type === 'tool_use' || block.type === 'toolCall')
|
||||
.map((block) => ({
|
||||
id: block.id,
|
||||
name: block.name || block.id || 'tool',
|
||||
input: block.input ?? block.arguments,
|
||||
}));
|
||||
}
|
||||
|
||||
export function formatTimestamp(ts?: number): string {
|
||||
if (!ts) return '';
|
||||
|
||||
const ms = ts < 1e12 ? ts * 1000 : ts;
|
||||
return new Date(ms).toLocaleString();
|
||||
}
|
||||
|
||||
export function isToolResultRole(role?: string): boolean {
|
||||
if (!role) return false;
|
||||
|
||||
const normalized = role.toLowerCase();
|
||||
return normalized === 'toolresult' || normalized === 'tool_result';
|
||||
}
|
||||
|
||||
export function isToolOnlyMessage(message?: RawMessage): boolean {
|
||||
if (!message) return false;
|
||||
if (isToolResultRole(message.role)) return true;
|
||||
if (!Array.isArray(message.content)) return false;
|
||||
|
||||
const hasToolBlock = message.content.some((block) =>
|
||||
['tool_use', 'tool_result', 'toolCall', 'toolResult'].includes(block.type),
|
||||
);
|
||||
const hasTextBlock = message.content.some((block) => block.type === 'text' && block.text?.trim());
|
||||
const hasImageBlock = message.content.some((block) => block.type === 'image');
|
||||
|
||||
return hasToolBlock && !hasTextBlock && !hasImageBlock;
|
||||
}
|
||||
|
||||
export function isInternalMessage(message: { role?: string; content?: unknown }): boolean {
|
||||
if (message.role === 'system') return true;
|
||||
|
||||
if (message.role === 'assistant') {
|
||||
const text = typeof message.content === 'string'
|
||||
? message.content
|
||||
: extractText(message as RawMessage);
|
||||
|
||||
if (/^(HEARTBEAT_OK|NO_REPLY)\s*$/.test(text)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user