// ***************************************************************************** // Copyright (C) 2025 EclipseSource GmbH. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** import { Agent, AgentService, getTextOfResponse, LanguageModelRegistry, LanguageModelRequirement, LanguageModelService, PromptService, UserRequest } from '@theia/ai-core'; import { inject, injectable } from '@theia/core/shared/inversify'; import { ChatSession } from './chat-service'; import { generateUuid, nls } from '@theia/core'; import { CHAT_SESSION_NAMING_PROMPT } from './chat-session-naming-prompt-template'; @injectable() export class ChatSessionNamingService { @inject(AgentService) protected agentService: AgentService; async generateChatSessionName(chatSession: ChatSession, otherNames: string[]): Promise { const chatSessionNamingAgent = this.agentService.getAgents().find(agent => ChatSessionNamingAgent.ID === agent.id); if (!(chatSessionNamingAgent instanceof ChatSessionNamingAgent)) { return undefined; } return chatSessionNamingAgent.generateChatSessionName(chatSession, otherNames); } } @injectable() export class ChatSessionNamingAgent implements Agent { static ID = 'Chat Session Naming'; id = ChatSessionNamingAgent.ID; name = ChatSessionNamingAgent.ID; description = nls.localize('theia/ai/chat/chatSessionNamingAgent/description', 'Agent for generating chat session names'); variables = []; prompts = [CHAT_SESSION_NAMING_PROMPT]; languageModelRequirements: LanguageModelRequirement[] = [{ purpose: 'chat-session-naming', identifier: 'default/fast', }]; agentSpecificVariables = [ { name: 'conversation', usedInPrompt: true, description: nls.localize('theia/ai/chat/chatSessionNamingAgent/vars/conversation/description', 'The content of the chat conversation.') }, { name: 'listOfSessionNames', usedInPrompt: true, description: nls.localize('theia/ai/chat/chatSessionNamingAgent/vars/listOfSessionNames/description', 'The list of existing session names.') } ]; functions = []; @inject(LanguageModelRegistry) protected readonly lmRegistry: LanguageModelRegistry; @inject(LanguageModelService) protected readonly languageModelService: LanguageModelService; @inject(PromptService) protected promptService: PromptService; async generateChatSessionName(chatSession: ChatSession, otherNames: string[]): Promise { const lm = await this.lmRegistry.selectLanguageModel({ agent: this.id, ...this.languageModelRequirements[0] }); if (!lm) { throw new Error('No language model found for chat session naming'); } if (chatSession.model.getRequests().length < 1) { throw new Error('No chat request available to generate chat session name'); } const conversation = chatSession.model.getRequests() .map(req => `${req.message.parts.map(chunk => chunk.promptText).join('')}` + (req.response.response ? `${req.response.response.asString()}` : '')) .join('\n\n'); const listOfSessionNames = otherNames.map(name => name).join(', '); const prompt = await this.promptService.getResolvedPromptFragment(CHAT_SESSION_NAMING_PROMPT.id, { conversation, listOfSessionNames }); const message = prompt?.text; if (!message) { throw new Error('Unable to create prompt message for generating chat session name'); } const variantInfo = this.promptService.getPromptVariantInfo(CHAT_SESSION_NAMING_PROMPT.id); const sessionId = generateUuid(); const requestId = generateUuid(); const request: UserRequest & { agentId: string } = { messages: [{ actor: 'user', text: message, type: 'text' }], requestId, sessionId, agentId: this.id, promptVariantId: variantInfo?.variantId, isPromptVariantCustomized: variantInfo?.isCustomized }; const result = await this.languageModelService.sendRequest(lm, request); const response = await getTextOfResponse(result); return response.replace(/\s+/g, ' ').substring(0, 100); } }