@theia/ai-chat 1.63.0-next.52 → 1.63.1
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/ai-chat-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-chat-frontend-module.js +0 -1
- package/lib/browser/ai-chat-frontend-module.js.map +1 -1
- package/lib/browser/change-set-file-element.d.ts +28 -7
- package/lib/browser/change-set-file-element.d.ts.map +1 -1
- package/lib/browser/change-set-file-element.js +145 -24
- package/lib/browser/change-set-file-element.js.map +1 -1
- package/lib/browser/frontend-chat-service.d.ts +1 -1
- package/lib/browser/frontend-chat-service.d.ts.map +1 -1
- package/lib/browser/frontend-chat-service.js +2 -13
- package/lib/browser/frontend-chat-service.js.map +1 -1
- package/lib/common/chat-model.d.ts +5 -5
- package/lib/common/chat-model.d.ts.map +1 -1
- package/lib/common/chat-model.js.map +1 -1
- package/lib/common/chat-request-parser.d.ts.map +1 -1
- package/lib/common/chat-request-parser.js +0 -6
- package/lib/common/chat-request-parser.js.map +1 -1
- package/lib/common/chat-service.d.ts +11 -0
- package/lib/common/chat-service.d.ts.map +1 -1
- package/lib/common/chat-service.js +32 -7
- package/lib/common/chat-service.js.map +1 -1
- package/lib/common/chat-session-naming-service.js +2 -2
- package/lib/common/chat-session-naming-service.js.map +1 -1
- package/lib/common/chat-session-summary-agent-prompt.js +3 -3
- package/lib/common/chat-session-summary-agent-prompt.js.map +1 -1
- package/lib/common/chat-tool-request-service.d.ts +2 -2
- package/lib/common/chat-tool-request-service.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/browser/ai-chat-frontend-module.ts +0 -1
- package/src/browser/change-set-file-element.ts +168 -24
- package/src/browser/frontend-chat-service.ts +2 -11
- package/src/common/chat-model.ts +5 -4
- package/src/common/chat-request-parser.ts +0 -12
- package/src/common/chat-service.ts +35 -6
- package/src/common/chat-session-naming-service.ts +2 -2
- package/src/common/chat-session-summary-agent-prompt.ts +3 -3
- package/src/common/chat-tool-request-service.ts +2 -2
|
@@ -14,16 +14,29 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { DisposableCollection, Emitter, URI } from '@theia/core';
|
|
18
|
-
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
19
|
-
import { Replacement } from '@theia/core/lib/common/content-replacer';
|
|
20
17
|
import { ConfigurableInMemoryResources, ConfigurableMutableReferenceResource } from '@theia/ai-core';
|
|
18
|
+
import { CancellationToken, DisposableCollection, Emitter, URI } from '@theia/core';
|
|
19
|
+
import { ConfirmDialog } from '@theia/core/lib/browser';
|
|
20
|
+
import { Replacement } from '@theia/core/lib/common/content-replacer';
|
|
21
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
22
|
+
import { EditorPreferences } from '@theia/editor/lib/browser';
|
|
23
|
+
import { FileSystemPreferences } from '@theia/filesystem/lib/browser';
|
|
24
|
+
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
25
|
+
import { IReference } from '@theia/monaco-editor-core/esm/vs/base/common/lifecycle';
|
|
26
|
+
import { TrimTrailingWhitespaceCommand } from '@theia/monaco-editor-core/esm/vs/editor/common/commands/trimTrailingWhitespaceCommand';
|
|
27
|
+
import { Selection } from '@theia/monaco-editor-core/esm/vs/editor/common/core/selection';
|
|
28
|
+
import { CommandExecutor } from '@theia/monaco-editor-core/esm/vs/editor/common/cursor/cursor';
|
|
29
|
+
import { formatDocumentWithSelectedProvider, FormattingMode } from '@theia/monaco-editor-core/esm/vs/editor/contrib/format/browser/format';
|
|
30
|
+
import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
|
|
31
|
+
import { IInstantiationService } from '@theia/monaco-editor-core/esm/vs/platform/instantiation/common/instantiation';
|
|
32
|
+
import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
|
|
33
|
+
import { insertFinalNewline } from '@theia/monaco/lib/browser/monaco-utilities';
|
|
34
|
+
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
|
|
21
35
|
import { ChangeSetElement } from '../common';
|
|
22
36
|
import { createChangeSetFileUri } from './change-set-file-resource';
|
|
23
37
|
import { ChangeSetFileService } from './change-set-file-service';
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { ChangeSetDecoratorService } from './change-set-decorator-service';
|
|
38
|
+
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
39
|
+
import { MonacoCodeActionService } from '@theia/monaco/lib/browser';
|
|
27
40
|
|
|
28
41
|
export const ChangeSetFileElementFactory = Symbol('ChangeSetFileElementFactory');
|
|
29
42
|
export type ChangeSetFileElementFactory = (elementProps: ChangeSetElementArgs) => ChangeSetFileElement;
|
|
@@ -62,16 +75,23 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
62
75
|
@inject(ChangeSetFileService)
|
|
63
76
|
protected readonly changeSetFileService: ChangeSetFileService;
|
|
64
77
|
|
|
65
|
-
@inject(ChangeSetDecoratorService)
|
|
66
|
-
protected readonly changeSetDecoratorService: ChangeSetDecoratorService;
|
|
67
|
-
|
|
68
78
|
@inject(FileService)
|
|
69
79
|
protected readonly fileService: FileService;
|
|
70
80
|
|
|
71
81
|
@inject(ConfigurableInMemoryResources)
|
|
72
82
|
protected readonly inMemoryResources: ConfigurableInMemoryResources;
|
|
73
83
|
|
|
74
|
-
@inject(
|
|
84
|
+
@inject(MonacoTextModelService)
|
|
85
|
+
protected readonly monacoTextModelService: MonacoTextModelService;
|
|
86
|
+
|
|
87
|
+
@inject(EditorPreferences)
|
|
88
|
+
protected readonly editorPreferences: EditorPreferences;
|
|
89
|
+
|
|
90
|
+
@inject(FileSystemPreferences)
|
|
91
|
+
protected readonly fileSystemPreferences: FileSystemPreferences;
|
|
92
|
+
|
|
93
|
+
@inject(MonacoCodeActionService)
|
|
94
|
+
protected readonly codeActionService: MonacoCodeActionService;
|
|
75
95
|
|
|
76
96
|
protected readonly toDispose = new DisposableCollection();
|
|
77
97
|
protected _state: ChangeSetElementState;
|
|
@@ -79,11 +99,13 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
79
99
|
private _originalContent: string | undefined;
|
|
80
100
|
protected _initialized = false;
|
|
81
101
|
protected _initializationPromise: Promise<void> | undefined;
|
|
102
|
+
protected _targetStateWithCodeActions: string | undefined;
|
|
103
|
+
protected codeActionDeferred?: Deferred<string>;
|
|
82
104
|
|
|
83
105
|
protected readonly onDidChangeEmitter = new Emitter<void>();
|
|
84
106
|
readonly onDidChange = this.onDidChangeEmitter.event;
|
|
85
|
-
protected _readOnlyResource
|
|
86
|
-
protected _changeResource
|
|
107
|
+
protected _readOnlyResource?: ConfigurableMutableReferenceResource;
|
|
108
|
+
protected _changeResource?: ConfigurableMutableReferenceResource;
|
|
87
109
|
|
|
88
110
|
@postConstruct()
|
|
89
111
|
init(): void {
|
|
@@ -174,7 +196,8 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
174
196
|
protected get changeResource(): ConfigurableMutableReferenceResource {
|
|
175
197
|
if (!this._changeResource) {
|
|
176
198
|
this._changeResource = this.getInMemoryUri(createChangeSetFileUri(this.elementProps.chatSessionId, this.uri));
|
|
177
|
-
this._changeResource.update({ autosaveable: false });
|
|
199
|
+
this._changeResource.update({ autosaveable: false, contents: this.targetState });
|
|
200
|
+
this.applyCodeActionsToTargetState();
|
|
178
201
|
this.toDispose.push(this._changeResource);
|
|
179
202
|
}
|
|
180
203
|
return this._changeResource;
|
|
@@ -236,6 +259,10 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
236
259
|
}
|
|
237
260
|
|
|
238
261
|
get targetState(): string {
|
|
262
|
+
return this._targetStateWithCodeActions ?? this.elementProps.targetState ?? '';
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
get originalTargetState(): string {
|
|
239
266
|
return this.elementProps.targetState ?? '';
|
|
240
267
|
}
|
|
241
268
|
|
|
@@ -255,14 +282,16 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
255
282
|
async apply(contents?: string): Promise<void> {
|
|
256
283
|
await this.ensureInitialized();
|
|
257
284
|
if (!await this.confirm('Apply')) { return; }
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
285
|
+
|
|
286
|
+
if (this.type === 'delete') {
|
|
287
|
+
await this.changeSetFileService.delete(this.uri);
|
|
288
|
+
this.state = 'applied';
|
|
289
|
+
this.changeSetFileService.closeDiff(this.readOnlyUri);
|
|
290
|
+
return;
|
|
265
291
|
}
|
|
292
|
+
|
|
293
|
+
// Load Monaco model for the base file URI and apply changes
|
|
294
|
+
await this.applyChangesWithMonaco(contents);
|
|
266
295
|
this.changeSetFileService.closeDiff(this.readOnlyUri);
|
|
267
296
|
}
|
|
268
297
|
|
|
@@ -271,9 +300,124 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
271
300
|
this.state = 'applied';
|
|
272
301
|
}
|
|
273
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Applies changes using Monaco utilities, including loading the model for the base file URI,
|
|
305
|
+
* setting the value to the intended state, and running code actions on save.
|
|
306
|
+
*/
|
|
307
|
+
protected async applyChangesWithMonaco(contents?: string): Promise<void> {
|
|
308
|
+
let modelReference: IReference<MonacoEditorModel> | undefined;
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
modelReference = await this.monacoTextModelService.createModelReference(this.uri);
|
|
312
|
+
const model = modelReference.object;
|
|
313
|
+
const targetContent = contents ?? this.targetState;
|
|
314
|
+
model.textEditorModel.setValue(targetContent);
|
|
315
|
+
|
|
316
|
+
const languageId = model.languageId;
|
|
317
|
+
const uriStr = this.uri.toString();
|
|
318
|
+
|
|
319
|
+
await this.codeActionService.applyOnSaveCodeActions(model.textEditorModel, languageId, uriStr, CancellationToken.None);
|
|
320
|
+
await this.applyFormatting(model, languageId, uriStr);
|
|
321
|
+
|
|
322
|
+
await model.save();
|
|
323
|
+
this.state = 'applied';
|
|
324
|
+
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error('Failed to apply changes with Monaco:', error);
|
|
327
|
+
await this.writeChanges(contents);
|
|
328
|
+
} finally {
|
|
329
|
+
modelReference?.dispose();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
protected applyCodeActionsToTargetState(): Promise<string> {
|
|
334
|
+
if (!this.codeActionDeferred) {
|
|
335
|
+
this.codeActionDeferred = new Deferred();
|
|
336
|
+
this.codeActionDeferred.resolve(this.doApplyCodeActionsToTargetState());
|
|
337
|
+
}
|
|
338
|
+
return this.codeActionDeferred.promise;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
protected async doApplyCodeActionsToTargetState(): Promise<string> {
|
|
342
|
+
const targetState = this.originalTargetState;
|
|
343
|
+
if (!targetState) {
|
|
344
|
+
this._targetStateWithCodeActions = '';
|
|
345
|
+
return this._targetStateWithCodeActions;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
let tempResource: ConfigurableMutableReferenceResource | undefined;
|
|
349
|
+
let tempModel: IReference<MonacoEditorModel> | undefined;
|
|
350
|
+
try {
|
|
351
|
+
// Create a temporary model to apply code actions
|
|
352
|
+
const tempUri = new URI(`untitled://changeset/${Date.now()}${this.uri.path.ext}`);
|
|
353
|
+
tempResource = this.inMemoryResources.add(tempUri, { contents: this.targetState });
|
|
354
|
+
tempModel = await this.monacoTextModelService.createModelReference(tempUri);
|
|
355
|
+
tempModel.object.suppressOpenEditorWhenDirty = true;
|
|
356
|
+
tempModel.object.textEditorModel.setValue(this.targetState);
|
|
357
|
+
|
|
358
|
+
const languageId = tempModel.object.languageId;
|
|
359
|
+
const uriStr = this.uri.toString();
|
|
360
|
+
|
|
361
|
+
await this.codeActionService.applyOnSaveCodeActions(tempModel.object.textEditorModel, languageId, uriStr, CancellationToken.None);
|
|
362
|
+
|
|
363
|
+
// Apply formatting and other editor preferences
|
|
364
|
+
await this.applyFormatting(tempModel.object, languageId, uriStr);
|
|
365
|
+
|
|
366
|
+
this._targetStateWithCodeActions = tempModel.object.textEditorModel.getValue();
|
|
367
|
+
if (this._changeResource?.contents === this.elementProps.targetState) {
|
|
368
|
+
this._changeResource?.update({ contents: this.targetState });
|
|
369
|
+
}
|
|
370
|
+
} catch (error) {
|
|
371
|
+
console.warn('Failed to apply code actions to target state:', error);
|
|
372
|
+
this._targetStateWithCodeActions = targetState;
|
|
373
|
+
} finally {
|
|
374
|
+
tempModel?.dispose();
|
|
375
|
+
tempResource?.dispose();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return this.targetState;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Applies formatting preferences like format on save, trim trailing whitespace, and insert final newline.
|
|
383
|
+
*/
|
|
384
|
+
protected async applyFormatting(model: MonacoEditorModel, languageId: string, uriStr: string): Promise<void> {
|
|
385
|
+
try {
|
|
386
|
+
const formatOnSave = this.editorPreferences.get({ preferenceName: 'editor.formatOnSave', overrideIdentifier: languageId }, undefined, uriStr);
|
|
387
|
+
if (formatOnSave) {
|
|
388
|
+
const instantiation = StandaloneServices.get(IInstantiationService);
|
|
389
|
+
await instantiation.invokeFunction(
|
|
390
|
+
formatDocumentWithSelectedProvider,
|
|
391
|
+
model.textEditorModel,
|
|
392
|
+
FormattingMode.Explicit,
|
|
393
|
+
{ report(): void { } },
|
|
394
|
+
CancellationToken.None, true
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const trimTrailingWhitespace = this.fileSystemPreferences.get({ preferenceName: 'files.trimTrailingWhitespace', overrideIdentifier: languageId }, undefined, uriStr);
|
|
399
|
+
if (trimTrailingWhitespace) {
|
|
400
|
+
const ttws = new TrimTrailingWhitespaceCommand(new Selection(1, 1, 1, 1), [], false);
|
|
401
|
+
CommandExecutor.executeCommands(model.textEditorModel, [], [ttws]);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const shouldInsertFinalNewline = this.fileSystemPreferences.get({ preferenceName: 'files.insertFinalNewline', overrideIdentifier: languageId }, undefined, uriStr);
|
|
405
|
+
if (shouldInsertFinalNewline) {
|
|
406
|
+
insertFinalNewline(model);
|
|
407
|
+
}
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.warn('Failed to apply formatting:', error);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
274
413
|
onShow(): void {
|
|
275
|
-
|
|
276
|
-
|
|
414
|
+
this.changeResource.update({
|
|
415
|
+
contents: this.targetState,
|
|
416
|
+
onSave: async content => {
|
|
417
|
+
// Use Monaco utilities when saving from the change resource
|
|
418
|
+
await this.applyChangesWithMonaco(content);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
277
421
|
}
|
|
278
422
|
|
|
279
423
|
async revert(): Promise<void> {
|
|
@@ -290,11 +434,11 @@ export class ChangeSetFileElement implements ChangeSetElement {
|
|
|
290
434
|
async confirm(verb: string): Promise<boolean> {
|
|
291
435
|
if (this._state !== 'stale') { return true; }
|
|
292
436
|
await this.openChange();
|
|
293
|
-
const
|
|
437
|
+
const answer = await new ConfirmDialog({
|
|
294
438
|
title: `${verb} suggestion.`,
|
|
295
439
|
msg: `The file ${this.uri.path.toString()} has changed since this suggestion was created. Are you certain you wish to ${verb.toLowerCase()} the change?`
|
|
296
440
|
}).open(true);
|
|
297
|
-
return !!
|
|
441
|
+
return !!answer;
|
|
298
442
|
}
|
|
299
443
|
|
|
300
444
|
dispose(): void {
|
|
@@ -32,17 +32,8 @@ export class FrontendChatServiceImpl extends ChatServiceImpl {
|
|
|
32
32
|
@inject(ChangeSetFileService)
|
|
33
33
|
protected readonly changeSetFileService: ChangeSetFileService;
|
|
34
34
|
|
|
35
|
-
protected override
|
|
36
|
-
|
|
37
|
-
if (!this.preferenceService.get<boolean>(PIN_CHAT_AGENT_PREF)) {
|
|
38
|
-
return agent;
|
|
39
|
-
}
|
|
40
|
-
if (!session.pinnedAgent && agent && agent.id !== this.defaultChatAgentId?.id) {
|
|
41
|
-
session.pinnedAgent = agent;
|
|
42
|
-
} else if (session.pinnedAgent && this.getMentionedAgent(parsedRequest) === undefined) {
|
|
43
|
-
agent = session.pinnedAgent;
|
|
44
|
-
}
|
|
45
|
-
return agent;
|
|
35
|
+
protected override isPinChatAgentEnabled(): boolean {
|
|
36
|
+
return this.preferenceService.get<boolean>(PIN_CHAT_AGENT_PREF, true);
|
|
46
37
|
}
|
|
47
38
|
|
|
48
39
|
protected override initialAgentSelection(parsedRequest: ParsedChatRequest): ChatAgent | undefined {
|
package/src/common/chat-model.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
ResolvedAIContextVariable,
|
|
26
26
|
TextMessage,
|
|
27
27
|
ThinkingMessage,
|
|
28
|
+
ToolCallResult,
|
|
28
29
|
ToolResultMessage,
|
|
29
30
|
ToolUseMessage
|
|
30
31
|
} from '@theia/ai-core';
|
|
@@ -389,7 +390,7 @@ export interface ToolCallChatResponseContent extends Required<ChatResponseConten
|
|
|
389
390
|
name?: string;
|
|
390
391
|
arguments?: string;
|
|
391
392
|
finished: boolean;
|
|
392
|
-
result?:
|
|
393
|
+
result?: ToolCallResult;
|
|
393
394
|
confirmed: Promise<boolean>;
|
|
394
395
|
confirm(): void;
|
|
395
396
|
deny(): void;
|
|
@@ -1497,12 +1498,12 @@ export class ToolCallChatResponseContentImpl implements ToolCallChatResponseCont
|
|
|
1497
1498
|
protected _name?: string;
|
|
1498
1499
|
protected _arguments?: string;
|
|
1499
1500
|
protected _finished?: boolean;
|
|
1500
|
-
protected _result?:
|
|
1501
|
+
protected _result?: ToolCallResult;
|
|
1501
1502
|
protected _confirmed: Promise<boolean>;
|
|
1502
1503
|
protected _confirmationResolver?: (value: boolean) => void;
|
|
1503
1504
|
protected _confirmationRejecter?: (reason?: unknown) => void;
|
|
1504
1505
|
|
|
1505
|
-
constructor(id?: string, name?: string, arg_string?: string, finished?: boolean, result?:
|
|
1506
|
+
constructor(id?: string, name?: string, arg_string?: string, finished?: boolean, result?: ToolCallResult) {
|
|
1506
1507
|
this._id = id;
|
|
1507
1508
|
this._name = name;
|
|
1508
1509
|
this._arguments = arg_string;
|
|
@@ -1527,7 +1528,7 @@ export class ToolCallChatResponseContentImpl implements ToolCallChatResponseCont
|
|
|
1527
1528
|
get finished(): boolean {
|
|
1528
1529
|
return this._finished === undefined ? false : this._finished;
|
|
1529
1530
|
}
|
|
1530
|
-
get result():
|
|
1531
|
+
get result(): ToolCallResult | undefined {
|
|
1531
1532
|
return this._result;
|
|
1532
1533
|
}
|
|
1533
1534
|
|
|
@@ -228,18 +228,6 @@ export class ChatRequestParserImpl implements ChatRequestParser {
|
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
// The agent must come first
|
|
232
|
-
if (
|
|
233
|
-
parts.some(
|
|
234
|
-
p =>
|
|
235
|
-
(p instanceof ParsedChatRequestTextPart &&
|
|
236
|
-
p.text.trim() !== '') ||
|
|
237
|
-
!(p instanceof ParsedChatRequestAgentPart)
|
|
238
|
-
)
|
|
239
|
-
) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
231
|
return new ParsedChatRequestAgentPart(agentRange, agent.id, agent.name);
|
|
244
232
|
}
|
|
245
233
|
|
|
@@ -313,15 +313,44 @@ export class ChatServiceImpl implements ChatService {
|
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
protected getAgent(parsedRequest: ParsedChatRequest, session: ChatSession): ChatAgent | undefined {
|
|
316
|
-
|
|
317
|
-
if (this.
|
|
316
|
+
const agent = this.initialAgentSelection(parsedRequest);
|
|
317
|
+
if (!this.isPinChatAgentEnabled()) {
|
|
318
318
|
return agent;
|
|
319
319
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
320
|
+
|
|
321
|
+
return this.handlePinnedAgent(parsedRequest, session, agent);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Determines if chat agent pinning is enabled.
|
|
326
|
+
* Can be overridden by subclasses to provide different logic (e.g., using preferences).
|
|
327
|
+
*/
|
|
328
|
+
protected isPinChatAgentEnabled(): boolean {
|
|
329
|
+
return this.pinChatAgent !== false;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Handle pinned agent by:
|
|
334
|
+
* - checking if an agent is pinned, and use it if no other agent is mentioned
|
|
335
|
+
* - pinning the current agent
|
|
336
|
+
*/
|
|
337
|
+
protected handlePinnedAgent(parsedRequest: ParsedChatRequest, session: ChatSession, agent: ChatAgent | undefined): ChatAgent | undefined {
|
|
338
|
+
const mentionedAgentPart = this.getMentionedAgent(parsedRequest);
|
|
339
|
+
const mentionedAgent = mentionedAgentPart ? this.chatAgentService.getAgent(mentionedAgentPart.agentId) : undefined;
|
|
340
|
+
if (mentionedAgent) {
|
|
341
|
+
// If an agent is explicitly mentioned, it becomes the new pinned agent
|
|
342
|
+
session.pinnedAgent = mentionedAgent;
|
|
343
|
+
return mentionedAgent;
|
|
344
|
+
} else if (session.pinnedAgent) {
|
|
345
|
+
// If we have a valid pinned agent, use it (pinned agent may become stale
|
|
346
|
+
// if it was disabled; so we always need to recheck)
|
|
347
|
+
const pinnedAgent = this.chatAgentService.getAgent(session.pinnedAgent.id);
|
|
348
|
+
if (pinnedAgent) {
|
|
349
|
+
return pinnedAgent;
|
|
350
|
+
}
|
|
324
351
|
}
|
|
352
|
+
// Otherwise, override the pinned agent and return the suggested one
|
|
353
|
+
session.pinnedAgent = agent;
|
|
325
354
|
return agent;
|
|
326
355
|
}
|
|
327
356
|
|
|
@@ -30,9 +30,9 @@ import { ChatSession } from './chat-service';
|
|
|
30
30
|
import { generateUuid } from '@theia/core';
|
|
31
31
|
|
|
32
32
|
const CHAT_SESSION_NAMING_PROMPT: PromptVariantSet = {
|
|
33
|
-
id: 'chat-session-naming-
|
|
33
|
+
id: 'chat-session-naming-system',
|
|
34
34
|
defaultVariant: {
|
|
35
|
-
id: 'chat-session-naming-
|
|
35
|
+
id: 'chat-session-naming-system-default',
|
|
36
36
|
template: '{{!-- Made improvements or adaptations to this prompt template? We\'d love for you to share it with the community! Contribute back here: ' +
|
|
37
37
|
'https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}\n\n' +
|
|
38
38
|
'Provide a short and descriptive name for the given AI chat conversation of an AI-powered tool based on the conversation below.\n\n' +
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
import { CHANGE_SET_SUMMARY_VARIABLE_ID } from './context-variables';
|
|
12
12
|
|
|
13
13
|
export const CHAT_SESSION_SUMMARY_PROMPT = {
|
|
14
|
-
id: 'chat-session-summary-system
|
|
14
|
+
id: 'chat-session-summary-system',
|
|
15
15
|
defaultVariant: {
|
|
16
|
-
id: 'chat-session-summary-
|
|
16
|
+
id: 'chat-session-summary-system-default',
|
|
17
17
|
template: '{{!-- !-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).\n' +
|
|
18
18
|
'Made improvements or adaptations to this prompt template? We\'d love for you to share it with the community! Contribute back here: ' +
|
|
19
19
|
'https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}\n\n' +
|
|
@@ -23,7 +23,7 @@ export const CHAT_SESSION_SUMMARY_PROMPT = {
|
|
|
23
23
|
'Ensure that the summary is sufficiently comprehensive to allow seamless continuation of the workflow. ' +
|
|
24
24
|
'The summary will primarily be used by other AI agents, so tailor your response for use by AI agents. ' +
|
|
25
25
|
'Also consider the system message. ' +
|
|
26
|
-
'Make sure you include all necessary context information and use unique references(such as URIs, file paths, etc.). ' +
|
|
26
|
+
'Make sure you include all necessary context information and use unique references (such as URIs, file paths, etc.). ' +
|
|
27
27
|
'If the conversation was about a task, describe the state of the task, i.e.what has been completed and what is open. ' +
|
|
28
28
|
'If a changeset is open in the session, describe the state of the suggested changes. ' +
|
|
29
29
|
`\n\n{{${CHANGE_SET_SUMMARY_VARIABLE_ID}}}`,
|
|
@@ -19,8 +19,8 @@ import { injectable } from '@theia/core/shared/inversify';
|
|
|
19
19
|
import { MutableChatRequestModel } from './chat-model';
|
|
20
20
|
|
|
21
21
|
export interface ChatToolRequest extends ToolRequest {
|
|
22
|
-
handler(arg_string: string, context: MutableChatRequestModel):
|
|
23
|
-
handler(arg_string: string, ctx?: unknown):
|
|
22
|
+
handler(arg_string: string, context: MutableChatRequestModel): ReturnType<ToolRequest['handler']>;
|
|
23
|
+
handler(arg_string: string, ctx?: unknown): ReturnType<ToolRequest['handler']>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|