Skip to content

feat(vscode): add sidebar chat view#2195

Closed
buaoyezz wants to merge 3 commits intoQwenLM:mainfrom
buaoyezz:feat/vscode-sidebar-integration
Closed

feat(vscode): add sidebar chat view#2195
buaoyezz wants to merge 3 commits intoQwenLM:mainfrom
buaoyezz:feat/vscode-sidebar-integration

Conversation

@buaoyezz
Copy link
Contributor

@buaoyezz buaoyezz commented Mar 8, 2026

TLDR

Adds a focused VS Code sidebar integration for Qwen Code.

What changed

  • registers a dedicated Qwen Code sidebar container and qwen-code-chat webview view
  • adds a sidebar webview provider that reuses the existing chat surface
  • wires sidebar permission handling into existing diff accept/cancel flows
  • adds extension coverage for sidebar registration

Validation

pm --prefix packages/vscode-ide-companion test

pm exec eslint src/extension.ts src/extension.test.ts src/webview/WebViewContent.ts src/webview/SidebarWebviewProvider.ts

This supersedes #1954 with a smaller, latest-main-based change set focused only on sidebar integration.

@yiliang114
Copy link
Collaborator

@buaoyezz Bro, you can look at my branch changes a few days ago, #2188 there are several main problems are:

  1. SidebarWebviewProvider content and WebViewProvider repeat more, need more abstraction?
  2. When the extension is activated, the QwenAgentManager ConversationStore is directly created, which can be handled lazily.
    3....
    However, I think there are still some points in your logic that I can learn from when comparing the two branches: extractSessionListItems backward compatibility, onDidChangeVisibility recertification, initializationPromise de-duplication, etc.
    I'm going to commit from the cherry pick section of your branch. the commit will bring your commit record as a collaborator, similar to 2220936 and 9b05ae1, and your commit record will still enter the main branch.

@buaoyezz
Copy link
Contributor Author

buaoyezz commented Mar 9, 2026

@buaoyezz Bro, you can look at my branch changes a few days ago, #2188 there are several main problems are:

  1. SidebarWebviewProvider content and WebViewProvider repeat more, need more abstraction?
  2. When the extension is activated, the QwenAgentManager ConversationStore is directly created, which can be handled lazily.
    3....
    However, I think there are still some points in your logic that I can learn from when comparing the two branches: extractSessionListItems backward compatibility, onDidChangeVisibility recertification, initializationPromise de-duplication, etc.
    I'm going to commit from the cherry pick section of your branch. the commit will bring your commit record as a collaborator, similar to 2220936 and 9b05ae1, and your commit record will still enter the main branch.

Sorry, I just saw your PR. Got it, thanks!

yiliang114 added a commit that referenced this pull request Mar 9, 2026
…s from PR #2195

- Add extractSessionListItems() utility for robust ACP response parsing
- Refactor getSessionList() and getSessionListPaged() to use the new utility
- Add openNewChatTabCommand to create new session when opening chat tab
- Add comprehensive test coverage for session list extraction

Co-authored-by: ZZAoYe <zzbuaoye@gmail.com>
@wenshao
Copy link
Collaborator

wenshao commented Mar 10, 2026

Issues & Suggestions

  1. Massive code duplication (Critical)

SidebarWebviewProvider.ts (766 lines) is largely a copy-paste of WebViewProvider.ts (1450 lines). The constructor, agent event wiring, permission handling, auth flow, forceReLogin(), respondToPendingPermission(), handleWebviewReady(), active editor listeners, and more are
near-identical. This was already called out in the existing PR comments.

Recommendation: Extract shared logic into a base class or composition helper. The sidebar and panel providers differ only in how they host the webview (WebviewView vs WebviewPanel) — the agent lifecycle, permission handling, and message routing are identical and should be
shared.

  1. updateAuthStateFromMessage is defined but only called internally — never from received messages

updateAuthStateFromMessage() is called in sendMessageToWebView(), which means the sidebar tracks its own auth state based on outgoing messages. This works but is fragile — if a new message type is added that affects auth state and someone forgets to update this switch
statement, state will drift.

  1. createNewSession is public but not declared in any interface

The openNewChatTab command now calls provider.createNewSession(), but the PR doesn't show where createNewSession is defined on SidebarWebviewProvider. Looking at the code, there's no createNewSession method on the sidebar provider — only in QwenAgentManager. If
createWebViewProvider() can return a SidebarWebviewProvider, this will be a runtime error.

Recommendation: Either add createNewSession() to SidebarWebviewProvider or ensure the createWebViewProvider callback in registerNewCommands always returns a WebViewProvider.

  1. Missing AskUserQuestion support in sidebar

WebViewProvider handles AskUserQuestionRequest with pendingAskUserQuestionRequest/pendingAskUserQuestionResolve. The sidebar provider does not register an onAskUserQuestion handler at all. This means interactive prompts from the agent will hang or fail when initiated from
the sidebar.

  1. Permission handler leak in onPermissionRequest

