mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge remote-tracking branch 'origin/main' into dev/dmitriv/fetch-fixes-2
This commit is contained in:
@@ -73,6 +73,13 @@ export class WebPageLoader extends Disposable {
|
||||
.once('did-fail-load', this.onFailLoad.bind(this))
|
||||
.once('will-navigate', this.onRedirect.bind(this))
|
||||
.once('will-redirect', this.onRedirect.bind(this));
|
||||
|
||||
// Disable any UI interactions that could interfere with content loading.
|
||||
this._window.webContents
|
||||
.on('login', (event) => event.preventDefault())
|
||||
.on('select-client-certificate', (event) => event.preventDefault())
|
||||
.on('certificate-error', (event) => event.preventDefault());
|
||||
|
||||
}
|
||||
|
||||
private trace(message: string) {
|
||||
@@ -165,7 +172,12 @@ export class WebPageLoader extends Disposable {
|
||||
}
|
||||
|
||||
this.trace(`Received 'did-fail-load' event, code: ${statusCode}, error: '${error}'`);
|
||||
void this._queue.queue(() => this.extractContent({ status: 'error', statusCode, error }));
|
||||
if (statusCode === -3) {
|
||||
this.trace(`Ignoring ERR_ABORTED (-3) as it may be caused by CSP or other measures`);
|
||||
void this._queue.queue(() => this.extractContent());
|
||||
} else {
|
||||
void this._queue.queue(() => this.extractContent({ status: 'error', statusCode, error }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,14 @@ class MockWebContents {
|
||||
return this;
|
||||
}
|
||||
|
||||
on(event: string, listener: (...args: unknown[]) => void): this {
|
||||
if (!this._listeners.has(event)) {
|
||||
this._listeners.set(event, []);
|
||||
}
|
||||
this._listeners.get(event)!.push(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
emit(event: string, ...args: unknown[]): void {
|
||||
const listeners = this._listeners.get(event) || [];
|
||||
for (const listener of listeners) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { raceCancellationError } from '../../../base/common/async.js';
|
||||
import { CancellationToken } from '../../../base/common/cancellation.js';
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Emitter, Event } from '../../../base/common/event.js';
|
||||
import { IMarkdownString, MarkdownString } from '../../../base/common/htmlContent.js';
|
||||
import { Disposable, DisposableMap, DisposableStore, IDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { ResourceMap } from '../../../base/common/map.js';
|
||||
@@ -16,9 +16,10 @@ import { URI, UriComponents } from '../../../base/common/uri.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { IDialogService } from '../../../platform/dialogs/common/dialogs.js';
|
||||
import { ILogService } from '../../../platform/log/common/log.js';
|
||||
import { ChatViewPaneTarget, IChatWidgetService, isIChatViewViewContext } from '../../contrib/chat/browser/chat.js';
|
||||
import { IChatEditorOptions } from '../../contrib/chat/browser/chatEditor.js';
|
||||
import { ChatEditorInput } from '../../contrib/chat/browser/chatEditorInput.js';
|
||||
import { ChatViewPaneTarget, IChatWidgetService, isIChatViewViewContext } from '../../contrib/chat/browser/chat.js';
|
||||
import { awaitStatsForSession } from '../../contrib/chat/common/chat.js';
|
||||
import { IChatAgentRequest } from '../../contrib/chat/common/chatAgents.js';
|
||||
import { IChatContentInlineReference, IChatProgress, IChatService } from '../../contrib/chat/common/chatService.js';
|
||||
import { IChatSession, IChatSessionContentProvider, IChatSessionHistoryItem, IChatSessionItem, IChatSessionItemProvider, IChatSessionProviderOptionItem, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
@@ -342,7 +343,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
|
||||
this._proxy = this._extHostContext.getProxy(ExtHostContext.ExtHostChatSessions);
|
||||
|
||||
this._chatSessionsService.setOptionsChangeCallback(async (sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string }>) => {
|
||||
this._chatSessionsService.setOptionsChangeCallback(async (sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>) => {
|
||||
const handle = this._getHandleForSessionType(sessionResource.scheme);
|
||||
if (handle !== undefined) {
|
||||
await this.notifyOptionsChange(handle, sessionResource, updates);
|
||||
@@ -360,7 +361,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
const changeEmitter = disposables.add(new Emitter<void>());
|
||||
const provider: IChatSessionItemProvider = {
|
||||
chatSessionType,
|
||||
onDidChangeChatSessionItems: changeEmitter.event,
|
||||
onDidChangeChatSessionItems: Event.debounce(changeEmitter.event, (_, e) => e, 200),
|
||||
provideChatSessionItems: (token) => this._provideChatSessionItems(handle, token),
|
||||
provideNewChatSessionItem: (options, token) => this._provideNewChatSessionItem(handle, options, token)
|
||||
};
|
||||
@@ -448,21 +449,35 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
try {
|
||||
// Get all results as an array from the RPC call
|
||||
const sessions = await this._proxy.$provideChatSessionItems(handle, token);
|
||||
return sessions.map(session => {
|
||||
return Promise.all(sessions.map(async session => {
|
||||
const uri = URI.revive(session.resource);
|
||||
const model = this._chatService.getSession(uri);
|
||||
let description: string | undefined;
|
||||
let statistics: IChatSessionItem['statistics'];
|
||||
if (model) {
|
||||
description = this._chatSessionsService.getSessionDescription(model);
|
||||
}
|
||||
|
||||
const modelStats = model ?
|
||||
await awaitStatsForSession(model) :
|
||||
(await this._chatService.getMetadataForSession(uri))?.stats;
|
||||
if (modelStats) {
|
||||
statistics = {
|
||||
files: modelStats.fileCount,
|
||||
insertions: modelStats.added,
|
||||
deletions: modelStats.removed
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...session,
|
||||
resource: uri,
|
||||
iconPath: session.iconPath,
|
||||
tooltip: session.tooltip ? this._reviveTooltip(session.tooltip) : undefined,
|
||||
description: description || session.description
|
||||
};
|
||||
});
|
||||
description: description || session.description,
|
||||
statistics
|
||||
} satisfies IChatSessionItem;
|
||||
}));
|
||||
} catch (error) {
|
||||
this._logService.error('Error providing chat sessions:', error);
|
||||
}
|
||||
@@ -629,7 +644,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
/**
|
||||
* Notify the extension about option changes for a session
|
||||
*/
|
||||
async notifyOptionsChange(handle: number, sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | undefined }>): Promise<void> {
|
||||
async notifyOptionsChange(handle: number, sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem | undefined }>): Promise<void> {
|
||||
try {
|
||||
await this._proxy.$provideHandleOptionsChange(handle, sessionResource, updates, CancellationToken.None);
|
||||
} catch (error) {
|
||||
|
||||
@@ -3275,12 +3275,12 @@ export type IChatSessionHistoryItemDto = {
|
||||
|
||||
export interface ChatSessionOptionUpdateDto {
|
||||
readonly optionId: string;
|
||||
readonly value: string | undefined;
|
||||
readonly value: string | IChatSessionProviderOptionItem | undefined;
|
||||
}
|
||||
|
||||
export interface ChatSessionOptionUpdateDto2 {
|
||||
readonly optionId: string;
|
||||
readonly value: string;
|
||||
readonly value: string | IChatSessionProviderOptionItem;
|
||||
}
|
||||
|
||||
export interface ChatSessionDto {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { URI, UriComponents } from '../../../base/common/uri.js';
|
||||
import { IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
|
||||
import { ILogService } from '../../../platform/log/common/log.js';
|
||||
import { IChatAgentRequest, IChatAgentResult } from '../../contrib/chat/common/chatAgents.js';
|
||||
import { ChatSessionStatus, IChatSessionItem } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatSessionStatus, IChatSessionItem, IChatSessionProviderOptionItem } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
|
||||
import { Proxied } from '../../services/extensions/common/proxyIdentifier.js';
|
||||
import { ChatSessionDto, ExtHostChatSessionsShape, IChatAgentProgressShape, IChatSessionProviderOptions, MainContext, MainThreadChatSessionsShape } from './extHost.protocol.js';
|
||||
@@ -309,7 +309,7 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio
|
||||
};
|
||||
}
|
||||
|
||||
async $provideHandleOptionsChange(handle: number, sessionResourceComponents: UriComponents, updates: ReadonlyArray<{ optionId: string; value: string | undefined }>, token: CancellationToken): Promise<void> {
|
||||
async $provideHandleOptionsChange(handle: number, sessionResourceComponents: UriComponents, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem | undefined }>, token: CancellationToken): Promise<void> {
|
||||
const sessionResource = URI.revive(sessionResourceComponents);
|
||||
const provider = this._chatSessionContentProviders.get(handle);
|
||||
if (!provider) {
|
||||
@@ -323,7 +323,11 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio
|
||||
}
|
||||
|
||||
try {
|
||||
await provider.provider.provideHandleOptionsChange(sessionResource, updates, token);
|
||||
const updatesToSend = updates.map(update => ({
|
||||
optionId: update.optionId,
|
||||
value: update.value === undefined ? undefined : (typeof update.value === 'string' ? update.value : update.value.id)
|
||||
}));
|
||||
await provider.provider.provideHandleOptionsChange(sessionResource, updatesToSend, token);
|
||||
} catch (error) {
|
||||
this._logService.error(`Error calling provideHandleOptionsChange for handle ${handle}, sessionResource ${sessionResource}:`, error);
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
// React to chat session option changes for the active session
|
||||
this._register(this.chatSessionsService.onDidChangeSessionOptions(e => {
|
||||
const sessionResource = this._widget?.viewModel?.model.sessionResource;
|
||||
if (sessionResource && isEqual(sessionResource, e.resource)) {
|
||||
if (sessionResource && isEqual(sessionResource, e)) {
|
||||
// Options changed for our current session - refresh pickers
|
||||
this.refreshChatSessionPickers();
|
||||
}
|
||||
@@ -710,7 +710,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
this.getOrCreateOptionEmitter(optionGroup.id).fire(option);
|
||||
this.chatSessionsService.notifySessionOptionsChange(
|
||||
ctx.chatSessionResource,
|
||||
[{ optionId: optionGroup.id, value: option.id }]
|
||||
[{ optionId: optionGroup.id, value: option }]
|
||||
).catch(err => this.logService.error(`Failed to notify extension of ${optionGroup.id} change:`, err));
|
||||
},
|
||||
getAllOptions: () => {
|
||||
@@ -1270,9 +1270,16 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
if (currentOption) {
|
||||
const optionGroup = optionGroups.find(g => g.id === optionGroupId);
|
||||
if (optionGroup) {
|
||||
const item = optionGroup.items.find(m => m.id === currentOption);
|
||||
const currentOptionId = typeof currentOption === 'string' ? currentOption : currentOption.id;
|
||||
const item = optionGroup.items.find(m => m.id === currentOptionId);
|
||||
if (item) {
|
||||
this.getOrCreateOptionEmitter(optionGroupId).fire(item);
|
||||
// If currentOption is an object (not a string ID), it represents a complete option item and should be used directly.
|
||||
// Otherwise, if it's a string ID, look up the corresponding item and use that.
|
||||
if (typeof currentOption === 'string') {
|
||||
this.getOrCreateOptionEmitter(optionGroupId).fire(item);
|
||||
} else {
|
||||
this.getOrCreateOptionEmitter(optionGroupId).fire(currentOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
|
||||
private readonly _onDidChangeContentProviderSchemes = this._register(new Emitter<{ readonly added: string[]; readonly removed: string[] }>());
|
||||
public get onDidChangeContentProviderSchemes() { return this._onDidChangeContentProviderSchemes.event; }
|
||||
private readonly _onDidChangeSessionOptions = this._register(new Emitter<{ readonly resource: URI; readonly updates: ReadonlyArray<{ optionId: string; value: string }> }>());
|
||||
private readonly _onDidChangeSessionOptions = this._register(new Emitter<URI>());
|
||||
public get onDidChangeSessionOptions() { return this._onDidChangeSessionOptions.event; }
|
||||
|
||||
private readonly inProgressMap: Map<string, number> = new Map();
|
||||
@@ -1078,7 +1078,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
/**
|
||||
* Notify extension about option changes for a session
|
||||
*/
|
||||
public async notifySessionOptionsChange(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string }>): Promise<void> {
|
||||
public async notifySessionOptionsChange(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>): Promise<void> {
|
||||
if (!updates.length) {
|
||||
return;
|
||||
}
|
||||
@@ -1088,7 +1088,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
for (const u of updates) {
|
||||
this.setSessionOption(sessionResource, u.optionId, u.value);
|
||||
}
|
||||
this._onDidChangeSessionOptions.fire({ resource: sessionResource, updates });
|
||||
this._onDidChangeSessionOptions.fire(sessionResource);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1053,6 +1053,7 @@ export interface IChatService {
|
||||
logChatIndex(): void;
|
||||
getLiveSessionItems(): Promise<IChatDetail[]>;
|
||||
getHistorySessionItems(): Promise<IChatDetail[]>;
|
||||
getMetadataForSession(sessionResource: URI): Promise<IChatDetail | undefined>;
|
||||
|
||||
readonly onDidPerformUserAction: Event<IChatUserActionEvent>;
|
||||
notifyUserAction(event: IChatUserActionEvent): void;
|
||||
|
||||
@@ -39,7 +39,7 @@ import { ChatRequestParser } from './chatRequestParser.js';
|
||||
import { ChatMcpServersStarting, IChatCompleteResponse, IChatDetail, IChatFollowup, IChatModelReference, IChatProgress, IChatSendRequestData, IChatSendRequestOptions, IChatSendRequestResponseState, IChatService, IChatSessionContext, IChatSessionStartOptions, IChatTransferredSessionData, IChatUserActionEvent } from './chatService.js';
|
||||
import { ChatRequestTelemetry, ChatServiceTelemetry } from './chatServiceTelemetry.js';
|
||||
import { IChatSessionsService } from './chatSessionsService.js';
|
||||
import { ChatSessionStore, IChatTransfer2 } from './chatSessionStore.js';
|
||||
import { ChatSessionStore, IChatSessionEntryMetadata, IChatTransfer2 } from './chatSessionStore.js';
|
||||
import { IChatSlashCommandService } from './chatSlashCommands.js';
|
||||
import { IChatTransferService } from './chatTransferService.js';
|
||||
import { LocalChatSessionUri } from './chatUri.js';
|
||||
@@ -153,6 +153,8 @@ export class ChatService extends Disposable implements IChatService {
|
||||
} else if (this._saveModelsEnabled) {
|
||||
await this._chatSessionStore.storeSessions([model]);
|
||||
}
|
||||
} else if (!localSessionId && model.getRequests().length > 0) {
|
||||
await this._chatSessionStore.storeSessionsMetadataOnly([model]);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -217,10 +219,14 @@ export class ChatService extends Disposable implements IChatService {
|
||||
return;
|
||||
}
|
||||
|
||||
const liveChats = Array.from(this._sessionModels.values())
|
||||
const liveLocalChats = Array.from(this._sessionModels.values())
|
||||
.filter(session => this.shouldStoreSession(session));
|
||||
|
||||
this._chatSessionStore.storeSessions(liveChats);
|
||||
this._chatSessionStore.storeSessions(liveLocalChats);
|
||||
|
||||
const liveNonLocalChats = Array.from(this._sessionModels.values())
|
||||
.filter(session => !LocalChatSessionUri.parseLocalSessionId(session.sessionResource));
|
||||
this._chatSessionStore.storeSessionsMetadataOnly(liveNonLocalChats);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,18 +411,32 @@ export class ChatService extends Disposable implements IChatService {
|
||||
async getHistorySessionItems(): Promise<IChatDetail[]> {
|
||||
const index = await this._chatSessionStore.getIndex();
|
||||
return Object.values(index)
|
||||
.filter(entry => !entry.isExternal)
|
||||
.filter(entry => !this._sessionModels.has(LocalChatSessionUri.forSession(entry.sessionId)) && entry.initialLocation === ChatAgentLocation.Chat && !entry.isEmpty)
|
||||
.map((entry): IChatDetail => {
|
||||
const sessionResource = LocalChatSessionUri.forSession(entry.sessionId);
|
||||
return ({
|
||||
...entry,
|
||||
sessionResource,
|
||||
stats: entry.stats,
|
||||
isActive: this._sessionModels.has(sessionResource),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async getMetadataForSession(sessionResource: URI): Promise<IChatDetail | undefined> {
|
||||
const index = await this._chatSessionStore.getIndex();
|
||||
const metadata: IChatSessionEntryMetadata | undefined = index[sessionResource.toString()];
|
||||
if (metadata) {
|
||||
return {
|
||||
...metadata,
|
||||
sessionResource,
|
||||
isActive: this._sessionModels.has(sessionResource),
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private shouldBeInHistory(entry: ChatModel): boolean {
|
||||
return !entry.isImported && !!LocalChatSessionUri.parseLocalSessionId(entry.sessionResource) && entry.initialLocation === ChatAgentLocation.Chat;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { awaitStatsForSession } from './chat.js';
|
||||
import { ModifiedFileEntryState } from './chatEditingService.js';
|
||||
import { ChatModel, IChatModelInputState, ISerializableChatData, ISerializableChatDataIn, ISerializableChatsData, normalizeSerializableChatData } from './chatModel.js';
|
||||
import { IChatSessionStats } from './chatService.js';
|
||||
import { LocalChatSessionUri } from './chatUri.js';
|
||||
import { ChatAgentLocation } from './constants.js';
|
||||
|
||||
const maxPersistedSessions = 25;
|
||||
@@ -102,6 +103,27 @@ export class ChatSessionStore extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
async storeSessionsMetadataOnly(sessions: ChatModel[]): Promise<void> {
|
||||
if (this.shuttingDown) {
|
||||
// Don't start this task if we missed the chance to block shutdown
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.storeTask = this.storeQueue.queue(async () => {
|
||||
try {
|
||||
await Promise.all(sessions.map(session => this.writeSessionMetadataOnly(session)));
|
||||
await this.flushIndex();
|
||||
} catch (e) {
|
||||
this.reportError('storeSessions', 'Error storing chat sessions', e);
|
||||
}
|
||||
});
|
||||
await this.storeTask;
|
||||
} finally {
|
||||
this.storeTask = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// async storeTransferSession(transferData: IChatTransfer, session: ISerializableChatData): Promise<void> {
|
||||
// try {
|
||||
// const content = JSON.stringify(session, undefined, 2);
|
||||
@@ -144,6 +166,23 @@ export class ChatSessionStore extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private async writeSessionMetadataOnly(session: ChatModel): Promise<void> {
|
||||
// Only to be used for external sessions
|
||||
if (LocalChatSessionUri.parseLocalSessionId(session.sessionResource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const index = this.internalGetIndex();
|
||||
|
||||
// TODO get this class on sessionResource
|
||||
const externalSessionId = session.sessionResource.toString();
|
||||
index.entries[externalSessionId] = await getSessionMetadata(session);
|
||||
} catch (e) {
|
||||
this.reportError('sessionMetadataWrite', 'Error writing chat session metadata', e);
|
||||
}
|
||||
}
|
||||
|
||||
private async flushIndex(): Promise<void> {
|
||||
const index = this.internalGetIndex();
|
||||
try {
|
||||
@@ -163,6 +202,7 @@ export class ChatSessionStore extends Disposable {
|
||||
private async trimEntries(): Promise<void> {
|
||||
const index = this.internalGetIndex();
|
||||
const entries = Object.entries(index.entries)
|
||||
.filter(([_id, entry]) => !entry.isExternal)
|
||||
.sort((a, b) => b[1].lastMessageDate - a[1].lastMessageDate)
|
||||
.map(([id]) => id);
|
||||
|
||||
@@ -400,6 +440,11 @@ export interface IChatSessionEntryMetadata {
|
||||
* filter the old ones out of history.
|
||||
*/
|
||||
isEmpty?: boolean;
|
||||
|
||||
/**
|
||||
* Whether this session was loaded from an external provider (eg background/cloud sessions).
|
||||
*/
|
||||
isExternal?: boolean;
|
||||
}
|
||||
|
||||
function isChatSessionEntryMetadata(obj: unknown): obj is IChatSessionEntryMetadata {
|
||||
@@ -459,7 +504,8 @@ async function getSessionMetadata(session: ChatModel | ISerializableChatData): P
|
||||
initialLocation: session.initialLocation,
|
||||
hasPendingEdits: session instanceof ChatModel ? (session.editingSession?.entries.get().some(e => e.state.get() === ModifiedFileEntryState.Modified)) : false,
|
||||
isEmpty: session instanceof ChatModel ? session.getRequests().length === 0 : session.requests.length === 0,
|
||||
stats
|
||||
stats,
|
||||
isExternal: session instanceof ChatModel && !LocalChatSessionUri.parseLocalSessionId(session.sessionResource)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ export interface IChatSessionContentProvider {
|
||||
|
||||
export type SessionOptionsChangedCallback = (sessionResource: URI, updates: ReadonlyArray<{
|
||||
optionId: string;
|
||||
value: string;
|
||||
value: string | IChatSessionProviderOptionItem;
|
||||
}>) => Promise<void>;
|
||||
|
||||
export interface IChatSessionsService {
|
||||
@@ -203,7 +203,7 @@ export interface IChatSessionsService {
|
||||
/**
|
||||
* Fired when options for a chat session change.
|
||||
*/
|
||||
onDidChangeSessionOptions: Event<{ readonly resource: URI; readonly updates: ReadonlyArray<{ optionId: string; value: string }> }>;
|
||||
onDidChangeSessionOptions: Event<URI>;
|
||||
|
||||
/**
|
||||
* Get the capabilities for a specific session type
|
||||
@@ -213,7 +213,7 @@ export interface IChatSessionsService {
|
||||
getOptionGroupsForSessionType(chatSessionType: string): IChatSessionProviderOptionGroup[] | undefined;
|
||||
setOptionGroupsForSessionType(chatSessionType: string, handle: number, optionGroups?: IChatSessionProviderOptionGroup[]): void;
|
||||
setOptionsChangeCallback(callback: SessionOptionsChangedCallback): void;
|
||||
notifySessionOptionsChange(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string }>): Promise<void>;
|
||||
notifySessionOptionsChange(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>): Promise<void>;
|
||||
|
||||
// Editable session support
|
||||
setEditableSession(sessionResource: URI, data: IEditableData | null): Promise<void>;
|
||||
|
||||
@@ -181,6 +181,10 @@ class MockChatService implements IChatService {
|
||||
waitForModelDisposals(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getMetadataForSession(sessionResource: URI): Promise<IChatDetail | undefined> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
function createMockChatModel(options: {
|
||||
|
||||
@@ -146,4 +146,7 @@ export class MockChatService implements IChatService {
|
||||
waitForModelDisposals(): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getMetadataForSession(sessionResource: URI): Promise<IChatDetail | undefined> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IChatSession, IChatSessionContentProvider, IChatSessionItem, IChatSessi
|
||||
export class MockChatSessionsService implements IChatSessionsService {
|
||||
_serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeSessionOptions = new Emitter<{ readonly resource: URI; readonly updates: ReadonlyArray<{ optionId: string; value: string }> }>();
|
||||
private readonly _onDidChangeSessionOptions = new Emitter<URI>();
|
||||
readonly onDidChangeSessionOptions = this._onDidChangeSessionOptions.event;
|
||||
private readonly _onDidChangeItemsProviders = new Emitter<IChatSessionItemProvider>();
|
||||
readonly onDidChangeItemsProviders = this._onDidChangeItemsProviders.event;
|
||||
|
||||
@@ -306,7 +306,9 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
|
||||
const quickSuggestionsConfig = this._configurationService.getValue<ITerminalSuggestConfiguration>(terminalSuggestConfigSection).quickSuggestions;
|
||||
const allowFallbackCompletions = explicitlyInvoked || quickSuggestionsConfig.unknown === 'on';
|
||||
this._logService.trace('SuggestAddon#_handleCompletionProviders provideCompletions');
|
||||
const providedCompletions = await this._terminalCompletionService.provideCompletions(this._currentPromptInputState.value, this._currentPromptInputState.cursorIndex, allowFallbackCompletions, this.shellType, this._capabilities, token, false, doNotRequestExtensionCompletions, explicitlyInvoked);
|
||||
// Trim ghost text from the prompt value when requesting completions
|
||||
const promptValue = this._mostRecentPromptInputState?.ghostTextIndex !== undefined ? this._currentPromptInputState.value.substring(0, this._mostRecentPromptInputState?.ghostTextIndex) : this._currentPromptInputState.value;
|
||||
const providedCompletions = await this._terminalCompletionService.provideCompletions(promptValue, this._currentPromptInputState.cursorIndex, allowFallbackCompletions, this.shellType, this._capabilities, token, false, doNotRequestExtensionCompletions, explicitlyInvoked);
|
||||
this._logService.trace('SuggestAddon#_handleCompletionProviders provideCompletions done');
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
|
||||
@@ -199,7 +199,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* The new value assigned to the option. When `undefined`, the option is cleared.
|
||||
*/
|
||||
readonly value: string;
|
||||
readonly value: string | ChatSessionProviderOptionItem;
|
||||
}>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user