diff --git a/packages/ai-chat/src/browser/change-set-file-element.ts b/packages/ai-chat/src/browser/change-set-file-element.ts index a73108a95f959..20ee6fcebece8 100644 --- a/packages/ai-chat/src/browser/change-set-file-element.ts +++ b/packages/ai-chat/src/browser/change-set-file-element.ts @@ -15,7 +15,7 @@ // ***************************************************************************** import { ConfigurableInMemoryResources, ConfigurableMutableReferenceResource } from '@theia/ai-core'; -import { CancellationToken, DisposableCollection, Emitter, URI } from '@theia/core'; +import { CancellationToken, DisposableCollection, Emitter, nls, URI } from '@theia/core'; import { ConfirmDialog } from '@theia/core/lib/browser'; import { Replacement } from '@theia/core/lib/common/content-replacer'; import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; @@ -448,12 +448,18 @@ export class ChangeSetFileElement implements ChangeSetElement { } } - async confirm(verb: string): Promise { + async confirm(verb: 'Apply' | 'Revert'): Promise { if (this._state !== 'stale') { return true; } await this.openChange(); const answer = await new ConfirmDialog({ - title: `${verb} suggestion.`, - msg: `The file ${this.uri.path.toString()} has changed since this suggestion was created. Are you certain you wish to ${verb.toLowerCase()} the change?` + title: verb === 'Apply' + ? nls.localize('theia/ai/chat/applySuggestion', 'Apply suggestion') + : nls.localize('theia/ai/chat/revertSuggestion', 'Revert suggestion'), + msg: verb === 'Apply' + ? nls.localize('theia/ai/chat/confirmApplySuggestion', + 'The file {0} has changed since this suggestion was created. Are you certain you wish to apply the change?', this.uri.path.toString()) + : nls.localize('theia/ai/chat/confirmRevertSuggestion', + 'The file {0} has changed since this suggestion was created. Are you certain you wish to revert the change?', this.uri.path.toString()) }).open(true); return !!answer; } diff --git a/packages/ai-chat/src/browser/change-set-file-service.ts b/packages/ai-chat/src/browser/change-set-file-service.ts index 4882414cdd3ee..576b8a899c834 100644 --- a/packages/ai-chat/src/browser/change-set-file-service.ts +++ b/packages/ai-chat/src/browser/change-set-file-service.ts @@ -14,7 +14,7 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { ILogger, URI } from '@theia/core'; +import { ILogger, nls, URI } from '@theia/core'; import { ApplicationShell, DiffUris, LabelProvider, NavigatableWidget, OpenerService, open } from '@theia/core/lib/browser'; import { inject, injectable } from '@theia/core/shared/inversify'; import { EditorManager } from '@theia/editor/lib/browser'; @@ -79,7 +79,7 @@ export class ChangeSetFileService { if (wsUri) { const wsRelative = wsUri.relative(uri); if (wsRelative?.hasDir) { - return `${wsRelative.dir.toString()}`; + return wsRelative.dir.toString(); } return ''; } @@ -104,7 +104,7 @@ export class ChangeSetFileService { protected getDiffUri(originalUri: URI, suggestedUri: URI): URI { return DiffUris.encode(originalUri, suggestedUri, - `AI Changes: ${this.labelProvider.getName(originalUri)}`, + nls.localize('theia/ai/chat/changeSetFileDiffUriLabel', 'AI Changes: {0}', this.labelProvider.getName(originalUri)), ); } diff --git a/packages/ai-chat/src/browser/file-chat-variable-contribution.ts b/packages/ai-chat/src/browser/file-chat-variable-contribution.ts index 93a4e924a4418..d35ec3d1ee626 100644 --- a/packages/ai-chat/src/browser/file-chat-variable-contribution.ts +++ b/packages/ai-chat/src/browser/file-chat-variable-contribution.ts @@ -17,7 +17,7 @@ import { AIVariableContext, AIVariableResolutionRequest, PromptText } from '@theia/ai-core'; import { AIVariableCompletionContext, AIVariableDropResult, FrontendVariableContribution, FrontendVariableService } from '@theia/ai-core/lib/browser'; import { FILE_VARIABLE } from '@theia/ai-core/lib/browser/file-variable-contribution'; -import { CancellationToken, ILogger, QuickInputService, URI } from '@theia/core'; +import { CancellationToken, ILogger, nls, QuickInputService, URI } from '@theia/core'; import { inject, injectable } from '@theia/core/shared/inversify'; import * as monaco from '@theia/monaco-editor-core'; import { FileQuickPickItem, QuickFileSelectService } from '@theia/file-search/lib/browser/quick-file-select-service'; @@ -76,7 +76,7 @@ export class FileChatVariableContribution implements FrontendVariableContributio protected async imageArgumentPicker(): Promise { const quickPick = this.quickInputService.createQuickPick(); - quickPick.title = 'Select an image file'; + quickPick.title = nls.localize('theia/ai/chat/selectImageFile', 'Select an image file'); // Get all files and filter only image files const allPicks = await this.quickFileSelectService.getPicks(); diff --git a/packages/ai-chat/src/browser/image-context-variable-contribution.ts b/packages/ai-chat/src/browser/image-context-variable-contribution.ts index cb0587ed73655..7c1423211e953 100644 --- a/packages/ai-chat/src/browser/image-context-variable-contribution.ts +++ b/packages/ai-chat/src/browser/image-context-variable-contribution.ts @@ -148,6 +148,6 @@ export class ImageContextVariableContribution implements AIVariableContribution, getDetails(element: ImageContextVariableRequest): string | undefined { const path = ImageContextVariable.parseArg(element.arg).wsRelativePath; - return path ? this.labelProvider.getDetails(new URI(path)) : '[pasted]'; + return path ? this.labelProvider.getDetails(new URI(path)) : undefined; } } diff --git a/packages/ai-chat/src/browser/task-context-service.ts b/packages/ai-chat/src/browser/task-context-service.ts index e1ddfadf8e1ad..d916e4672bfb6 100644 --- a/packages/ai-chat/src/browser/task-context-service.ts +++ b/packages/ai-chat/src/browser/task-context-service.ts @@ -15,7 +15,7 @@ // ***************************************************************************** import { inject, injectable } from '@theia/core/shared/inversify'; -import { MaybePromise, ProgressService, URI, generateUuid, Event, EOL } from '@theia/core'; +import { MaybePromise, ProgressService, URI, generateUuid, Event, EOL, nls } from '@theia/core'; import { ChatAgent, ChatAgentLocation, ChatService, ChatSession, MutableChatModel, MutableChatRequestModel, ParsedChatRequestTextPart } from '../common'; import { PreferenceService } from '@theia/core/lib/common'; import { ChatSessionSummaryAgent } from '../common/chat-session-summary-agent'; @@ -90,7 +90,10 @@ export class TaskContextService { if (existing && !override) { return existing.id; } const summaryId = generateUuid(); const summaryDeferred = new Deferred(); - const progress = await this.progressService.showProgress({ text: `Summarize: ${session.title || session.id}`, options: { location: 'ai-chat' } }); + const progress = await this.progressService.showProgress({ + text: nls.localize('theia/ai/chat/taskContextService/summarizeProgressMessage', 'Summarize: {0}', session.title || session.id), + options: { location: 'ai-chat' } + }); this.pendingSummaries.set(session.id, summaryDeferred.promise); try { const prompt = await this.getSystemPrompt(session, promptId); @@ -127,7 +130,10 @@ export class TaskContextService { return this.summarize(session, promptId, agent, override); } - const progress = await this.progressService.showProgress({ text: `Updating: ${session.title || session.id}`, options: { location: 'ai-chat' } }); + const progress = await this.progressService.showProgress({ + text: nls.localize('theia/ai/chat/taskContextService/updatingProgressMessage', 'Updating: {0}', session.title || session.id), + options: { location: 'ai-chat' } + }); try { const prompt = await this.getSystemPrompt(session, promptId); if (!prompt) { diff --git a/packages/ai-chat/src/browser/task-context-variable.ts b/packages/ai-chat/src/browser/task-context-variable.ts index 6704141e491ed..a789ad208b8eb 100644 --- a/packages/ai-chat/src/browser/task-context-variable.ts +++ b/packages/ai-chat/src/browser/task-context-variable.ts @@ -15,14 +15,19 @@ // ***************************************************************************** import { AIVariable } from '@theia/ai-core'; +import { nls } from '@theia/core'; import { codiconArray } from '@theia/core/lib/browser'; export const TASK_CONTEXT_VARIABLE: AIVariable = { id: 'taskContext', - description: 'Provides context information for a task, e.g. the plan for completing a task or a summary of a previous sessions', + description: nls.localize('theia/chat/taskContextVariable/description', + 'Provides context information for a task, e.g. the plan for completing a task or a summary of a previous sessions'), name: 'taskContext', - label: 'Task Context', + label: nls.localize('theia/chat/taskContextVariable/label', 'Task Context'), iconClasses: codiconArray('clippy'), isContextVariable: true, - args: [{ name: 'context-id', description: 'The ID of the task context to retrieve, or a chat session to summarize.' }] + args: [{ + name: 'context-id', + description: nls.localize('theia/chat/taskContextVariable/args/contextId/description', 'The ID of the task context to retrieve, or a chat session to summarize.') + }] }; diff --git a/packages/ai-chat/src/common/change-set.ts b/packages/ai-chat/src/common/change-set.ts index b8e0b585c50b7..26d3410eb6df2 100644 --- a/packages/ai-chat/src/common/change-set.ts +++ b/packages/ai-chat/src/common/change-set.ts @@ -14,7 +14,7 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { ArrayUtils, Disposable, Emitter, Event, URI } from '@theia/core'; +import { ArrayUtils, Disposable, Emitter, Event, nls, URI } from '@theia/core'; export interface ChangeSetElement { readonly uri: URI; @@ -95,7 +95,7 @@ export class ChangeSetImpl implements ChangeSet { protected hasBeenSet = false; protected _elements = new Map(); - protected _title = 'Suggested Changes'; + protected _title = nls.localize('theia/ai/chat/changeSetDefaultTitle', 'Suggested Changes'); get title(): string { return this._title; } diff --git a/packages/ai-chat/src/common/chat-agents-variable-contribution.ts b/packages/ai-chat/src/common/chat-agents-variable-contribution.ts index 72344d166fb54..ab41f0194b8e6 100644 --- a/packages/ai-chat/src/common/chat-agents-variable-contribution.ts +++ b/packages/ai-chat/src/common/chat-agents-variable-contribution.ts @@ -13,7 +13,7 @@ // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { MaybePromise } from '@theia/core'; +import { MaybePromise, nls } from '@theia/core'; import { inject, injectable } from '@theia/core/shared/inversify'; import { AIVariable, @@ -29,7 +29,7 @@ import { ChatAgentService } from './chat-agent-service'; export const CHAT_AGENTS_VARIABLE: AIVariable = { id: 'chatAgents', name: 'chatAgents', - description: 'Returns the list of chat agents available in the system' + description: nls.localize('theia/ai/chat/chatAgentsVariable/description', 'Returns the list of chat agents available in the system') }; export interface ChatAgentDescriptor { diff --git a/packages/ai-chat/src/common/chat-agents.ts b/packages/ai-chat/src/common/chat-agents.ts index 5ea4a53d138f0..bfb21edb91af1 100644 --- a/packages/ai-chat/src/common/chat-agents.ts +++ b/packages/ai-chat/src/common/chat-agents.ts @@ -49,7 +49,7 @@ import { LanguageModelRegistry, LanguageModelStreamResponsePart } from '@theia/ai-core/lib/common'; -import { ContributionProvider, ILogger, isArray } from '@theia/core'; +import { ContributionProvider, ILogger, isArray, nls } from '@theia/core'; import { inject, injectable, named, postConstruct } from '@theia/core/shared/inversify'; import { ChatAgentService } from './chat-agent-service'; import { @@ -155,7 +155,7 @@ export abstract class AbstractChatAgent implements ChatAgent { readonly abstract languageModelRequirements: LanguageModelRequirement[]; iconClass: string = 'codicon codicon-copilot'; locations: ChatAgentLocation[] = ChatAgentLocation.ALL; - tags: string[] = ['Chat']; + tags: string[] = [nls.localizeByDefault('Chat')]; description: string = ''; variables: string[] = []; prompts: PromptVariantSet[] = []; @@ -180,7 +180,7 @@ export abstract class AbstractChatAgent implements ChatAgent { try { const languageModel = await this.getLanguageModel(this.defaultLanguageModelPurpose); if (!languageModel) { - throw new Error('Couldn\'t find a matching language model. Please check your setup!'); + throw new Error(nls.localize('theia/ai/chat/couldNotFindMatchingLM', 'Couldn\'t find a matching language model. Please check your setup!')); } const systemMessageDescription = await this.getSystemMessageDescription({ model: request.session, request } satisfies ChatSessionContext); const messages = await this.getMessages(request.session); @@ -237,7 +237,7 @@ export abstract class AbstractChatAgent implements ChatAgent { protected async selectLanguageModel(selector: LanguageModelRequirement): Promise { const languageModel = await this.languageModelRegistry.selectLanguageModel({ agent: this.id, ...selector }); if (!languageModel) { - throw new Error(`Couldn\'t find a ready language model for agent ${this.id}. Please check your setup!`); + throw new Error(nls.localize('theia/ai/chat/couldNotFindReadyLMforAgent', 'Couldn\'t find a ready language model for agent {0}. Please check your setup!', this.id)); } return languageModel; } diff --git a/packages/ai-chat/src/common/chat-session-naming-service.ts b/packages/ai-chat/src/common/chat-session-naming-service.ts index 5d8e32e765ff1..f3c5258f916cb 100644 --- a/packages/ai-chat/src/common/chat-session-naming-service.ts +++ b/packages/ai-chat/src/common/chat-session-naming-service.ts @@ -26,7 +26,7 @@ import { } from '@theia/ai-core'; import { inject, injectable } from '@theia/core/shared/inversify'; import { ChatSession } from './chat-service'; -import { generateUuid } from '@theia/core'; +import { generateUuid, nls } from '@theia/core'; import { CHAT_SESSION_NAMING_PROMPT } from './chat-session-naming-prompt-template'; @@ -47,7 +47,7 @@ export class ChatSessionNamingAgent implements Agent { static ID = 'Chat Session Naming'; id = ChatSessionNamingAgent.ID; name = ChatSessionNamingAgent.ID; - description = 'Agent for generating chat session names'; + description = nls.localize('theia/ai/chat/chatSessionNamingAgent/description', 'Agent for generating chat session names'); variables = []; prompts = [CHAT_SESSION_NAMING_PROMPT]; languageModelRequirements: LanguageModelRequirement[] = [{ @@ -55,8 +55,16 @@ export class ChatSessionNamingAgent implements Agent { identifier: 'default/summarize', }]; agentSpecificVariables = [ - { name: 'conversation', usedInPrompt: true, description: 'The content of the chat conversation.' }, - { name: 'listOfSessionNames', usedInPrompt: true, description: 'The list of existing session names.' } + { + 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 = []; diff --git a/packages/ai-chat/src/common/chat-session-summary-agent-prompt.ts b/packages/ai-chat/src/common/chat-session-summary-agent-prompt.ts index 0667e34dbeafa..210d1b46f3149 100644 --- a/packages/ai-chat/src/common/chat-session-summary-agent-prompt.ts +++ b/packages/ai-chat/src/common/chat-session-summary-agent-prompt.ts @@ -24,7 +24,7 @@ export const CHAT_SESSION_SUMMARY_PROMPT = { 'The summary will primarily be used by other AI agents, so tailor your response for use by AI agents. ' + 'Also consider the system message. ' + 'Make sure you include all necessary context information and use unique references (such as URIs, file paths, etc.). ' + - 'If the conversation was about a task, describe the state of the task, i.e.what has been completed and what is open. ' + + 'If the conversation was about a task, describe the state of the task, i.e. what has been completed and what is open. ' + 'If a changeset is open in the session, describe the state of the suggested changes. ' + `\n\n{{${CHANGE_SET_SUMMARY_VARIABLE_ID}}}`, } diff --git a/packages/ai-chat/src/common/chat-session-summary-agent.ts b/packages/ai-chat/src/common/chat-session-summary-agent.ts index 59175b3026a6c..298a27aea0ccc 100644 --- a/packages/ai-chat/src/common/chat-session-summary-agent.ts +++ b/packages/ai-chat/src/common/chat-session-summary-agent.ts @@ -21,13 +21,14 @@ import { import { injectable } from '@theia/core/shared/inversify'; import { AbstractStreamParsingChatAgent, ChatAgent } from './chat-agents'; import { CHAT_SESSION_SUMMARY_PROMPT } from './chat-session-summary-agent-prompt'; +import { nls } from '@theia/core'; @injectable() export class ChatSessionSummaryAgent extends AbstractStreamParsingChatAgent implements ChatAgent { static ID = 'chat-session-summary-agent'; id = ChatSessionSummaryAgent.ID; name = 'Chat Session Summary'; - override description = 'Agent for generating chat session summaries.'; + override description = nls.localize('theia/ai/chat/chatSessionSummaryAgent/description', 'Agent for generating chat session summaries.'); override prompts: PromptVariantSet[] = [CHAT_SESSION_SUMMARY_PROMPT]; protected readonly defaultLanguageModelPurpose = 'chat-session-summary'; languageModelRequirements: LanguageModelRequirement[] = [{ diff --git a/packages/ai-chat/src/common/chat-tool-preferences.ts b/packages/ai-chat/src/common/chat-tool-preferences.ts index 28b35549a8b37..65c69c74e869f 100644 --- a/packages/ai-chat/src/common/chat-tool-preferences.ts +++ b/packages/ai-chat/src/common/chat-tool-preferences.ts @@ -70,7 +70,7 @@ export const chatToolPreferences: PreferenceSchema = { }, default: {}, description: nls.localize('theia/ai/chat/toolConfirmation/description', - 'Configure confirmation behavior for different tools. Key is the tool ID, value is the confirmation mode.' + + 'Configure confirmation behavior for different tools. Key is the tool ID, value is the confirmation mode. ' + 'Use "*" as the key to set a global default for all tools.'), title: AI_CORE_PREFERENCES_TITLE, } @@ -80,4 +80,3 @@ export const chatToolPreferences: PreferenceSchema = { export interface ChatToolConfiguration { [TOOL_CONFIRMATION_PREFERENCE]: { [toolId: string]: ToolConfirmationMode }; } - diff --git a/packages/ai-chat/src/common/image-context-variable.ts b/packages/ai-chat/src/common/image-context-variable.ts index c762f8b5eee9e..015472c2e3a61 100644 --- a/packages/ai-chat/src/common/image-context-variable.ts +++ b/packages/ai-chat/src/common/image-context-variable.ts @@ -19,19 +19,34 @@ import { AIVariableResolutionRequest, ResolvedAIContextVariable } from '@theia/ai-core'; +import { nls } from '@theia/core'; export const IMAGE_CONTEXT_VARIABLE: AIVariable = { id: 'imageContext', - description: 'Provides context information for an image', + description: nls.localize('theia/ai/chat/imageContextVariable/description', 'Provides context information for an image'), name: 'imageContext', - label: 'Image File', + label: nls.localize('theia/ai/chat/imageContextVariable/label', 'Image File'), iconClasses: ['codicon', 'codicon-file-media'], isContextVariable: true, args: [ - { name: 'name', description: 'The name of the image file if available.', isOptional: true }, - { name: 'wsRelativePath', description: 'The workspace-relative path of the image file if available.', isOptional: true }, - { name: 'data', description: 'The image data in base64.' }, - { name: 'mimeType', description: 'The mimetype of the image.' } + { + name: 'name', + description: nls.localize('theia/ai/chat/imageContextVariable/args/name/description', 'The name of the image file if available.'), + isOptional: true + }, + { + name: 'wsRelativePath', + description: nls.localize('theia/ai/chat/imageContextVariable/args/wsRelativePath/description', 'The workspace-relative path of the image file if available.'), + isOptional: true + }, + { + name: 'data', + description: nls.localize('theia/ai/chat/imageContextVariable/args/data/description', 'The image data in base64.') + }, + { + name: 'mimeType', + description: nls.localize('theia/ai/chat/imageContextVariable/args/mimeType/description', 'The mimetype of the image.') + } ] };