feat: multi-runtime selection in interactive installer (#1281)

The interactive prompt now accepts comma-separated or space-separated
choices (e.g., "1,4,6" or "1 4 6") to install multiple runtimes in
one go, without needing --all or running the installer multiple times.

- Replaced if/else-if chain with runtimeMap lookup + split parser
- Added hint text: "Select multiple: 1,4,6 or 1 4 6"
- Invalid choices silently filtered, duplicates deduplicated
- Empty input still defaults to Claude Code
- Choice "8" still selects all runtimes

Tests: 10 new tests covering comma/space/mixed separators,
deduplication, invalid input filtering, order preservation,
and source-level assertions.

Closes #1281

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-03-21 09:52:52 -04:00
parent 33db504934
commit f3ce0957cd
3 changed files with 181 additions and 27 deletions

View File

@@ -150,18 +150,13 @@ describe('Source code integration (Copilot)', () => {
assert.ok(src.includes('--copilot'), 'help text has --copilot option');
});
test('CLI-02: promptRuntime has Copilot as option 5', () => {
assert.ok(src.includes("choice === '5'"), 'choice 5 exists');
// Verify choice 5 maps to copilot (the line after choice === '5' should reference copilot)
const choice5Index = src.indexOf("choice === '5'");
const nextLines = src.substring(choice5Index, choice5Index + 100);
assert.ok(nextLines.includes('copilot'), 'choice 5 maps to copilot');
test('CLI-02: promptRuntime runtimeMap has Copilot as option 5', () => {
assert.ok(src.includes("'5': 'copilot'"), 'runtimeMap has 5 -> copilot');
});
test('CLI-02: promptRuntime has All option including copilot', () => {
// All option callback includes copilot in the runtimes array
const allCallbackMatch = src.match(/callback\(\[(['a-z', ]+)\]\)/g);
assert.ok(allCallbackMatch && allCallbackMatch.some(m => m.includes('copilot')), 'All option includes copilot');
test('CLI-02: promptRuntime allRuntimes array includes copilot', () => {
const allMatch = src.match(/const allRuntimes = \[([^\]]+)\]/);
assert.ok(allMatch && allMatch[1].includes('copilot'), 'allRuntimes includes copilot');
});
test('isCopilot variable exists in install function', () => {