diff --git a/tools/server/webui/src/lib/clients/agentic.client.ts b/tools/server/webui/src/lib/clients/agentic.client.ts index 439fae7f2d..e94f396e39 100644 --- a/tools/server/webui/src/lib/clients/agentic.client.ts +++ b/tools/server/webui/src/lib/clients/agentic.client.ts @@ -26,8 +26,8 @@ import { mcpClient } from '$lib/clients'; import { ChatService } from '$lib/services'; import { config } from '$lib/stores/settings.svelte'; -import { getAgenticConfig, toAgenticMessages } from '$lib/utils'; -import type { AgenticMessage, AgenticToolCallList } from '$lib/types/agentic'; +import { agenticStore } from '$lib/stores/agentic.svelte'; +import type { AgenticMessage, AgenticToolCallList, AgenticConfig } from '$lib/types/agentic'; import type { ApiChatCompletionToolCall, ApiChatMessageData, @@ -49,6 +49,45 @@ import type { } from '$lib/types/database'; import { AttachmentType, MessageRole } from '$lib/enums'; +/** + * Converts API messages to agentic format. + */ +function toAgenticMessages(messages: ApiChatMessageData[]): AgenticMessage[] { + return messages.map((message) => { + if ( + message.role === MessageRole.ASSISTANT && + message.tool_calls && + message.tool_calls.length > 0 + ) { + return { + role: MessageRole.ASSISTANT, + content: message.content, + tool_calls: message.tool_calls.map((call, index) => ({ + id: call.id ?? `call_${index}`, + type: (call.type as 'function') ?? 'function', + function: { + name: call.function?.name ?? '', + arguments: call.function?.arguments ?? '' + } + })) + } satisfies AgenticMessage; + } + + if (message.role === MessageRole.TOOL && message.tool_call_id) { + return { + role: MessageRole.TOOL, + tool_call_id: message.tool_call_id, + content: typeof message.content === 'string' ? message.content : '' + } satisfies AgenticMessage; + } + + return { + role: message.role as MessageRole.SYSTEM | MessageRole.USER, + content: message.content + } satisfies AgenticMessage; + }); +} + export interface AgenticFlowCallbacks { onChunk?: (chunk: string) => void; onReasoningChunk?: (chunk: string) => void; @@ -158,7 +197,7 @@ export class AgenticClient { } = callbacks; // Get agentic configuration (considering per-chat MCP overrides) - const agenticConfig = getAgenticConfig(config(), perChatOverrides); + const agenticConfig = agenticStore.getConfig(config(), perChatOverrides); if (!agenticConfig.enabled) { return { handled: false }; } @@ -243,7 +282,7 @@ export class AgenticClient { messages: ApiChatMessageData[]; options: AgenticFlowOptions; tools: ReturnType; - agenticConfig: ReturnType; + agenticConfig: AgenticConfig; callbacks: AgenticFlowCallbacks; signal?: AbortSignal; }): Promise { diff --git a/tools/server/webui/src/lib/clients/chat.client.ts b/tools/server/webui/src/lib/clients/chat.client.ts index 12e11bea10..15097e130b 100644 --- a/tools/server/webui/src/lib/clients/chat.client.ts +++ b/tools/server/webui/src/lib/clients/chat.client.ts @@ -12,9 +12,9 @@ import { normalizeModelName, filterByLeafNodeId, findDescendantMessages, - findLeafNode, - getAgenticConfig + findLeafNode } from '$lib/utils'; +import { agenticStore } from '$lib/stores/agentic.svelte'; import { DEFAULT_CONTEXT } from '$lib/constants/default-context'; import { SYSTEM_MESSAGE_PLACEHOLDER } from '$lib/constants/ui'; import { REASONING_TAGS } from '$lib/constants/agentic'; @@ -687,7 +687,7 @@ export class ChatClient { }; const perChatOverrides = conversationsStore.activeConversation?.mcpServerOverrides; - const agenticConfig = getAgenticConfig(config(), perChatOverrides); + const agenticConfig = agenticStore.getConfig(config(), perChatOverrides); if (agenticConfig.enabled) { const agenticResult = await agenticClient.runAgenticFlow({ conversationId: assistantMessage.convId, diff --git a/tools/server/webui/src/lib/stores/agentic.svelte.ts b/tools/server/webui/src/lib/stores/agentic.svelte.ts index a85f300125..9af1d67afb 100644 --- a/tools/server/webui/src/lib/stores/agentic.svelte.ts +++ b/tools/server/webui/src/lib/stores/agentic.svelte.ts @@ -27,7 +27,11 @@ import { browser } from '$app/environment'; import type { AgenticFlowParams, AgenticFlowResult } from '$lib/clients'; -import type { AgenticSession } from '$lib/types/agentic'; +import type { AgenticSession, AgenticConfig } from '$lib/types/agentic'; +import type { SettingsConfigType } from '$lib/types/settings'; +import type { McpServerOverride } from '$lib/types/database'; +import { DEFAULT_AGENTIC_CONFIG } from '$lib/constants/agentic'; +import { mcpStore } from '$lib/stores/mcp.svelte'; import { agenticClient } from '$lib/clients/agentic.client'; export type { @@ -212,6 +216,30 @@ class AgenticStore { clearError(conversationId: string): void { this.updateSession(conversationId, { lastError: null }); } + + /** + * + * Configuration + * + */ + + /** + * Gets the current agentic configuration. + * Automatically disables agentic mode if no MCP servers are configured. + * @param settings - Global settings configuration + * @param perChatOverrides - Optional per-chat MCP server overrides + */ + getConfig(settings: SettingsConfigType, perChatOverrides?: McpServerOverride[]): AgenticConfig { + const maxTurns = Number(settings.agenticMaxTurns) || DEFAULT_AGENTIC_CONFIG.maxTurns; + const maxToolPreviewLines = + Number(settings.agenticMaxToolPreviewLines) || DEFAULT_AGENTIC_CONFIG.maxToolPreviewLines; + + return { + enabled: mcpStore.hasEnabledServers(perChatOverrides) && DEFAULT_AGENTIC_CONFIG.enabled, + maxTurns, + maxToolPreviewLines + }; + } } export const agenticStore = new AgenticStore(); diff --git a/tools/server/webui/src/lib/utils/agentic.ts b/tools/server/webui/src/lib/utils/agentic.ts deleted file mode 100644 index d458fc1e4a..0000000000 --- a/tools/server/webui/src/lib/utils/agentic.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { ApiChatMessageData } from '$lib/types/api'; -import type { AgenticMessage, AgenticConfig } from '$lib/types/agentic'; -import type { SettingsConfigType } from '$lib/types/settings'; -import type { McpServerOverride } from '$lib/types/database'; -import { DEFAULT_AGENTIC_CONFIG } from '$lib/constants/agentic'; -import { mcpStore } from '$lib/stores/mcp.svelte'; -import { MessageRole } from '$lib/enums'; - -/** - * Gets the current agentic configuration. - * Automatically disables agentic mode if no MCP servers are configured. - * @param settings - Global settings configuration - * @param perChatOverrides - Optional per-chat MCP server overrides - */ -export function getAgenticConfig( - settings: SettingsConfigType, - perChatOverrides?: McpServerOverride[] -): AgenticConfig { - const maxTurns = Number(settings.agenticMaxTurns) || DEFAULT_AGENTIC_CONFIG.maxTurns; - const maxToolPreviewLines = - Number(settings.agenticMaxToolPreviewLines) || DEFAULT_AGENTIC_CONFIG.maxToolPreviewLines; - - return { - enabled: mcpStore.hasEnabledServers(perChatOverrides) && DEFAULT_AGENTIC_CONFIG.enabled, - maxTurns, - maxToolPreviewLines - }; -} - -/** - * Converts API messages to agentic format. - */ -export function toAgenticMessages(messages: ApiChatMessageData[]): AgenticMessage[] { - return messages.map((message) => { - if ( - message.role === MessageRole.ASSISTANT && - message.tool_calls && - message.tool_calls.length > 0 - ) { - return { - role: MessageRole.ASSISTANT, - content: message.content, - tool_calls: message.tool_calls.map((call, index) => ({ - id: call.id ?? `call_${index}`, - type: (call.type as 'function') ?? 'function', - function: { - name: call.function?.name ?? '', - arguments: call.function?.arguments ?? '' - } - })) - } satisfies AgenticMessage; - } - - if (message.role === MessageRole.TOOL && message.tool_call_id) { - return { - role: MessageRole.TOOL, - tool_call_id: message.tool_call_id, - content: typeof message.content === 'string' ? message.content : '' - } satisfies AgenticMessage; - } - - return { - role: message.role as MessageRole.SYSTEM | MessageRole.USER, - content: message.content - } satisfies AgenticMessage; - }); -} diff --git a/tools/server/webui/src/lib/utils/index.ts b/tools/server/webui/src/lib/utils/index.ts index 4a1204cb7a..a55382b2c7 100644 --- a/tools/server/webui/src/lib/utils/index.ts +++ b/tools/server/webui/src/lib/utils/index.ts @@ -101,9 +101,6 @@ export { getLanguageFromFilename } from './syntax-highlight-language'; // Text file utilities export { isTextFileByName, readFileAsText, isLikelyTextFile } from './text-files'; -// Agentic utilities -export { toAgenticMessages, getAgenticConfig } from './agentic'; - // Debounce utilities export { debounce } from './debounce';