@theia/ai-chat 1.72.0-next.2 → 1.72.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/chat-tool-preference-bindings.d.ts +28 -4
- package/lib/browser/chat-tool-preference-bindings.d.ts.map +1 -1
- package/lib/browser/chat-tool-preference-bindings.js +55 -32
- package/lib/browser/chat-tool-preference-bindings.js.map +1 -1
- package/lib/browser/chat-tool-preference-bindings.spec.js +168 -98
- package/lib/browser/chat-tool-preference-bindings.spec.js.map +1 -1
- package/lib/common/chat-tool-preferences.d.ts +2 -0
- package/lib/common/chat-tool-preferences.d.ts.map +1 -1
- package/lib/common/chat-tool-preferences.js +26 -9
- package/lib/common/chat-tool-preferences.js.map +1 -1
- package/package.json +10 -10
- package/src/browser/chat-tool-preference-bindings.spec.ts +194 -104
- package/src/browser/chat-tool-preference-bindings.ts +71 -39
- package/src/common/chat-tool-preferences.ts +29 -8
|
@@ -18,7 +18,11 @@ import { injectable, inject } from '@theia/core/shared/inversify';
|
|
|
18
18
|
import {
|
|
19
19
|
PreferenceService,
|
|
20
20
|
} from '@theia/core/lib/common/preferences';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
ToolConfirmationMode,
|
|
23
|
+
TOOL_CONFIRMATION_PREFERENCE,
|
|
24
|
+
DEFAULT_TOOL_CONFIRMATION_PREFERENCE
|
|
25
|
+
} from '../common/chat-tool-preferences';
|
|
22
26
|
import { ToolRequest } from '@theia/ai-core';
|
|
23
27
|
import { TrustAwarePreferenceReader } from '@theia/ai-core/lib/browser/trust-aware-preference-reader';
|
|
24
28
|
|
|
@@ -36,12 +40,33 @@ export class ToolConfirmationManager {
|
|
|
36
40
|
// In-memory session overrides (not persisted), per chat
|
|
37
41
|
protected sessionOverrides: Map<string, Map<string, ToolConfirmationMode>> = new Map();
|
|
38
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Get the global default confirmation mode (used when no tool-specific entry exists).
|
|
45
|
+
*
|
|
46
|
+
* Read through the trust-aware reader so that an untrusted workspace cannot override
|
|
47
|
+
* the default to a more permissive value.
|
|
48
|
+
*/
|
|
49
|
+
getDefaultConfirmationMode(): ToolConfirmationMode {
|
|
50
|
+
const value = this.trustAwareReader.get<ToolConfirmationMode>(DEFAULT_TOOL_CONFIRMATION_PREFERENCE);
|
|
51
|
+
return value ?? this.getDefaultPreferenceSchemaDefault();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Set the global default confirmation mode.
|
|
56
|
+
*
|
|
57
|
+
* Returns the promise produced by the underlying preference update so callers can
|
|
58
|
+
* `await` completion and react to errors (e.g. show a notification on failure).
|
|
59
|
+
*/
|
|
60
|
+
setDefaultConfirmationMode(mode: ToolConfirmationMode): Promise<void> {
|
|
61
|
+
return this.preferenceService.updateValue(DEFAULT_TOOL_CONFIRMATION_PREFERENCE, mode);
|
|
62
|
+
}
|
|
63
|
+
|
|
39
64
|
/**
|
|
40
65
|
* Get the confirmation mode for a specific tool, considering session overrides first (per chat).
|
|
41
66
|
*
|
|
42
67
|
* For tools with `confirmAlwaysAllow` flag:
|
|
43
|
-
* - They default to CONFIRM mode instead of ALWAYS_ALLOW
|
|
44
|
-
* -
|
|
68
|
+
* - They default to CONFIRM mode instead of inheriting ALWAYS_ALLOW from the global default.
|
|
69
|
+
* - Tool-specific preference entries are still respected (informed user consent).
|
|
45
70
|
*
|
|
46
71
|
* @param toolId - The tool identifier
|
|
47
72
|
* @param chatId - The chat session identifier
|
|
@@ -55,21 +80,15 @@ export class ToolConfirmationManager {
|
|
|
55
80
|
const toolConfirmation = this.trustAwareReader.get<Record<string, ToolConfirmationMode>>(
|
|
56
81
|
TOOL_CONFIRMATION_PREFERENCE, {}
|
|
57
82
|
) ?? {};
|
|
58
|
-
if (toolConfirmation
|
|
83
|
+
if (toolId in toolConfirmation) {
|
|
59
84
|
return toolConfirmation[toolId];
|
|
60
85
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
return toolConfirmation['*'];
|
|
86
|
+
const defaultMode = this.getDefaultConfirmationMode();
|
|
87
|
+
// For confirmAlwaysAllow tools, don't inherit a global ALWAYS_ALLOW default
|
|
88
|
+
if (toolRequest?.confirmAlwaysAllow && defaultMode === ToolConfirmationMode.ALWAYS_ALLOW) {
|
|
89
|
+
return ToolConfirmationMode.CONFIRM;
|
|
67
90
|
}
|
|
68
|
-
|
|
69
|
-
// Default: ALWAYS_ALLOW for normal tools, CONFIRM for confirmAlwaysAllow tools
|
|
70
|
-
return toolRequest?.confirmAlwaysAllow
|
|
71
|
-
? ToolConfirmationMode.CONFIRM
|
|
72
|
-
: ToolConfirmationMode.ALWAYS_ALLOW;
|
|
91
|
+
return defaultMode;
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
/**
|
|
@@ -79,30 +98,20 @@ export class ToolConfirmationManager {
|
|
|
79
98
|
* @param mode - The confirmation mode to set
|
|
80
99
|
* @param toolRequest - Optional ToolRequest to check for confirmAlwaysAllow flag
|
|
81
100
|
*/
|
|
82
|
-
setConfirmationMode(toolId: string, mode: ToolConfirmationMode, toolRequest?: ToolRequest): void {
|
|
83
|
-
const defaultPref = this.preferenceService.inspect(TOOL_CONFIRMATION_PREFERENCE)?.defaultValue as {
|
|
84
|
-
[toolId: string]: ToolConfirmationMode;
|
|
85
|
-
} || {};
|
|
101
|
+
setConfirmationMode(toolId: string, mode: ToolConfirmationMode, toolRequest?: ToolRequest): Promise<void> {
|
|
86
102
|
const current = this.trustAwareReader.get<Record<string, ToolConfirmationMode>>(
|
|
87
103
|
TOOL_CONFIRMATION_PREFERENCE, {}
|
|
88
104
|
) ?? {};
|
|
89
|
-
|
|
90
|
-
if (starMode === undefined) {
|
|
91
|
-
starMode = defaultPref['*'] ?? ToolConfirmationMode.ALWAYS_ALLOW;
|
|
92
|
-
}
|
|
93
|
-
// For confirmAlwaysAllow tools, the effective default is CONFIRM, not ALWAYS_ALLOW
|
|
94
|
-
const effectiveDefault = (toolRequest?.confirmAlwaysAllow && starMode === ToolConfirmationMode.ALWAYS_ALLOW)
|
|
95
|
-
? ToolConfirmationMode.CONFIRM
|
|
96
|
-
: defaultPref[toolId] ?? starMode;
|
|
105
|
+
const effectiveDefault = this.computeEffectiveDefaultForTool(toolId, toolRequest);
|
|
97
106
|
if (mode === effectiveDefault) {
|
|
98
107
|
if (toolId in current) {
|
|
99
108
|
const { [toolId]: _, ...rest } = current;
|
|
100
|
-
this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, rest);
|
|
109
|
+
return this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, rest);
|
|
101
110
|
}
|
|
102
|
-
|
|
103
|
-
const updated = { ...current, [toolId]: mode };
|
|
104
|
-
this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, updated);
|
|
111
|
+
return Promise.resolve();
|
|
105
112
|
}
|
|
113
|
+
const updated = { ...current, [toolId]: mode };
|
|
114
|
+
return this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, updated);
|
|
106
115
|
}
|
|
107
116
|
|
|
108
117
|
/**
|
|
@@ -137,14 +146,37 @@ export class ToolConfirmationManager {
|
|
|
137
146
|
) ?? {};
|
|
138
147
|
}
|
|
139
148
|
|
|
140
|
-
resetAllConfirmationModeSettings(): void {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
resetAllConfirmationModeSettings(): Promise<void> {
|
|
150
|
+
return this.preferenceService.updateValue(TOOL_CONFIRMATION_PREFERENCE, {});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Compute the effective default for a given tool, taking the schema-level default,
|
|
155
|
+
* any product-shipped per-tool default, and the confirmAlwaysAllow flag into account.
|
|
156
|
+
*/
|
|
157
|
+
protected computeEffectiveDefaultForTool(toolId: string, toolRequest?: ToolRequest): ToolConfirmationMode {
|
|
158
|
+
const perToolDefaults = this.preferenceService.inspect(TOOL_CONFIRMATION_PREFERENCE)?.defaultValue as
|
|
159
|
+
| { [toolId: string]: ToolConfirmationMode }
|
|
160
|
+
| undefined;
|
|
161
|
+
const perToolDefault = perToolDefaults?.[toolId];
|
|
162
|
+
if (perToolDefault) {
|
|
163
|
+
return perToolDefault;
|
|
148
164
|
}
|
|
165
|
+
const globalDefault = this.getDefaultConfirmationMode();
|
|
166
|
+
if (toolRequest?.confirmAlwaysAllow && globalDefault === ToolConfirmationMode.ALWAYS_ALLOW) {
|
|
167
|
+
return ToolConfirmationMode.CONFIRM;
|
|
168
|
+
}
|
|
169
|
+
return globalDefault;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Read the schema-level default for the default-confirmation preference.
|
|
174
|
+
* Falls back to CONFIRM if the preference service has not registered the schema yet.
|
|
175
|
+
*/
|
|
176
|
+
protected getDefaultPreferenceSchemaDefault(): ToolConfirmationMode {
|
|
177
|
+
const schemaDefault = this.preferenceService.inspect(DEFAULT_TOOL_CONFIRMATION_PREFERENCE)?.defaultValue as
|
|
178
|
+
| ToolConfirmationMode
|
|
179
|
+
| undefined;
|
|
180
|
+
return schemaDefault ?? ToolConfirmationMode.CONFIRM;
|
|
149
181
|
}
|
|
150
182
|
}
|
|
@@ -54,25 +54,45 @@ export enum ToolConfirmationMode {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export const TOOL_CONFIRMATION_PREFERENCE = 'ai-features.chat.toolConfirmation';
|
|
57
|
+
export const DEFAULT_TOOL_CONFIRMATION_PREFERENCE = 'ai-features.chat.defaultToolConfirmation';
|
|
57
58
|
export const TOOL_CONFIRMATION_TIMEOUT_PREFERENCE = 'ai-features.chat.toolConfirmationTimeout';
|
|
58
59
|
|
|
60
|
+
const TOOL_CONFIRMATION_MODE_VALUES = [
|
|
61
|
+
ToolConfirmationMode.ALWAYS_ALLOW,
|
|
62
|
+
ToolConfirmationMode.CONFIRM,
|
|
63
|
+
ToolConfirmationMode.DISABLED
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const TOOL_CONFIRMATION_MODE_DESCRIPTIONS = [
|
|
67
|
+
nls.localize('theia/ai/chat/toolConfirmation/alwaysAllow/description', 'Execute tools automatically without confirmation'),
|
|
68
|
+
nls.localize('theia/ai/chat/toolConfirmation/confirm/description', 'Ask for confirmation before executing tools'),
|
|
69
|
+
nls.localize('theia/ai/chat/toolConfirmation/disabled/description', 'Disable tool execution')
|
|
70
|
+
];
|
|
71
|
+
|
|
59
72
|
export const chatToolPreferences: PreferenceSchema = {
|
|
60
73
|
properties: {
|
|
74
|
+
[DEFAULT_TOOL_CONFIRMATION_PREFERENCE]: {
|
|
75
|
+
type: 'string',
|
|
76
|
+
enum: TOOL_CONFIRMATION_MODE_VALUES,
|
|
77
|
+
enumDescriptions: TOOL_CONFIRMATION_MODE_DESCRIPTIONS,
|
|
78
|
+
default: ToolConfirmationMode.CONFIRM,
|
|
79
|
+
description: nls.localize('theia/ai/chat/defaultToolConfirmation/description',
|
|
80
|
+
'Default confirmation behavior used for tools that do not have a tool-specific entry under ' +
|
|
81
|
+
'"ai-features.chat.toolConfirmation". Tools that explicitly require confirmation before being auto-approved ' +
|
|
82
|
+
'always default to "confirm" regardless of this setting.'),
|
|
83
|
+
title: AI_CORE_PREFERENCES_TITLE,
|
|
84
|
+
},
|
|
61
85
|
[TOOL_CONFIRMATION_PREFERENCE]: {
|
|
62
86
|
type: 'object',
|
|
63
87
|
additionalProperties: {
|
|
64
88
|
type: 'string',
|
|
65
|
-
enum:
|
|
66
|
-
enumDescriptions:
|
|
67
|
-
nls.localize('theia/ai/chat/toolConfirmation/yolo/description', 'Execute tools automatically without confirmation'),
|
|
68
|
-
nls.localize('theia/ai/chat/toolConfirmation/confirm/description', 'Ask for confirmation before executing tools'),
|
|
69
|
-
nls.localize('theia/ai/chat/toolConfirmation/disabled/description', 'Disable tool execution')
|
|
70
|
-
]
|
|
89
|
+
enum: TOOL_CONFIRMATION_MODE_VALUES,
|
|
90
|
+
enumDescriptions: TOOL_CONFIRMATION_MODE_DESCRIPTIONS
|
|
71
91
|
},
|
|
72
92
|
default: {},
|
|
73
93
|
description: nls.localize('theia/ai/chat/toolConfirmation/description',
|
|
74
|
-
'Configure confirmation behavior for
|
|
75
|
-
'
|
|
94
|
+
'Configure confirmation behavior for individual tools. Key is the tool ID, value is the confirmation mode. ' +
|
|
95
|
+
'To change the default for all tools, use "ai-features.chat.defaultToolConfirmation".'),
|
|
76
96
|
title: AI_CORE_PREFERENCES_TITLE,
|
|
77
97
|
},
|
|
78
98
|
[TOOL_CONFIRMATION_TIMEOUT_PREFERENCE]: {
|
|
@@ -89,5 +109,6 @@ export const chatToolPreferences: PreferenceSchema = {
|
|
|
89
109
|
|
|
90
110
|
export interface ChatToolConfiguration {
|
|
91
111
|
[TOOL_CONFIRMATION_PREFERENCE]: { [toolId: string]: ToolConfirmationMode };
|
|
112
|
+
[DEFAULT_TOOL_CONFIRMATION_PREFERENCE]: ToolConfirmationMode;
|
|
92
113
|
[TOOL_CONFIRMATION_TIMEOUT_PREFERENCE]: number;
|
|
93
114
|
}
|