Skip to content

Commit 2b872b7

Browse files
committed
fix: defer Workspace Build output channel creation until first write
Constructing TerminalOutputChannel previously called createOutputChannel and show(true) immediately, which forced the Output panel open even on reconnects to an already-running workspace where no build logs would ever be written. The empty channel was disposed shortly after, but the Output panel itself stayed visible. Defer both calls to the first write, so reconnects to a running workspace never create the channel and never pop the panel.
1 parent d8f53c6 commit 2b872b7

3 files changed

Lines changed: 28 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
from published versions since it shows up in the VS Code extension changelog
66
tab and is confusing to users. Add it back between releases if needed. -->
77

8+
## Unreleased
9+
10+
### Fixed
11+
12+
- The **Coder: Workspace Build** output channel is no longer created when reconnecting to an
13+
already-running workspace, so the Output panel doesn't pop open empty.
14+
815
## [v1.14.4-pre](https://github.com/coder/vscode-coder/releases/tag/v1.14.4-pre) 2026-04-20
916

1017
### Added
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
import stripAnsi from "strip-ansi";
22
import * as vscode from "vscode";
33

4-
/** Adapts terminal-style output for a VS Code OutputChannel. Strips ANSI escape sequences and carriage returns. */
4+
/**
5+
* Adapts terminal-style output for a VS Code OutputChannel.
6+
* Strips ANSI escape sequences and carriage returns;
7+
* creates the underlying channel lazily on first write.
8+
*/
59
export class TerminalOutputChannel implements vscode.Disposable {
6-
private readonly channel: vscode.OutputChannel;
10+
private channel: vscode.OutputChannel | undefined;
711

8-
constructor(name: string) {
9-
this.channel = vscode.window.createOutputChannel(name);
10-
this.channel.show(true);
11-
}
12+
constructor(private readonly name: string) {}
1213

1314
write(data: string): void {
15+
if (!this.channel) {
16+
this.channel = vscode.window.createOutputChannel(this.name);
17+
this.channel.show(true);
18+
}
1419
this.channel.append(stripAnsi(data).replace(/\r/g, ""));
1520
}
1621

1722
dispose(): void {
18-
this.channel.dispose();
23+
this.channel?.dispose();
1924
}
2025
}

test/unit/remote/terminalOutputChannel.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,13 @@ describe("TerminalOutputChannel", () => {
2727
])("%s", (_label, input, expected) => {
2828
expect(setup(input).content.join("")).toBe(expected);
2929
});
30+
31+
it("does not create the channel until first write", () => {
32+
vi.mocked(vscode.window.createOutputChannel).mockClear();
33+
const channel = new TerminalOutputChannel("test");
34+
expect(vscode.window.createOutputChannel).not.toHaveBeenCalled();
35+
36+
channel.write("hello");
37+
expect(vscode.window.createOutputChannel).toHaveBeenCalledOnce();
38+
});
3039
});

0 commit comments

Comments
 (0)