From 03192d998001c2cae91ee94ac59e1c3d31d37eff Mon Sep 17 00:00:00 2001 From: Saqeb Akhter Date: Wed, 1 Jul 2026 11:19:17 +0000 Subject: [PATCH] fix: COD-153 match new session case from palette query --- src/web/public/panels-ui.js | 49 +++++++++++++++++++++++++++++++-- test/command-palette-ui.test.ts | 24 ++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/web/public/panels-ui.js b/src/web/public/panels-ui.js index 81cccfe0..5f936605 100644 --- a/src/web/public/panels-ui.js +++ b/src/web/public/panels-ui.js @@ -374,22 +374,61 @@ Object.assign(CodemanApp.prototype, { }); } - sessionItems.push(this._buildCommandPaletteNewSessionItem()); + sessionItems.push(this._buildCommandPaletteNewSessionItem(query)); return sessionItems; }, - _buildCommandPaletteNewSessionItem() { + _buildCommandPaletteNewSessionItem(query = '') { const mode = this.runMode || this._runMode || 'claude'; const labels = { claude: 'Claude', opencode: 'OpenCode', codex: 'Codex', gemini: 'Gemini' }; - const caseName = document.getElementById('quickStartCase')?.value || 'testcase'; + const caseName = this._findCommandPaletteCaseMatch(query) || document.getElementById('quickStartCase')?.value || 'testcase'; return { id: 'new-session', type: 'new-session', + caseName, title: 'New session', subtitle: `Run ${labels[mode] || mode} in ${caseName}`, }; }, + _findCommandPaletteCaseMatch(query = '') { + const needle = query.trim().toLowerCase(); + if (!needle || !Array.isArray(this.cases)) return null; + + const scoreCase = (caseItem) => { + const name = String(caseItem?.name || '').trim(); + if (!name) return 0; + const haystack = [ + name, + caseItem?.path, + caseItem?.casePath, + caseItem?.workingDir, + caseItem?.remote?.path, + caseItem?.remote?.hostId, + ] + .filter(Boolean) + .join(' ') + .toLowerCase(); + const lowerName = name.toLowerCase(); + if (lowerName === needle) return 100; + if (lowerName.startsWith(needle)) return 90; + if (lowerName.includes(needle)) return 80; + if (haystack.includes(needle)) return 60; + return 0; + }; + + let best = null; + let bestScore = 0; + for (const caseItem of this.cases) { + const score = scoreCase(caseItem); + if (score > bestScore) { + best = caseItem; + bestScore = score; + } + } + return best?.name || null; + }, + renderCommandPalette() { const search = document.getElementById('commandPaletteSearch'); const list = document.getElementById('commandPaletteList'); @@ -434,6 +473,10 @@ Object.assign(CodemanApp.prototype, { return; } if (item.type === 'new-session') { + const caseSelect = document.getElementById('quickStartCase'); + if (caseSelect && item.caseName) { + caseSelect.value = item.caseName; + } await this.run(); } }, diff --git a/test/command-palette-ui.test.ts b/test/command-palette-ui.test.ts index e7c38115..d1363dd2 100644 --- a/test/command-palette-ui.test.ts +++ b/test/command-palette-ui.test.ts @@ -43,6 +43,9 @@ function loadPaletteHarness(overrides: Record = {}) { listeners[`list:${event}`] = handler; }), }; + elements.quickStartCase = { + value: 'plex-previews', + }; const context = vm.createContext({ CodemanApp, @@ -87,6 +90,7 @@ function loadPaletteHarness(overrides: Record = {}) { ], ]); app.sessionOrder = ['sess-beta', 'sess-alpha']; + app.cases = [{ name: 'plex-previews' }, { name: 'flux-player' }, { name: 'api-tools' }]; app.selectSession = vi.fn(); app.run = vi.fn(); app.closeMobileHeaderUtilities = vi.fn(); @@ -176,6 +180,26 @@ describe('Command-K session palette', () => { expect(results[1]).toMatchObject({ type: 'new-session', title: 'New session' }); }); + it('uses the best matching case for the new-session action', async () => { + const { app, elements } = loadPaletteHarness(); + + const results = app.buildCommandPaletteItems('flux'); + const newSession = results.find((item: any) => item.type === 'new-session'); + + expect(newSession).toMatchObject({ + type: 'new-session', + caseName: 'flux-player', + subtitle: 'Run Claude in flux-player', + }); + + app.commandPaletteItems = [newSession]; + app.commandPaletteActiveIndex = 0; + await app.activateCommandPaletteItem(); + + expect(elements.quickStartCase.value).toBe('flux-player'); + expect(app.run).toHaveBeenCalledTimes(1); + }); + it('activates the highlighted session result', async () => { const { app } = loadPaletteHarness(); app.openCommandPalette();