In the permission request callback (~line 629), this.messageHandler.setPermissionHandler(handler) is called inside a new Promise constructor. But handler is a closure that calls this.pendingPermissionResolve?.() — which is the same resolve that was just set. If a second
permission request arrives before the first resolves, the old resolve is silently overwritten and the first promise never settles.

WebViewProvider has the same issue, but duplicating it isn't great.

  1. Double execution of diff commands on cancel

In the permission handler (~lines 637-646), when isCancel is true, qwen.diff.closeAll is executed. But then the void (async () => { ... })() block also runs. Meanwhile, in the pendingPermissionResolve callback (~line 621), the !isCancel branch also runs closeAll and
suppressBriefly. The isCancel path executes closeAll twice — once in the handler and once in the resolve callback's finally block (which runs regardless).

  1. No test for SidebarWebviewProvider itself

The PR adds tests for registerNewCommands, extractSessionListItems, and sidebar registration in extension.test.ts, but there are no unit tests for SidebarWebviewProvider — the largest new file (766 lines). Permission handling, auth state tracking, and webview lifecycle are
all untested.

  1. Eager instantiation concern

SidebarWebviewProvider creates a QwenAgentManager and ConversationStore in its constructor (called at activation time), even if the user never opens the sidebar. This was noted in prior review comments. Consider lazy initialization.

@buaoyezz
Copy link
Contributor Author

Issues & Suggestions

  1. Massive code duplication (Critical)

SidebarWebviewProvider.ts (766 lines) is largely a copy-paste of WebViewProvider.ts (1450 lines). The constructor, agent event wiring, permission handling, auth flow, forceReLogin(), respondToPendingPermission(), handleWebviewReady(), active editor listeners, and more are near-identical. This was already called out in the existing PR comments.

Recommendation: Extract shared logic into a base class or composition helper. The sidebar and panel providers differ only in how they host the webview (WebviewView vs WebviewPanel) — the agent lifecycle, permission handling, and message routing are identical and should be shared.

  1. updateAuthStateFromMessage is defined but only called internally — never from received messages

updateAuthStateFromMessage() is called in sendMessageToWebView(), which means the sidebar tracks its own auth state based on outgoing messages. This works but is fragile — if a new message type is added that affects auth state and someone forgets to update this switch statement, state will drift.

  1. createNewSession is public but not declared in any interface

The openNewChatTab command now calls provider.createNewSession(), but the PR doesn't show where createNewSession is defined on SidebarWebviewProvider. Looking at the code, there's no createNewSession method on the sidebar provider — only in QwenAgentManager. If createWebViewProvider() can return a SidebarWebviewProvider, this will be a runtime error.

Recommendation: Either add createNewSession() to SidebarWebviewProvider or ensure the createWebViewProvider callback in registerNewCommands always returns a WebViewProvider.

  1. Missing AskUserQuestion support in sidebar

WebViewProvider handles AskUserQuestionRequest with pendingAskUserQuestionRequest/pendingAskUserQuestionResolve. The sidebar provider does not register an onAskUserQuestion handler at all. This means interactive prompts from the agent will hang or fail when initiated from the sidebar.

  1. Permission handler leak in onPermissionRequest

In the permission request callback (~line 629), this.messageHandler.setPermissionHandler(handler) is called inside a new Promise constructor. But handler is a closure that calls this.pendingPermissionResolve?.() — which is the same resolve that was just set. If a second permission request arrives before the first resolves, the old resolve is silently overwritten and the first promise never settles.

WebViewProvider has the same issue, but duplicating it isn't great.

  1. Double execution of diff commands on cancel

In the permission handler (~lines 637-646), when isCancel is true, qwen.diff.closeAll is executed. But then the void (async () => { ... })() block also runs. Meanwhile, in the pendingPermissionResolve callback (~line 621), the !isCancel branch also runs closeAll and suppressBriefly. The isCancel path executes closeAll twice — once in the handler and once in the resolve callback's finally block (which runs regardless).

  1. No test for SidebarWebviewProvider itself

The PR adds tests for registerNewCommands, extractSessionListItems, and sidebar registration in extension.test.ts, but there are no unit tests for SidebarWebviewProvider — the largest new file (766 lines). Permission handling, auth state tracking, and webview lifecycle are all untested.

  1. Eager instantiation concern

SidebarWebviewProvider creates a QwenAgentManager and ConversationStore in its constructor (called at activation time), even if the user never opens the sidebar. This was noted in prior review comments. Consider lazy initialization.

Thanks for the detailed feedback. I understand this PR won’t be merged as-is, and I appreciate that some parts were cherry-picked into #2188. Since that PR has already landed and this branch now conflicts with main, I’ll close this PR.

@buaoyezz buaoyezz closed this Mar 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants