From 9b8214cdd4d287c6e560706a08d07ecfb310f2b1 Mon Sep 17 00:00:00 2001 From: DEV_DSW <562304744@qq.com> Date: Wed, 22 Apr 2026 09:16:40 +0800 Subject: [PATCH] refactor: remove unused runAgentService and consolidate chat model functions --- PROJECT_OVERVIEW.md | 1 - electron/process/runAgentService.ts | 0 runtime-shared/shared/chat-model.ts | 109 --------------------------- src/shared/chat-model.ts | 111 ++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 110 deletions(-) delete mode 100644 electron/process/runAgentService.ts diff --git a/PROJECT_OVERVIEW.md b/PROJECT_OVERVIEW.md index f0df9d2..b3990c0 100644 --- a/PROJECT_OVERVIEW.md +++ b/PROJECT_OVERVIEW.md @@ -19,7 +19,6 @@ * **`process/`**: 包含核心业务逻辑。 * `runTaskOperationService.ts`: 管理任务操作,启动本地 Chrome,并执行自动化脚本。 - * `runAgentService.ts`: AI Agent 执行的占位符/入口。 * **`service/`**: 各种功能的模块化服务。 * `execute-script-service/`: 启动 Node.js 子进程以安全地运行自动化脚本。 * `config-service/`: 管理应用程序配置。 diff --git a/electron/process/runAgentService.ts b/electron/process/runAgentService.ts deleted file mode 100644 index e69de29..0000000 diff --git a/runtime-shared/shared/chat-model.ts b/runtime-shared/shared/chat-model.ts index 9f60973..d4676bf 100644 --- a/runtime-shared/shared/chat-model.ts +++ b/runtime-shared/shared/chat-model.ts @@ -62,112 +62,3 @@ export interface ChatSession { 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; -} diff --git a/src/shared/chat-model.ts b/src/shared/chat-model.ts index e3b371e..7249991 100644 --- a/src/shared/chat-model.ts +++ b/src/shared/chat-model.ts @@ -1 +1,112 @@ +import type { RawMessage } from '../../runtime-shared/shared/chat-model'; + export * from '../../runtime-shared/shared/chat-model'; + +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; +}