139 lines
5.6 KiB
TypeScript
139 lines
5.6 KiB
TypeScript
// *****************************************************************************
|
|
// 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 { injectable, inject } from '@theia/core/shared/inversify';
|
|
import {
|
|
PreferenceService,
|
|
} from '@theia/core/lib/common/preferences';
|
|
import { ToolConfirmationMode, TOOL_CONFIRMATION_PREFERENCE, ChatToolPreferences } from '../common/chat-tool-preferences';
|
|
import { ToolRequest } from '@theia/ai-core';
|
|
|
|
/**
|
|
* Utility class to manage tool confirmation settings
|
|
*/
|
|
@injectable()
|
|
export class ToolConfirmationManager {
|
|
@inject(ChatToolPreferences)
|
|
protected readonly preferences: ChatToolPreferences;
|
|
|
|
@inject(PreferenceService)
|
|
protected readonly preferenceService: PreferenceService;
|
|
|
|
// In-memory session overrides (not persisted), per chat
|
|
protected sessionOverrides: Map<string, Map<string, ToolConfirmationMode>> = new Map();
|
|
|
|
/**
|
|
* Get the confirmation mode for a specific tool, considering session overrides first (per chat).
|
|
*
|
|
* For tools with `confirmAlwaysAllow` flag:
|
|
* - They default to CONFIRM mode instead of ALWAYS_ALLOW
|
|
* - They don't inherit global ALWAYS_ALLOW from the '*' preference
|
|
*
|
|
* @param toolId - The tool identifier
|
|
* @param chatId - The chat session identifier
|
|
* @param toolRequest - Optional ToolRequest to check for confirmAlwaysAllow flag
|
|
*/
|
|
getConfirmationMode(toolId: string, chatId: string, toolRequest?: ToolRequest): ToolConfirmationMode {
|
|
const chatMap = this.sessionOverrides.get(chatId);
|
|
if (chatMap && chatMap.has(toolId)) {
|
|
return chatMap.get(toolId)!;
|
|
}
|
|
const toolConfirmation = this.preferences[TOOL_CONFIRMATION_PREFERENCE];
|
|
if (toolConfirmation[toolId]) {
|
|
return toolConfirmation[toolId];
|
|
}
|
|
if (toolConfirmation['*']) {
|
|
// For confirmAlwaysAllow tools, don't inherit global ALWAYS_ALLOW
|
|
if (toolRequest?.confirmAlwaysAllow && toolConfirmation['*'] === ToolConfirmationMode.ALWAYS_ALLOW) {
|
|
return ToolConfirmationMode.CONFIRM;
|
|
}
|
|
return toolConfirmation['*'];
|
|
}
|
|
|
|
// Default: ALWAYS_ALLOW for normal tools, CONFIRM for confirmAlwaysAllow tools
|
|
return toolRequest?.confirmAlwaysAllow
|
|
? ToolConfirmationMode.CONFIRM
|
|
: ToolConfirmationMode.ALWAYS_ALLOW;
|
|
}
|
|
|
|
/**
|
|
* Set the confirmation mode for a specific tool (persisted)
|
|
*
|
|
* @param toolId - The tool identifier
|
|
* @param mode - The confirmation mode to set
|
|
* @param toolRequest - Optional ToolRequest to check for confirmAlwaysAllow flag
|
|
*/
|
|
setConfirmationMode(toolId: string, mode: ToolConfirmationMode, toolRequest?: ToolRequest): void {
|
|
const current = this.preferences[TOOL_CONFIRMATION_PREFERENCE] || {};
|
|
let starMode = current['*'];
|
|
if (starMode === undefined) {
|
|
starMode = ToolConfirmationMode.ALWAYS_ALLOW;
|
|
}
|
|
// For confirmAlwaysAllow tools, the effective default is CONFIRM, not ALWAYS_ALLOW
|
|
const effectiveDefault = (toolRequest?.confirmAlwaysAllow && starMode === ToolConfirmationMode.ALWAYS_ALLOW)
|
|
? ToolConfirmationMode.CONFIRM
|
|
: starMode;
|
|
if (mode === effectiveDefault) {
|
|
if (toolId in current) {
|
|
const { [toolId]: _, ...rest } = current;
|
|
this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, rest);
|
|
}
|
|
} else {
|
|
const updated = { ...current, [toolId]: mode };
|
|
this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, updated);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the confirmation mode for a specific tool for this session only (not persisted, per chat)
|
|
*/
|
|
setSessionConfirmationMode(toolId: string, mode: ToolConfirmationMode, chatId: string): void {
|
|
let chatMap = this.sessionOverrides.get(chatId);
|
|
if (!chatMap) {
|
|
chatMap = new Map();
|
|
this.sessionOverrides.set(chatId, chatMap);
|
|
}
|
|
chatMap.set(toolId, mode);
|
|
}
|
|
|
|
/**
|
|
* Clear all session overrides for a specific chat, or all if no chatId is given
|
|
*/
|
|
clearSessionOverrides(chatId?: string): void {
|
|
if (chatId) {
|
|
this.sessionOverrides.delete(chatId);
|
|
} else {
|
|
this.sessionOverrides.clear();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all tool confirmation settings
|
|
*/
|
|
getAllConfirmationSettings(): { [toolId: string]: ToolConfirmationMode } {
|
|
return this.preferences[TOOL_CONFIRMATION_PREFERENCE] || {};
|
|
}
|
|
|
|
resetAllConfirmationModeSettings(): void {
|
|
const current = this.preferences[TOOL_CONFIRMATION_PREFERENCE] || {};
|
|
if ('*' in current) {
|
|
this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, { '*': current['*'] });
|
|
} else {
|
|
this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, {});
|
|
}
|
|
}
|
|
}
|