diff --git a/changelogs/fragments/10999.yml b/changelogs/fragments/10999.yml new file mode 100644 index 000000000000..b7be5b0ba4fd --- /dev/null +++ b/changelogs/fragments/10999.yml @@ -0,0 +1,2 @@ +fix: +- [BUG][Chat] Unregister tools when component unmount ([#10999](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/10999)) \ No newline at end of file diff --git a/src/plugins/chat/public/plugin.ts b/src/plugins/chat/public/plugin.ts index 7d402faa6213..f63032d63aef 100644 --- a/src/plugins/chat/public/plugin.ts +++ b/src/plugins/chat/public/plugin.ts @@ -188,5 +188,6 @@ export class ChatPlugin implements Plugin { public stop() { this.paddingSizeSubscription?.unsubscribe(); this.unsubscribeWindowStateChange?.(); + this.chatService?.destroy(); } } diff --git a/src/plugins/chat/public/services/chat_service.ts b/src/plugins/chat/public/services/chat_service.ts index 8dde65b5daa8..531b155840c3 100644 --- a/src/plugins/chat/public/services/chat_service.ts +++ b/src/plugins/chat/public/services/chat_service.ts @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { AgUiAgent } from './ag_ui_agent'; import { RunAgentInput, Message, UserMessage, ToolMessage } from '../../common/types'; import type { ToolDefinition } from '../../../context_provider/public'; +import { AssistantActionService } from '../../../context_provider/public'; import { ChatLayoutMode } from '../components/chat_header_button'; import type { ChatWindowInstance } from '../components/chat_window'; import { @@ -51,6 +52,9 @@ export class ChatService { // ChatWindow ref for delegating sendMessage calls to proper timeline management private chatWindowRef: React.RefObject | null = null; + // Subscription to assistant action service for tool updates + private toolSubscription?: Subscription; + constructor( uiSettings: IUiSettingsClient, coreChatService?: ChatServiceStart, @@ -69,6 +73,12 @@ export class ChatService { this.coreChatService.setThreadId(currentChatState.threadId); } this.currentMessages = currentChatState?.messages || []; + + // Subscribe to assistant action service to keep tools in sync + const assistantActionService = AssistantActionService.getInstance(); + this.toolSubscription = assistantActionService.getState$().subscribe((state) => { + this.availableTools = state.toolDefinitions; + }); } public getThreadId = () => { @@ -514,4 +524,14 @@ export class ChatService { // Clear dynamic context from global store for fresh chat session this.clearDynamicContextFromStore(); } + + /** + * Cleanup method to properly dispose of subscriptions + */ + public destroy(): void { + if (this.toolSubscription) { + this.toolSubscription.unsubscribe(); + this.toolSubscription = undefined; + } + } }