diff --git a/src/__tests__/fix-3263-runner-abstraction.test.ts b/src/__tests__/fix-3263-runner-abstraction.test.ts index fddd8be3..1294d425 100644 --- a/src/__tests__/fix-3263-runner-abstraction.test.ts +++ b/src/__tests__/fix-3263-runner-abstraction.test.ts @@ -195,3 +195,38 @@ describe('Issue #3263 — Runner abstraction layer', () => { }); }); }); + + it('unregisters a runner and updates default', () => { + const registry = new InMemoryRunnerRegistry(); + const first = new MockRunner('first'); + const second = new MockRunner('second'); + + registry.register(first); + registry.register(second); + expect(registry.getDefault()).toBe(first); + + registry.unregister('first'); + expect(registry.get('first')).toBeUndefined(); + expect(registry.listNames()).toEqual(['second']); + expect(registry.getDefault()).toBe(second); + }); + + it('unregisters the last runner and getDefault throws', () => { + const registry = new InMemoryRunnerRegistry(); + const runner = new MockRunner('only'); + + registry.register(runner); + registry.unregister('only'); + expect(registry.get('only')).toBeUndefined(); + expect(registry.listNames()).toEqual([]); + expect(() => registry.getDefault()).toThrow('No runners registered'); + }); + + it('unregister of unknown runner is a no-op', () => { + const registry = new InMemoryRunnerRegistry(); + registry.register(new MockRunner('existing')); + + registry.unregister('nonexistent'); + expect(registry.listNames()).toEqual(['existing']); + expect(registry.getDefault().name).toBe('existing'); + }); diff --git a/src/runners/registry.ts b/src/runners/registry.ts index 1546b7a4..408b4d4a 100644 --- a/src/runners/registry.ts +++ b/src/runners/registry.ts @@ -32,4 +32,12 @@ export class InMemoryRunnerRegistry implements RunnerRegistry { } return this.defaultRunner; } + + unregister(name: string): void { + this.runners.delete(name); + // If we removed the default, pick a new one + if (this.defaultRunner?.name === name) { + this.defaultRunner = this.runners.values().next().value; + } + } } diff --git a/src/runners/types.ts b/src/runners/types.ts index c59092b0..b21cddf6 100644 --- a/src/runners/types.ts +++ b/src/runners/types.ts @@ -165,4 +165,11 @@ export interface RunnerRegistry { /** Get the default runner. */ getDefault(): AgentRunner; + + /** + * Unregister a runner by name. + * + * @param name - Runner name to remove. + */ + unregister(name: string): void; }