chat: initial rough draft of request queuing#292619
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces initial infrastructure for chat request queuing and “steering” messages, along with the necessary API, model, view-model, and UI wiring to surface queued requests in the chat experience.
Changes:
- Extend the chat service API and models with a
ChatSendResultdiscriminated union,ChatRequestQueueKind, and per-session pending-request queues, including new service methods to manage pending requests and steering (setYieldRequested,removePendingRequest,setPendingRequests). - Update the chat view model, list renderer, widget, and actions to display queued and steering requests (including divider rows), add new queue-related toolbar actions, and introduce an experimental
chat.requestQueuing.enabledconfiguration setting. - Plumb a new
yieldRequestedflag through proposed chat participant APIs and ext host contexts, and adjust tests and mocks to the new send semantics and pending-queue surface.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts |
Adds ChatContext.yieldRequested to the proposed chat participant private API for steering-aware providers. |
src/vs/workbench/contrib/chat/test/common/model/mockChatModel.ts |
Extends the mock chat model to implement onDidChangePendingRequests and getPendingRequests to satisfy the updated IChatModel interface. |
src/vs/workbench/contrib/chat/test/common/chatService/mockChatService.ts |
Adjusts the mock chat service to the new ChatSendResult return type and adds stubs for queue-related methods. |
src/vs/workbench/contrib/chat/test/common/chatService/chatService.test.ts |
Updates tests to work with ChatSendResult, asserting sent results and accessing response promises via response.data. |
src/vs/workbench/contrib/chat/test/browser/widget/chatContentParts/chatThinkingContentPart.test.ts |
Switches the test render context’s element type from ChatTreeItem to IChatResponseViewModel to align with the new content-part context. |
src/vs/workbench/contrib/chat/test/browser/widget/chatContentParts/chatSubagentContentPart.test.ts |
Same type adjustment as above for the subagent content part tests. |
src/vs/workbench/contrib/chat/test/browser/agentSessions/localAgentSessionsProvider.test.ts |
Updates the test MockChatService to include queue-related methods and imports ChatRequestQueueKind. |
src/vs/workbench/contrib/chat/common/participants/chatAgents.ts |
Adds an optional yieldRequested?: boolean field to IChatAgentRequest to carry steering signals to agents. |
src/vs/workbench/contrib/chat/common/model/chatViewModel.ts |
Extends the view model with IChatPendingDividerViewModel, pendingKind on requests, wiring to model’s pending-requests events, and getItems() logic to append steering/queued divider items and pending request view models. |
src/vs/workbench/contrib/chat/common/model/chatModel.ts |
Introduces IChatPendingRequest and pending-request queue management APIs (getPendingRequests, addPendingRequest, removePendingRequest, dequeuePendingRequest, clearPendingRequests, setPendingRequests) on ChatModel. |
src/vs/workbench/contrib/chat/common/constants.ts |
Adds ChatConfiguration.RequestQueueingEnabled = 'chat.requestQueuing.enabled' for gating the experimental queuing feature. |
src/vs/workbench/contrib/chat/common/chatService/chatServiceImpl.ts |
Refactors sendRequest to return ChatSendResult, implements queueing logic with ChatRequestQueueKind, tracks in-flight requests via CancellableRequest, processes queued requests via processNextPendingRequest, and exposes setYieldRequested, removePendingRequest, and setPendingRequests. |
src/vs/workbench/contrib/chat/common/chatService/chatService.ts |
Defines ChatSendResult union and helpers, adds ChatRequestQueueKind, extends IChatSendRequestOptions with queue, and extends IChatService with queue/steering management methods. |
src/vs/workbench/contrib/chat/common/actions/chatContextKeys.ts |
Introduces context keys chatHasPendingRequests and chatPendingRequestCount (not yet wired) for future queue-aware UI state. |
src/vs/workbench/contrib/chat/browser/widget/media/chat.css |
Adds styles for pending requests and pending divider rows (opacity tweaks and label styling). |
src/vs/workbench/contrib/chat/browser/widget/chatWidget.ts |
Changes input acceptance to use ChatSendResult, automatically queues when a request is in progress, updates accessibility handling, and removes the previous “cancel current request before sending new one” behavior. |
src/vs/workbench/contrib/chat/browser/widget/chatListWidget.ts |
Updates diff identity provider and layout calculations to handle pending divider items and pending requests without breaking height/identity logic. |
src/vs/workbench/contrib/chat/browser/widget/chatListRenderer.ts |
Teaches the list renderer about IChatPendingDividerViewModel, adds rendering for divider rows, avoids rendering avatars for them, and marks queued requests with a CSS class. |
src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatContentParts.ts |
Narrows content-part render context elements to request/response view models and updates types accordingly. |
src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatConfirmationContentPart.ts |
Uses ChatSendResult for confirmation follow-up sends, only marking confirmations as used when the send actually succeeds. |
src/vs/workbench/contrib/chat/browser/chat.ts |
Extends ChatTreeItem to include pending divider VMs, updates accept-input options to support queueing, and imports queue-related types. |
src/vs/workbench/contrib/chat/browser/chat.contribution.ts |
Registers the new chat.requestQueuing.enabled configuration and wires in registerChatQueueActions(). |
src/vs/workbench/contrib/chat/browser/actions/chatQueueActions.ts |
Adds “Add to Queue”, “Steer with Message”, and “Remove from Queue” actions, plus a ChatExecuteQueue submenu gated by the new setting and context keys. |
src/vs/workbench/contrib/chat/browser/actions/chatCopyActions.ts |
Ensures copy actions treat only request/response items as copyable, ignoring pending-divider rows. |
src/vs/workbench/contrib/chat/browser/actions/chatContinueInAction.ts |
Updates continuation logic to work with ChatSendResult, only handling delegation exit on successful sends. |
src/vs/workbench/api/common/extHostChatSessions.ts |
Updates session request handler invocations to pass a ChatContext that includes yieldRequested (currently always false). |
src/vs/workbench/api/common/extHostChatAgents2.ts |
Plumbs yieldRequested into various extension host chat-agent contexts and into vscode.ChatContext for invoke/provideTitle/provideSummary/provideFollowups. |
src/vs/platform/actions/common/actions.ts |
Adds MenuId.ChatExecuteQueue for the new execute-toolbar queue submenu. |
Comments suppressed due to low confidence (1)
src/vs/workbench/contrib/chat/browser/widget/chatWidget.ts:2061
- Queueing behavior in
_acceptInputis now always enabled wheneverrequestInProgressis true, regardless of thechat.requestQueuing.enabledconfiguration. This changes the default UX from "cancel then send" to "queue" even when the experimental setting is disabled, which contradicts the setting description and may surprise users. Please gate the automaticoptions.queueassignment onChatConfiguration.RequestQueueingEnabled(or equivalent), so that queuing semantics only apply when the feature is explicitly enabled.
private async _acceptInput(query: { query: string } | undefined, options: IChatAcceptInputOptions = {}): Promise<IChatResponseModel | undefined> {
if (this.viewModel?.model.requestInProgress.get()) {
options.queue ??= ChatRequestQueueKind.Queued;
}
| /** | ||
| * Set to true by the editor to request the language model gracefully stop after its next opportunity. | ||
| */ | ||
| yieldRequested?: boolean; |
There was a problem hiding this comment.
The new yieldRequested steering flag is not currently wired through from the active CancellableRequest into the agent request: _sendRequestAsync never sets IChatAgentRequest.yieldRequested, so ExtHostChatAgents2 and extension ChatContext.yieldRequested will always see false. Since ChatService.setYieldRequested only flips the private _yieldRequested field on CancellableRequest, this value needs to be consulted when building IChatAgentRequest (e.g. in prepareChatAgentRequest) and propagated into the request DTO for steering messages to actually influence providers.
| return detector.provider.provideParticipantDetection( | ||
| extRequest, | ||
| { history }, | ||
| { history, yieldRequested: false }, |
There was a problem hiding this comment.
Can yieldRequested just be optional for all these callsites?
Still a solid amount of UX polish to do, but the base data flows are here so I'd like to get this merged in to avoid conflicts.
Disabled by default behind the setting
"chat.requestQueuing.enabled": true.Refs #260330