From fac47f067d30dadd0a013ad956de6b2acf1165e9 Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Sat, 24 Oct 2026 14:41:50 +0200 Subject: [PATCH] fix: address the release-prep review of #685 Keep the Run button's mode when fewer than two agents are offered (_commandPaletteAgent), so a Docker case whose host offers only Shell still starts the container agent the Run button shows; pinned by a new palette test. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/web/public/panels-ui.js | 18 ++++++++++++++---- test/command-palette-ui.test.ts | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/web/public/panels-ui.js b/src/web/public/panels-ui.js index 40a758f5..6d45db9a 100644 --- a/src/web/public/panels-ui.js +++ b/src/web/public/panels-ui.js @@ -575,7 +575,8 @@ Object.assign(CodemanApp.prototype, { * enabled entries that are installed here, in catalog order, the same list the * welcome screen's Run buttons offer (renderWelcomeCliActions). The ids are * DATA from the registry, never a list kept here. Empty on a page rendered - * without the catalog, which leaves the row on the Run button's mode. + * without the catalog; that and a single entry both leave the row on the Run + * button's mode (see _commandPaletteAgent). */ _commandPaletteAgentChoices() { const catalog = typeof window !== 'undefined' && Array.isArray(window.__codemanCliCatalog) ? window.__codemanCliCatalog : []; @@ -584,14 +585,23 @@ Object.assign(CodemanApp.prototype, { .map((cli) => ({ id: cli.id, label: (typeof cli.label === 'string' && cli.label.trim()) || cli.id })); }, - /** The agent the new-session row will start, or null when the catalog offers none. */ + /** + * The agent the new-session row will start, or null when fewer than two are + * offered. With one entry there is no picker to change it, so the row keeps + * the Run button's mode: for a Docker case the Run menu offers the + * container's CLIs while this list follows the host's, and the only host + * entry (often Shell) must not replace the agent the Run button shows. + */ _commandPaletteAgent() { const choices = this._commandPaletteAgentChoices(); - if (!choices.length) return null; + if (choices.length < 2) return null; return choices.find((c) => c.id === this._commandPaletteAgentId) || choices[0]; }, - /** Each time the palette opens, the row starts on the Run button's mode (or the first offered agent). */ + /** + * Each time the palette opens, the row starts on the Run button's mode (or, + * with two or more offered and that mode not among them, the first offered agent). + */ _resetCommandPaletteAgent() { const choices = this._commandPaletteAgentChoices(); const current = this.runMode || this._runMode; diff --git a/test/command-palette-ui.test.ts b/test/command-palette-ui.test.ts index 3b78c78a..1bd320e8 100644 --- a/test/command-palette-ui.test.ts +++ b/test/command-palette-ui.test.ts @@ -513,6 +513,28 @@ describe('Command-K new-session agent picker', () => { expect(elements.commandPaletteList.innerHTML).not.toContain('data-palette-agent-cycle'); }); + + it('keeps the Run button mode when the host offers a single other agent (a Docker case)', async () => { + // The host has only Shell, while a Docker case's Run menu put the Run + // button on the container's claude: Enter must still start claude. + const { app, elements } = loadAgentPalette(PALETTE_CATALOG.slice(0, 2)); + app.isCliAvailable = (id: string) => id !== 'claude'; + let modeDuringRun: string | undefined; + app.run = vi.fn(async () => { + modeDuringRun = app._runMode; + }); + + app.openCommandPalette(); + elements.commandPaletteSearch.value = 'nomatch'; + app.renderCommandPalette(); + const index = app.commandPaletteItems.findIndex((i: any) => i.type === 'new-session'); + + expect(app.commandPaletteItems[index]).toMatchObject({ mode: 'claude', subtitle: 'Run Claude in plex-previews' }); + expect(elements.commandPaletteList.innerHTML).not.toContain('data-palette-agent-cycle'); + await app.activateCommandPaletteItem(index); + expect(modeDuringRun).toBe('claude'); + expect(app._runMode).toBe('claude'); + }); }); describe('Session Manager unified list', () => {