microsoft / microsoft/vscode

feat: Standardized Chat Panel Extension API (transcript access, scroll state, overlay decorations)

Open
#327,561 2 comments 4 reactions 1 assignee Claimed by @roblourens View on GitHub
feature-request
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

# Feature Request: Standardized Chat Panel Extension API (transcript access, scroll state, overlay decorations)

## Summary

Propose a cross-editor-standardized extension API that lets third-party extensions observe and decorate AI chat panels — the same way the existing `TextEditor` decoration API lets extensions decorate file editors (overview ruler, gutter icons, minimap markers).

This is the API prerequisite that would have let a plugin deliver the companion feature request **(companion UI feature request — to be filed separately and linked back here)** without waiting for first-party implementation. We're asking VS Code to lead the standardization so that Cursor, Windsurf, and other VS Code-family editors can adopt the same surface, giving plugin developers one target instead of N.

## Motivation

AI chat panels are now a core editing surface, but they are completely opaque to extensions:

- **No transcript access.** An extension cannot read the turns of the host's built-in chat (Copilot Chat, Cascade, Cursor Chat, etc.). Anything that wants to analyze, summarize, export, or visualize the conversation has to scrape the DOM or be its own chat — neither of which is a real solution.
- **No scroll state.** There is no `chat.scrollTop`, `scrollHeight`, or `visibleRanges` equivalent. Even for notebooks this is missing (microsoft/vscode#311289); for chat it was never proposed. Any "minimap for chat", "jump to turn N", "synced side panel", or "reading-position marker" feature is impossible without it.
- **No overlay decorations.** The `createTextEditorDecorationType` API — including `overviewRulerColor`, `overviewRulerLane`, `gutterIconPath`, `before`/`after` — only applies to `TextEditor`. There is no equivalent for chat panels, so the overview-ruler/heatmap/error-marker UX from the companion request cannot be built by a third party.

This gap forces every "nice chat UX" feature to be either first-party-only or reimplemented per-editor. A standardized API would let one plugin target VS Code, Cursor, Windsurf, VSCodium, etc. simultaneously — exactly the ecosystem benefit the existing extension API already provides for file editors.

## Proposed API surface

Illustrative, not prescriptive — the goal is to start the conversation, not to dictate the final shape.

### 1. Chat panel handle

```ts
namespace vscode.chat {
// Handle to an open chat panel (sidebar or editor-embedded).
export interface ChatPanel {
readonly id: string;
readonly viewType: string; // e.g. "github.copilot-chat", "codeium.cascade", "cursor.chat"
readonly visible: boolean;
readonly onDidDispose: Event;
readonly onDidScroll: Event;
readonly onDidAddTurn: Event;
readonly transcript: readonly ChatTurn[];
readonly scroll: ChatScrollState;
revealTurn(turnId: string): Thenable;
setDecorations(decorationType: ChatDecorationType, ranges: ChatDecorationRange[]): void;
}

export interface ChatScrollState {
readonly scrollTop: number; // px from top
readonly scrollHeight: number; // total px
readonly viewportHeight: number;
}

export interface ChatScrollEvent {
readonly scroll: ChatScrollState;
}

export interface ChatTurn {
readonly id: string;
readonly role: 'user' | 'assistant' | 'system' | 'tool';
readonly timestamp: number;
readonly content: ChatContentPart[]; // markdown, tool calls, tool results, errors
readonly status?: 'ok' | 'error' | 'aborted' | 'timeout' | 'rate-limited';
readonly tokenEstimate?: number; // cumulative context size up to and including this turn
}

export interface ChatContentPart {
readonly kind: 'text' | 'tool-call' | 'tool-result' | 'image' | 'error';
readonly text?: string;
readonly errorKind?: 'timeout' | 'tool-failure' | 'rate-limit' | 'parse-failure' | 'aborted';
readonly failedSpan?: { start: number; end: number }; // offset into text, for strikethrough
}

export interface ChatDecorationRange {
readonly turnId: string; // anchor to a turn
readonly lane?: ChatOverviewRulerLane; // Left | Right | Full
readonly color?: string | ThemeColor;
readonly tooltip?: string;
}

export interface ChatDecorationType { /* opaque handle, like TextEditorDecorationType */ }

export function createChatDecorationType(options: ChatDecorationRenderOptions): ChatDecorationType;

// Discovery
export const onDidChangeActiveChatPanel: Event;
export const activeChatPanel: ChatPanel | undefined;
export const visibleChatPanels: readonly ChatPanel[];
}
```

### 2. Decoration options (mirror the existing TextEditor ones)

```ts
export interface ChatDecorationRenderOptions {
overviewRulerColor?: string | ThemeColor;
overviewRulerLane?: ChatOverviewRulerLane;
gutterIconPath?: Uri | ThemeIcon;
gutterIconSize?: 'contain' | 'cover' | 'auto';
strikethrough?: boolean;
color?: string | ThemeColor;
backgroundColor?: string | ThemeColor;
isWholeTurn?: boolean;
light?: ChatDecorationRenderOptions;
dark?: ChatDecorationRenderOptions;
}

export enum ChatOverviewRulerLane { Left = 1, Right = 2, Full = 3 }
```

### 3. Permissions / consent

Reading another chat's transcript is sensitive. Suggested model:

- A `chatPanel` extension contribution point in `package.json` declaring which `viewType`s the extension wants to observe.
- User gets a consent prompt the first time an extension requests transcript access for a given chat provider, similar to how proposed APIs and restricted APIs are gated.
- Providers (Copilot, Cascade, Cursor) opt in by registering their chat as an observable `ChatPanel` with a declared `viewType`. This is the standardization hook: every vendor implements the same `ChatPanel` interface.

## Why standardize across VS Code / Cursor / Windsurf

- **Plugin developers win.** One API, one `.vsix`, works everywhere. Today any chat-UX plugin has to be rewritten per editor or be first-party.
- **Vendors win.** Cursor and Windsurf both inherit the VS Code extension host; adopting this API is a small delta on top of their existing chat implementation and immediately unlocks a plugin ecosystem around their chat surfaces.
- **Users win.** Features like the companion overview-ruler/heatmap request, transcript export, conversation search, "jump to where I asked X", and accessibility tooling all become possible without waiting for each vendor to build them.

We're filing this against VS Code as the natural home for the standard, and we'll cross-file with Cursor and Windsurf asking them to adopt the same interface once it's defined here.

## Acceptance criteria

- [ ] A `vscode.chat.ChatPanel` handle is obtainable for any registered, observable chat panel.
- [ ] `transcript`, `scroll`, `onDidAddTurn`, `onDidScroll` are exposed and reliable.
- [ ] `createChatDecorationType` + `ChatPanel.setDecorations` render markers on the chat panel's overview ruler, mirroring the `TextEditor` decoration API.
- [ ] `revealTurn(turnId)` scrolls the chat to the given turn.
- [ ] Consent gating works: extensions must declare intent and be approved per chat provider.
- [ ] At least one built-in chat (Copilot Chat) registers itself as an observable `ChatPanel` as a reference implementation.
- [ ] Cursor and Windsurf publicly commit to implementing the same interface (linked issues below).

## Related

- Companion UI feature request (what this API unlocks, and the user-facing motivation): **(companion UI feature request — to be filed separately and linked back here)**
- Same-family upstream gap for notebooks (no pixel scroll state): microsoft/vscode#311289.
- Existing prior art to mirror: `createTextEditorDecorationType`, `overviewRulerLane`, `editorGutter`, `editor.minimap`.
- Proposed chat output renderer (related but narrower — renders inside a single response, not on the panel chrome): microsoft/vscode#257761.

- Adjacent chat API requests (not duplicates):
- microsoft/vscode#319722 — API to programmatically delete chat sessions (lifecycle action, not panel observation).
- microsoft/vscode#325507 — API to observe agent/subagent chat session lifecycle and status (conversation state, not UI panel scroll/decorations).
- microsoft/vscode#321409 — API to expose sidebar/panel/auxiliaryBar visibility state (general workbench layout, not chat-panel transcript/decorations).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.