From f7b7ae467e03ce5bd5109df41d95713dd91e1152 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Tue, 27 Jan 2026 15:25:47 +0100 Subject: [PATCH] feat: Introduce BaseClient for common store integration refactor(agentic-client): Extend BaseClient for store integration refactor(chat-client): Extend BaseClient for store integration refactor(conversations-client): Extend BaseClient for store integration --- .../webui/src/lib/clients/agentic.client.ts | 28 +---------- .../webui/src/lib/clients/base-client.ts | 48 +++++++++++++++++++ .../webui/src/lib/clients/chat.client.ts | 28 +---------- .../src/lib/clients/conversations.client.ts | 28 +---------- tools/server/webui/src/lib/clients/index.ts | 3 ++ 5 files changed, 57 insertions(+), 78 deletions(-) create mode 100644 tools/server/webui/src/lib/clients/base-client.ts diff --git a/tools/server/webui/src/lib/clients/agentic.client.ts b/tools/server/webui/src/lib/clients/agentic.client.ts index 9de0be19f8..831cbe1e25 100644 --- a/tools/server/webui/src/lib/clients/agentic.client.ts +++ b/tools/server/webui/src/lib/clients/agentic.client.ts @@ -23,6 +23,7 @@ * - Lazy disconnect after flow completes */ +import { BaseClient } from './base-client'; import { mcpClient } from '$lib/clients'; import { ChatService } from '$lib/services'; import { config } from '$lib/stores/settings.svelte'; @@ -108,32 +109,7 @@ interface AgenticStoreStateCallbacks { clearStreamingToolCall: (conversationId: string) => void; } -export class AgenticClient { - private storeCallbacks: AgenticStoreStateCallbacks | null = null; - - /** - * - * - * Store Integration - * - * - */ - - /** - * Sets callbacks for store state updates. - * Called by agenticStore during initialization. - */ - setStoreCallbacks(callbacks: AgenticStoreStateCallbacks): void { - this.storeCallbacks = callbacks; - } - - private get store(): AgenticStoreStateCallbacks { - if (!this.storeCallbacks) { - throw new Error('AgenticClient: Store callbacks not initialized'); - } - return this.storeCallbacks; - } - +export class AgenticClient extends BaseClient { /** * * diff --git a/tools/server/webui/src/lib/clients/base-client.ts b/tools/server/webui/src/lib/clients/base-client.ts new file mode 100644 index 0000000000..7e76b7b5b2 --- /dev/null +++ b/tools/server/webui/src/lib/clients/base-client.ts @@ -0,0 +1,48 @@ +/** + * BaseClient - Abstract base class for client classes + * + * Provides common store callback management pattern used by all clients. + * Clients extend this class to inherit the store callback infrastructure. + * + * **Usage:** + * ```typescript + * interface MyStoreCallbacks { + * setSomeState: (value: string) => void; + * } + * + * class MyClient extends BaseClient { + * doSomething() { + * this.store.setSomeState('value'); + * } + * } + * ``` + */ +export abstract class BaseClient { + private _storeCallbacks: TCallbacks | null = null; + + /** + * Sets callbacks for store state updates. + * Called by the corresponding store during initialization. + */ + setStoreCallbacks(callbacks: TCallbacks): void { + this._storeCallbacks = callbacks; + } + + /** + * Gets the store callbacks, throwing if not initialized. + * Use this in derived classes to access store callbacks safely. + */ + protected get store(): TCallbacks { + if (!this._storeCallbacks) { + throw new Error(`${this.constructor.name}: Store callbacks not initialized`); + } + return this._storeCallbacks; + } + + /** + * Checks if store callbacks have been initialized. + */ + protected get hasStoreCallbacks(): boolean { + return this._storeCallbacks !== null; + } +} diff --git a/tools/server/webui/src/lib/clients/chat.client.ts b/tools/server/webui/src/lib/clients/chat.client.ts index 3113b847f0..12fcd0f134 100644 --- a/tools/server/webui/src/lib/clients/chat.client.ts +++ b/tools/server/webui/src/lib/clients/chat.client.ts @@ -1,3 +1,4 @@ +import { BaseClient } from './base-client'; import { DatabaseService, ChatService } from '$lib/services'; import { conversationsStore } from '$lib/stores/conversations.svelte'; import { config } from '$lib/stores/settings.svelte'; @@ -79,32 +80,7 @@ const wrapReasoningContent = (content: string, reasoningContent?: string): strin * - Error handling (timeout, server errors) * - Graceful stop with partial response saving */ -export class ChatClient { - private storeCallbacks: ChatStoreStateCallbacks | null = null; - - /** - * - * - * Store Integration - * - * - */ - - /** - * Sets callbacks for store state updates. - * Called by chatStore during initialization to establish bidirectional communication. - */ - setStoreCallbacks(callbacks: ChatStoreStateCallbacks): void { - this.storeCallbacks = callbacks; - } - - private get store(): ChatStoreStateCallbacks { - if (!this.storeCallbacks) { - throw new Error('ChatClient: Store callbacks not initialized'); - } - return this.storeCallbacks; - } - +export class ChatClient extends BaseClient { /** * * diff --git a/tools/server/webui/src/lib/clients/conversations.client.ts b/tools/server/webui/src/lib/clients/conversations.client.ts index b28cab36ee..b62a64a7c1 100644 --- a/tools/server/webui/src/lib/clients/conversations.client.ts +++ b/tools/server/webui/src/lib/clients/conversations.client.ts @@ -20,6 +20,7 @@ * - Title management with confirmation */ +import { BaseClient } from './base-client'; import { goto } from '$app/navigation'; import { toast } from 'svelte-sonner'; import { DatabaseService } from '$lib/services/database.service'; @@ -46,32 +47,7 @@ interface ConversationsStoreStateCallbacks { | undefined; } -export class ConversationsClient { - private storeCallbacks: ConversationsStoreStateCallbacks | null = null; - - /** - * - * - * Store Integration - * - * - */ - - /** - * Sets callbacks for store state updates. - * Called by conversationsStore during initialization. - */ - setStoreCallbacks(callbacks: ConversationsStoreStateCallbacks): void { - this.storeCallbacks = callbacks; - } - - private get store(): ConversationsStoreStateCallbacks { - if (!this.storeCallbacks) { - throw new Error('ConversationsClient: Store callbacks not initialized'); - } - return this.storeCallbacks; - } - +export class ConversationsClient extends BaseClient { /** * * diff --git a/tools/server/webui/src/lib/clients/index.ts b/tools/server/webui/src/lib/clients/index.ts index 70f136c199..0ffe5f4a02 100644 --- a/tools/server/webui/src/lib/clients/index.ts +++ b/tools/server/webui/src/lib/clients/index.ts @@ -16,6 +16,9 @@ * @see stores/ for reactive state */ +// Base Client +export { BaseClient } from './base-client'; + // MCP Client export { MCPClient, mcpClient } from './mcp.client';