fix(vscode): send an editor comment to the sidebar chat instead of opening a tab

A comment went to the active session tab, and when there was none it opened
a new one, even while the user was chatting in the sidebar. That is not how
the other capture flows behave. The comment now takes the same route as
Add to Context: the active session tab when one exists, otherwise the
sidebar, revealed if it is closed.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
This commit is contained in:
Bohdan Triapitsyn
2026-09-05 14:25:00 +03:00
parent 60a4dccb32
commit 671dce7213
3 changed files with 6 additions and 40 deletions
+1 -1
View File
@@ -84,7 +84,7 @@ The webview build emits each worker as one self-contained file. VS Code webviews
- `InlineCommentThreads.ts`
- Owns the `openchamber.inlineComments` comment controller: the gutter `+` range, the thread opened by `openchamber.addLineComment`, and every thread a submitted comment leaves anchored in the editor until the message goes out.
- A thread never owns a draft. It mints the draft id, hands the payload to a chat webview (the active or newly opened session panel, else the sidebar), and follows the webview's whole-draft-list `inlineComments:sync` snapshots: present means show, absent after having been seen means dispose. A snapshot is tagged with the surface that produced it (a panel id or `sidebar`) and only decides that surface's own threads, because every webview runs its own draft store.
- A thread never owns a draft. It mints the draft id, hands the payload to a chat webview with the same routing as Add to Context (the active session panel when one exists, else the sidebar, revealed if needed), and follows the webview's whole-draft-list `inlineComments:sync` snapshots: present means show, absent after having been seen means dispose. A snapshot is tagged with the surface that produced it (a panel id or `sidebar`) and only decides that surface's own threads, because every webview runs its own draft store.
- A comment the composer never confirms holding within 30 s is retracted from every surface's pending hold, its thread disposed, and the user told, so a thread cannot promise a send that will never happen.
- `inlineCommentSelection.ts` holds the pure pieces (line ranges, the diff-side and real-path resolution for `git:` documents, the pending hold, removal broadcast, thread fate) without the `vscode` import so they are unit-tested directly.
- Webview side: `webview/inlineCommentTarget.ts` decides where a delivered comment is filed. A session panel stamps its session on every comment it delivers and the webview waits until it shows that session; the sidebar files on its current session or open draft. Filing on the first snapshot with a directory put the draft under `draft` while a fresh panel was still loading its session list, a key that composer never reads. `webview/inlineCommentRemovals.ts` remembers removals that arrive before a delayed delivery lands, so a comment dropped while its panel was still booting does not appear as a chip later. The extension is not activated on startup for this; the right-click command activates it, and the gutter `+` appears from then on.
@@ -375,39 +375,6 @@ export class SessionEditorPanelProvider {
return entry.id;
}
/**
* Delivers a comment to a session tab, opening one when none exists.
*
* A comment is written against code the user is reading, so it must not
* depend on their having opened a chat first. With no tab open this behaves
* like the toolbar's new-session button, then delivers into that tab once its
* webview is listening.
*/
public openWithLineComment(payload: LineCommentPayload, activeSessionId: string | null): string | null {
if (!payload.relativePath.trim()) {
return null;
}
const accepted = this.addLineCommentToActivePanel(payload);
if (accepted) {
return accepted;
}
if (activeSessionId) {
this.createOrShow(activeSessionId);
} else {
this.createOrShowNewSession();
}
const entry = this._getActivePanelEntry();
if (!entry) {
return null;
}
entry.pendingLineComments.push(payload);
return entry.id;
}
/**
* Drops a draft the user removed from its editor thread.
*
+5 -6
View File
@@ -489,15 +489,14 @@ export async function activate(context: vscode.ExtensionContext) {
// the authoritative list, so the threads follow what the webview reports.
const inlineCommentThreads = new InlineCommentThreads({
submitDraft: async (payload) => {
// A comment is written against code the user is reading, so it cannot
// require them to have opened a chat first: with no session tab open,
// one is opened, exactly as the toolbar's new-session button does.
const panelId = sessionEditorProvider?.openWithLineComment(payload, activeSessionId);
// Same routing as Add to Context: a session tab the user is working in
// takes the comment; otherwise it goes to the sidebar, revealing it when
// needed. Opening a fresh tab for a comment left the user's sidebar chat
// ignored and a new tab in the way.
const panelId = sessionEditorProvider?.addLineCommentToActivePanel(payload);
if (panelId) {
return panelId;
}
// No session editor at all (provider gone): fall back to the sidebar
// rather than accepting a comment that has nowhere to land.
if (!(await revealChatViewForPayload())) {
return null;
}