From 786edce372f36b0ae224d33a7c9645738767c18a Mon Sep 17 00:00:00 2001 From: Gennadi Ryan Date: Sun, 9 Aug 2026 01:25:45 +0000 Subject: [PATCH 1/6] Fix zoom keybindings first --- packages/extension/src/chat_bridge.ts | 16 ++++++++++++ packages/extension/test/chat_bridge.test.ts | 27 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/packages/extension/src/chat_bridge.ts b/packages/extension/src/chat_bridge.ts index 186bbd4..f235ccb 100644 --- a/packages/extension/src/chat_bridge.ts +++ b/packages/extension/src/chat_bridge.ts @@ -172,6 +172,22 @@ export function handleAmicodeBridgeMessage(msg: unknown, io: BridgeIo): boolean return true; } + // Zoom bridge (amicode#266): the workbench owns zoom inside the webview — + // the host intercepts the Cmd/Ctrl+Plus/Minus/0 chords before the webview + // document sees them, so the app cannot zoom itself. It posts the intent + // here and we run the matching workbench action. Three actions only, + // exact-match; anything else is a consumed no-op (our envelope, never + // foreign noise — same posture as the bug-lifecycle kinds). + if (msg.kind === "zoom") { + const action = (msg as { action?: unknown }).action; + const command = + action === "in" ? "workbench.action.zoomIn" : + action === "out" ? "workbench.action.zoomOut" : + action === "reset" ? "workbench.action.zoomReset" : undefined; + if (command) void vscode.commands.executeCommand(command); + return true; + } + // The "Amico" palette group — allowlisted commands only. if (msg.kind === "command") { const command = (msg as unknown as { command?: unknown }).command; diff --git a/packages/extension/test/chat_bridge.test.ts b/packages/extension/test/chat_bridge.test.ts index 271dba0..54ed47f 100644 --- a/packages/extension/test/chat_bridge.test.ts +++ b/packages/extension/test/chat_bridge.test.ts @@ -120,6 +120,33 @@ describe("amicode bridge — clipboard", () => { }); }); +describe("amicode bridge — zoom (amicode#266)", () => { + it("routes the three zoom intents to their workbench actions", async () => { + const host = io(); + const ran = () => (vscode.commands as unknown as { executed: string[] }).executed; + const before = ran().length; + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "in" }, host)).toBe(true); + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "out" }, host)).toBe(true); + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "reset" }, host)).toBe(true); + await flush(); + expect(ran().slice(before)).toEqual([ + "workbench.action.zoomIn", + "workbench.action.zoomOut", + "workbench.action.zoomReset", + ]); + }); + + it("unknown zoom actions are consumed without executing anything", async () => { + const host = io(); + const ran = (vscode.commands as unknown as { executed: string[] }).executed; + const before = ran.length; + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "to-the-moon" }, host)).toBe(true); + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom" }, host)).toBe(true); + await flush(); + expect(ran).toHaveLength(before); + }); +}); + describe("amicode bridge — commands & settings", () => { it("runs allowlisted commands only", async () => { const host = io(); From 1d99954e6f9067d9cfb04641b47e271107bae20a Mon Sep 17 00:00:00 2001 From: Gennadi Ryan Date: Sun, 9 Aug 2026 02:02:08 +0000 Subject: [PATCH 2/6] Finishing zoom keybind wiring --- packages/extension/src/chat_bridge.ts | 7 ++++++- packages/extension/src/chat_panel.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/extension/src/chat_bridge.ts b/packages/extension/src/chat_bridge.ts index f235ccb..b0acc81 100644 --- a/packages/extension/src/chat_bridge.ts +++ b/packages/extension/src/chat_bridge.ts @@ -184,7 +184,12 @@ export function handleAmicodeBridgeMessage(msg: unknown, io: BridgeIo): boolean action === "in" ? "workbench.action.zoomIn" : action === "out" ? "workbench.action.zoomOut" : action === "reset" ? "workbench.action.zoomReset" : undefined; - if (command) void vscode.commands.executeCommand(command); + if (command) { + // TEMP-DIAG (amicode#266 remote test): the envelope survived the relay. + // Remove after the diagnosis. + console.log("[amicode/zoom] execute:", command); + void vscode.commands.executeCommand(command); + } return true; } diff --git a/packages/extension/src/chat_panel.ts b/packages/extension/src/chat_panel.ts index cccf473..9e34149 100644 --- a/packages/extension/src/chat_panel.ts +++ b/packages/extension/src/chat_panel.ts @@ -260,7 +260,7 @@ export class ChatPanel { replyClipboardImage(d.nonce); return; } - if (d && d.source === "amicode" && (d.kind === "command" || d.kind === "clipboard-request" || d.kind === "clipboard-write" || d.kind === "open-external" || d.kind === "open-file" || d.kind === "save-file" || d.kind === "set-default-model" || d.kind === "bug-filed" || d.kind === "bug-report-closed" || d.kind === "bug-report-poke")) { + if (d && d.source === "amicode" && (d.kind === "command" || d.kind === "clipboard-request" || d.kind === "clipboard-write" || d.kind === "open-external" || d.kind === "open-file" || d.kind === "save-file" || d.kind === "set-default-model" || d.kind === "bug-filed" || d.kind === "bug-report-closed" || d.kind === "bug-report-poke" || d.kind === "zoom")) { vscode.postMessage(d); } return; From 77f245f8a5dde5bf84796d81941043d79776a2d8 Mon Sep 17 00:00:00 2001 From: Gennadi Ryan Date: Sun, 9 Aug 2026 02:42:44 +0000 Subject: [PATCH 3/6] Logging fixes --- packages/extension/src/chat_bridge.ts | 20 +++++++++++++++++++ packages/extension/src/chat_panel.ts | 2 +- packages/extension/test/__mocks__/vscode.ts | 9 ++++++++- packages/extension/test/chat_bridge.test.ts | 22 +++++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/packages/extension/src/chat_bridge.ts b/packages/extension/src/chat_bridge.ts index b0acc81..119bd1e 100644 --- a/packages/extension/src/chat_bridge.ts +++ b/packages/extension/src/chat_bridge.ts @@ -32,6 +32,12 @@ export const BRIDGE_ALLOWED_COMMANDS: ReadonlySet = new Set([ "workbench.action.showCommands", ]); +// TEMP-DIAG (amicode#266 remote test): the app relays its [zoom]-prefixed +// console lines here so a remote session can hand back a log file ("Open Log +// File" on the "Amicode — webview diag" channel) instead of webview devtools. +// Remove together with the lane below. +let diagChannel: vscode.OutputChannel | undefined; + /** The bug-session lifecycle sink (amicode#250) — the panels wire the * BugReportManager's. Structural, so the bridge never imports the manager. */ export interface BugReportSink { @@ -193,6 +199,20 @@ export function handleAmicodeBridgeMessage(msg: unknown, io: BridgeIo): boolean return true; } + // TEMP-DIAG (amicode#266 remote test): the app's relayed console lines land + // here — write them to the "Amicode — webview diag" output channel, whose + // backing file a remote session can hand back ("Open Log File"). Bounded + // payload; consumed either way. Remove after the diagnosis. + if (msg.kind === "diag-log") { + const level = (msg as { level?: unknown }).level; + const message = (msg as { message?: unknown }).message; + if (typeof message === "string" && message.length <= 4096) { + diagChannel ??= vscode.window.createOutputChannel("Amicode — webview diag"); + diagChannel.appendLine(`[${typeof level === "string" ? level : "log"}] ${message}`); + } + return true; + } + // The "Amico" palette group — allowlisted commands only. if (msg.kind === "command") { const command = (msg as unknown as { command?: unknown }).command; diff --git a/packages/extension/src/chat_panel.ts b/packages/extension/src/chat_panel.ts index 9e34149..0320f2c 100644 --- a/packages/extension/src/chat_panel.ts +++ b/packages/extension/src/chat_panel.ts @@ -260,7 +260,7 @@ export class ChatPanel { replyClipboardImage(d.nonce); return; } - if (d && d.source === "amicode" && (d.kind === "command" || d.kind === "clipboard-request" || d.kind === "clipboard-write" || d.kind === "open-external" || d.kind === "open-file" || d.kind === "save-file" || d.kind === "set-default-model" || d.kind === "bug-filed" || d.kind === "bug-report-closed" || d.kind === "bug-report-poke" || d.kind === "zoom")) { + if (d && d.source === "amicode" && (d.kind === "command" || d.kind === "clipboard-request" || d.kind === "clipboard-write" || d.kind === "open-external" || d.kind === "open-file" || d.kind === "save-file" || d.kind === "set-default-model" || d.kind === "bug-filed" || d.kind === "bug-report-closed" || d.kind === "bug-report-poke" || d.kind === "zoom" || d.kind === "diag-log")) { vscode.postMessage(d); } return; diff --git a/packages/extension/test/__mocks__/vscode.ts b/packages/extension/test/__mocks__/vscode.ts index 23e2233..69c490e 100644 --- a/packages/extension/test/__mocks__/vscode.ts +++ b/packages/extension/test/__mocks__/vscode.ts @@ -2,12 +2,19 @@ // only the runtime members our node-side modules touch; types are erased at // compile time so they need no runtime shape. export const window = { + outputLines: [] as string[], showInformationMessage: () => Promise.resolve(undefined), showErrorMessage: () => Promise.resolve(undefined), showWarningMessage: () => Promise.resolve(undefined), showInputBox: () => Promise.resolve(undefined), showSaveDialog: () => Promise.resolve(undefined), - createOutputChannel: () => ({ appendLine() {}, append() {}, dispose() {} }), + createOutputChannel: () => ({ + appendLine(line: string) { + window.outputLines.push(line); + }, + append() {}, + dispose() {}, + }), registerWebviewViewProvider: () => ({ dispose() {} }), activeColorTheme: { kind: 2 }, // ColorThemeKind.Dark onDidChangeActiveColorTheme: (_cb: unknown, _thisArg?: unknown, _subs?: unknown) => ({ dispose() {} }), diff --git a/packages/extension/test/chat_bridge.test.ts b/packages/extension/test/chat_bridge.test.ts index 54ed47f..865eb99 100644 --- a/packages/extension/test/chat_bridge.test.ts +++ b/packages/extension/test/chat_bridge.test.ts @@ -13,6 +13,7 @@ import { handleAmicodeBridgeMessage, extractReportBugModel, type BridgeIo } from const env = vscode.env as unknown as { opened: unknown[]; clipboard: { text: string } }; const ws = vscode.workspace as unknown as { configUpdates: Array<[string, unknown]> }; +const win = vscode.window as unknown as { outputLines: string[] }; function io(visible = true): BridgeIo & { posted: unknown[] } { const posted: unknown[] = []; @@ -31,6 +32,7 @@ beforeEach(() => { env.opened.length = 0; env.clipboard.text = ""; ws.configUpdates.length = 0; + win.outputLines.length = 0; }); describe("amicode bridge — open-external", () => { @@ -147,6 +149,26 @@ describe("amicode bridge — zoom (amicode#266)", () => { }); }); +describe("amicode bridge — diag-log relay (amicode#266 TEMP-DIAG)", () => { + it("writes relayed app console lines to the webview-diag output channel", () => { + const host = io(); + expect( + handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", level: "log", message: "[zoom] post: in" }, host), + ).toBe(true); + expect( + handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", level: "warn", message: "[zoom] relayed from pane: out" }, host), + ).toBe(true); + expect(win.outputLines).toEqual(["[log] [zoom] post: in", "[warn] [zoom] relayed from pane: out"]); + }); + + it("drops non-string or oversized payloads but still consumes", () => { + const host = io(); + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", message: 42 }, host)).toBe(true); + expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", message: "x".repeat(5000) }, host)).toBe(true); + expect(win.outputLines).toEqual([]); + }); +}); + describe("amicode bridge — commands & settings", () => { it("runs allowlisted commands only", async () => { const host = io(); From b7672cb9eeb2d20de011968cf3bc2ea2d82b033c Mon Sep 17 00:00:00 2001 From: Gennadi Ryan Date: Sun, 9 Aug 2026 04:43:26 +0000 Subject: [PATCH 4/6] Adding logging machinery to help disambiguate source of zoom key capture failure --- packages/extension/src/chat_panel.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/extension/src/chat_panel.ts b/packages/extension/src/chat_panel.ts index 0320f2c..1f80cfe 100644 --- a/packages/extension/src/chat_panel.ts +++ b/packages/extension/src/chat_panel.ts @@ -274,6 +274,31 @@ export class ChatPanel { } }); + // TEMP-DIAG + fix (amicode#266): capture the zoom chords at the webview + // HOST page — above the app iframe. Evidence so far: default forwarding + // works from the webview (Ctrl/Cmd+Shift+P reaches the workbench), yet + // workbench zoom never fires and the app document logs nothing, so the + // chord is dying somewhere between. If it reaches THIS document, we + // claim it (preventDefault — keydown targets one document, so the app + // iframe can never see the same key, no double-fire) and post the + // envelope straight to the extension (the "zoom" kind is in the relay + // allowlist), bypassing the app's registry entirely. Remove after the + // diagnosis. + window.addEventListener("keydown", function (e) { + var mod = e.metaKey || e.ctrlKey; + if (!mod) return; + var key = e.key; + var action = null; + if (key === "=" || key === "+") action = "in"; + else if (key === "-" || key === "_") action = "out"; + else if (key === "0") action = "reset"; + if (!action) return; + console.log("[zoom] host keydown:", action, "key=" + key, "shift=" + e.shiftKey); + vscode.postMessage({ source: "amicode", kind: "diag-log", level: "log", message: "[zoom] host keydown: " + action + " key=" + key + " shift=" + e.shiftKey }); + e.preventDefault(); + vscode.postMessage({ source: "amicode", kind: "zoom", action: action }); + }); + // Answer a clipboard-image-request from the framed app: read the first // image/* item off the OS clipboard (client-side; clipboard-read is // granted to this webview) and post it into the frame as a data URL. On From 9eb4aa136daf3bb2a1151a44b5347ee1124ac0be Mon Sep 17 00:00:00 2001 From: Gennadi Ryan Date: Sun, 9 Aug 2026 16:28:05 +0000 Subject: [PATCH 5/6] Adding logging machinery to help disambiguate source of zoom key capture failure; modified to be eager so that an empty log is genuinely attributable to a failure of the chord to land in the webview --- packages/extension/src/chat_bridge.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/extension/src/chat_bridge.ts b/packages/extension/src/chat_bridge.ts index 119bd1e..f4d67f0 100644 --- a/packages/extension/src/chat_bridge.ts +++ b/packages/extension/src/chat_bridge.ts @@ -32,11 +32,13 @@ export const BRIDGE_ALLOWED_COMMANDS: ReadonlySet = new Set([ "workbench.action.showCommands", ]); -// TEMP-DIAG (amicode#266 remote test): the app relays its [zoom]-prefixed -// console lines here so a remote session can hand back a log file ("Open Log -// File" on the "Amicode — webview diag" channel) instead of webview devtools. -// Remove together with the lane below. -let diagChannel: vscode.OutputChannel | undefined; +// TEMP-DIAG (amicode#266): eager probe — created at activation (this module +// is imported by chat_panel, which extension.ts imports at the top), so the +// channel exists with an "armed" line whether or not any chord ever fires. A +// visible channel proves the build contains the lane; the lane below appends +// the relayed [zoom] lines as they arrive. Remove after the diagnosis. +const diagChannel = vscode.window.createOutputChannel("Amicode — webview diag"); +diagChannel.appendLine("[amicode/zoom] diag relay armed — TEMP-DIAG (amicode#266)"); /** The bug-session lifecycle sink (amicode#250) — the panels wire the * BugReportManager's. Structural, so the bridge never imports the manager. */ @@ -207,7 +209,6 @@ export function handleAmicodeBridgeMessage(msg: unknown, io: BridgeIo): boolean const level = (msg as { level?: unknown }).level; const message = (msg as { message?: unknown }).message; if (typeof message === "string" && message.length <= 4096) { - diagChannel ??= vscode.window.createOutputChannel("Amicode — webview diag"); diagChannel.appendLine(`[${typeof level === "string" ? level : "log"}] ${message}`); } return true; From 285453830b5a7335c7f5ddb2238a2df7e91c91b5 Mon Sep 17 00:00:00 2001 From: Gennadi Ryan Date: Sun, 9 Aug 2026 18:07:15 +0000 Subject: [PATCH 6/6] Version 1 fix --- packages/extension/src/chat_bridge.ts | 42 ------------------ packages/extension/src/chat_panel.ts | 27 +----------- packages/extension/test/__mocks__/vscode.ts | 5 +-- packages/extension/test/chat_bridge.test.ts | 49 --------------------- 4 files changed, 2 insertions(+), 121 deletions(-) diff --git a/packages/extension/src/chat_bridge.ts b/packages/extension/src/chat_bridge.ts index f4d67f0..186bbd4 100644 --- a/packages/extension/src/chat_bridge.ts +++ b/packages/extension/src/chat_bridge.ts @@ -32,14 +32,6 @@ export const BRIDGE_ALLOWED_COMMANDS: ReadonlySet = new Set([ "workbench.action.showCommands", ]); -// TEMP-DIAG (amicode#266): eager probe — created at activation (this module -// is imported by chat_panel, which extension.ts imports at the top), so the -// channel exists with an "armed" line whether or not any chord ever fires. A -// visible channel proves the build contains the lane; the lane below appends -// the relayed [zoom] lines as they arrive. Remove after the diagnosis. -const diagChannel = vscode.window.createOutputChannel("Amicode — webview diag"); -diagChannel.appendLine("[amicode/zoom] diag relay armed — TEMP-DIAG (amicode#266)"); - /** The bug-session lifecycle sink (amicode#250) — the panels wire the * BugReportManager's. Structural, so the bridge never imports the manager. */ export interface BugReportSink { @@ -180,40 +172,6 @@ export function handleAmicodeBridgeMessage(msg: unknown, io: BridgeIo): boolean return true; } - // Zoom bridge (amicode#266): the workbench owns zoom inside the webview — - // the host intercepts the Cmd/Ctrl+Plus/Minus/0 chords before the webview - // document sees them, so the app cannot zoom itself. It posts the intent - // here and we run the matching workbench action. Three actions only, - // exact-match; anything else is a consumed no-op (our envelope, never - // foreign noise — same posture as the bug-lifecycle kinds). - if (msg.kind === "zoom") { - const action = (msg as { action?: unknown }).action; - const command = - action === "in" ? "workbench.action.zoomIn" : - action === "out" ? "workbench.action.zoomOut" : - action === "reset" ? "workbench.action.zoomReset" : undefined; - if (command) { - // TEMP-DIAG (amicode#266 remote test): the envelope survived the relay. - // Remove after the diagnosis. - console.log("[amicode/zoom] execute:", command); - void vscode.commands.executeCommand(command); - } - return true; - } - - // TEMP-DIAG (amicode#266 remote test): the app's relayed console lines land - // here — write them to the "Amicode — webview diag" output channel, whose - // backing file a remote session can hand back ("Open Log File"). Bounded - // payload; consumed either way. Remove after the diagnosis. - if (msg.kind === "diag-log") { - const level = (msg as { level?: unknown }).level; - const message = (msg as { message?: unknown }).message; - if (typeof message === "string" && message.length <= 4096) { - diagChannel.appendLine(`[${typeof level === "string" ? level : "log"}] ${message}`); - } - return true; - } - // The "Amico" palette group — allowlisted commands only. if (msg.kind === "command") { const command = (msg as unknown as { command?: unknown }).command; diff --git a/packages/extension/src/chat_panel.ts b/packages/extension/src/chat_panel.ts index 1f80cfe..cccf473 100644 --- a/packages/extension/src/chat_panel.ts +++ b/packages/extension/src/chat_panel.ts @@ -260,7 +260,7 @@ export class ChatPanel { replyClipboardImage(d.nonce); return; } - if (d && d.source === "amicode" && (d.kind === "command" || d.kind === "clipboard-request" || d.kind === "clipboard-write" || d.kind === "open-external" || d.kind === "open-file" || d.kind === "save-file" || d.kind === "set-default-model" || d.kind === "bug-filed" || d.kind === "bug-report-closed" || d.kind === "bug-report-poke" || d.kind === "zoom" || d.kind === "diag-log")) { + if (d && d.source === "amicode" && (d.kind === "command" || d.kind === "clipboard-request" || d.kind === "clipboard-write" || d.kind === "open-external" || d.kind === "open-file" || d.kind === "save-file" || d.kind === "set-default-model" || d.kind === "bug-filed" || d.kind === "bug-report-closed" || d.kind === "bug-report-poke")) { vscode.postMessage(d); } return; @@ -274,31 +274,6 @@ export class ChatPanel { } }); - // TEMP-DIAG + fix (amicode#266): capture the zoom chords at the webview - // HOST page — above the app iframe. Evidence so far: default forwarding - // works from the webview (Ctrl/Cmd+Shift+P reaches the workbench), yet - // workbench zoom never fires and the app document logs nothing, so the - // chord is dying somewhere between. If it reaches THIS document, we - // claim it (preventDefault — keydown targets one document, so the app - // iframe can never see the same key, no double-fire) and post the - // envelope straight to the extension (the "zoom" kind is in the relay - // allowlist), bypassing the app's registry entirely. Remove after the - // diagnosis. - window.addEventListener("keydown", function (e) { - var mod = e.metaKey || e.ctrlKey; - if (!mod) return; - var key = e.key; - var action = null; - if (key === "=" || key === "+") action = "in"; - else if (key === "-" || key === "_") action = "out"; - else if (key === "0") action = "reset"; - if (!action) return; - console.log("[zoom] host keydown:", action, "key=" + key, "shift=" + e.shiftKey); - vscode.postMessage({ source: "amicode", kind: "diag-log", level: "log", message: "[zoom] host keydown: " + action + " key=" + key + " shift=" + e.shiftKey }); - e.preventDefault(); - vscode.postMessage({ source: "amicode", kind: "zoom", action: action }); - }); - // Answer a clipboard-image-request from the framed app: read the first // image/* item off the OS clipboard (client-side; clipboard-read is // granted to this webview) and post it into the frame as a data URL. On diff --git a/packages/extension/test/__mocks__/vscode.ts b/packages/extension/test/__mocks__/vscode.ts index 69c490e..b9b16e5 100644 --- a/packages/extension/test/__mocks__/vscode.ts +++ b/packages/extension/test/__mocks__/vscode.ts @@ -2,16 +2,13 @@ // only the runtime members our node-side modules touch; types are erased at // compile time so they need no runtime shape. export const window = { - outputLines: [] as string[], showInformationMessage: () => Promise.resolve(undefined), showErrorMessage: () => Promise.resolve(undefined), showWarningMessage: () => Promise.resolve(undefined), showInputBox: () => Promise.resolve(undefined), showSaveDialog: () => Promise.resolve(undefined), createOutputChannel: () => ({ - appendLine(line: string) { - window.outputLines.push(line); - }, + appendLine() {}, append() {}, dispose() {}, }), diff --git a/packages/extension/test/chat_bridge.test.ts b/packages/extension/test/chat_bridge.test.ts index 865eb99..271dba0 100644 --- a/packages/extension/test/chat_bridge.test.ts +++ b/packages/extension/test/chat_bridge.test.ts @@ -13,7 +13,6 @@ import { handleAmicodeBridgeMessage, extractReportBugModel, type BridgeIo } from const env = vscode.env as unknown as { opened: unknown[]; clipboard: { text: string } }; const ws = vscode.workspace as unknown as { configUpdates: Array<[string, unknown]> }; -const win = vscode.window as unknown as { outputLines: string[] }; function io(visible = true): BridgeIo & { posted: unknown[] } { const posted: unknown[] = []; @@ -32,7 +31,6 @@ beforeEach(() => { env.opened.length = 0; env.clipboard.text = ""; ws.configUpdates.length = 0; - win.outputLines.length = 0; }); describe("amicode bridge — open-external", () => { @@ -122,53 +120,6 @@ describe("amicode bridge — clipboard", () => { }); }); -describe("amicode bridge — zoom (amicode#266)", () => { - it("routes the three zoom intents to their workbench actions", async () => { - const host = io(); - const ran = () => (vscode.commands as unknown as { executed: string[] }).executed; - const before = ran().length; - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "in" }, host)).toBe(true); - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "out" }, host)).toBe(true); - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "reset" }, host)).toBe(true); - await flush(); - expect(ran().slice(before)).toEqual([ - "workbench.action.zoomIn", - "workbench.action.zoomOut", - "workbench.action.zoomReset", - ]); - }); - - it("unknown zoom actions are consumed without executing anything", async () => { - const host = io(); - const ran = (vscode.commands as unknown as { executed: string[] }).executed; - const before = ran.length; - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom", action: "to-the-moon" }, host)).toBe(true); - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "zoom" }, host)).toBe(true); - await flush(); - expect(ran).toHaveLength(before); - }); -}); - -describe("amicode bridge — diag-log relay (amicode#266 TEMP-DIAG)", () => { - it("writes relayed app console lines to the webview-diag output channel", () => { - const host = io(); - expect( - handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", level: "log", message: "[zoom] post: in" }, host), - ).toBe(true); - expect( - handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", level: "warn", message: "[zoom] relayed from pane: out" }, host), - ).toBe(true); - expect(win.outputLines).toEqual(["[log] [zoom] post: in", "[warn] [zoom] relayed from pane: out"]); - }); - - it("drops non-string or oversized payloads but still consumes", () => { - const host = io(); - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", message: 42 }, host)).toBe(true); - expect(handleAmicodeBridgeMessage({ source: "amicode", kind: "diag-log", message: "x".repeat(5000) }, host)).toBe(true); - expect(win.outputLines).toEqual([]); - }); -}); - describe("amicode bridge — commands & settings", () => { it("runs allowlisted commands only", async () => { const host = io();