fix(ui): ensure model changes update the UI immediately (#12412)

This commit is contained in:
Abhi
2025-11-03 14:59:51 -05:00
committed by GitHub
parent 59e0b10e6c
commit 265f24e5d7
6 changed files with 94 additions and 3 deletions
+1
View File
@@ -147,6 +147,7 @@ vi.mock('../agents/subagent-tool-wrapper.js', () => ({
const mockCoreEvents = vi.hoisted(() => ({
emitFeedback: vi.fn(),
emitModelChanged: vi.fn(),
}));
const mockSetGlobalProxy = vi.hoisted(() => vi.fn());
+5 -2
View File
@@ -41,6 +41,7 @@ import {
DEFAULT_OTLP_ENDPOINT,
uiTelemetryService,
} from '../telemetry/index.js';
import { coreEvents } from '../utils/events.js';
import { tokenLimit } from '../core/tokenLimits.js';
import {
DEFAULT_GEMINI_EMBEDDING_MODEL,
@@ -76,7 +77,6 @@ import type { UserTierId } from '../code_assist/types.js';
import { AgentRegistry } from '../agents/registry.js';
import { setGlobalProxy } from '../utils/fetch.js';
import { SubagentToolWrapper } from '../agents/subagent-tool-wrapper.js';
import { coreEvents } from '../utils/events.js';
export enum ApprovalMode {
DEFAULT = 'default',
@@ -711,7 +711,10 @@ export class Config {
return;
}
this.model = newModel;
if (this.model !== newModel) {
this.model = newModel;
coreEvents.emitModelChanged(newModel);
}
}
isInFallbackMode(): boolean {
+13
View File
@@ -156,4 +156,17 @@ describe('CoreEventEmitter', () => {
});
expect(listener.mock.calls[2][0]).toMatchObject({ message: 'Buffered 2' });
});
describe('ModelChanged Event', () => {
it('should emit ModelChanged event with correct payload', () => {
const listener = vi.fn();
events.on(CoreEvent.ModelChanged, listener);
const newModel = 'gemini-2.5-pro';
events.emitModelChanged(newModel);
expect(listener).toHaveBeenCalledTimes(1);
expect(listener).toHaveBeenCalledWith({ model: newModel });
});
});
});
+31
View File
@@ -43,9 +43,20 @@ export interface FallbackModeChangedPayload {
isInFallbackMode: boolean;
}
/**
* Payload for the 'model-changed' event.
*/
export interface ModelChangedPayload {
/**
* The new model that was set.
*/
model: string;
}
export enum CoreEvent {
UserFeedback = 'user-feedback',
FallbackModeChanged = 'fallback-mode-changed',
ModelChanged = 'model-changed',
}
export class CoreEventEmitter extends EventEmitter {
@@ -86,6 +97,14 @@ export class CoreEventEmitter extends EventEmitter {
this.emit(CoreEvent.FallbackModeChanged, payload);
}
/**
* Notifies subscribers that the model has changed.
*/
emitModelChanged(model: string): void {
const payload: ModelChangedPayload = { model };
this.emit(CoreEvent.ModelChanged, payload);
}
/**
* Flushes buffered messages. Call this immediately after primary UI listener
* subscribes.
@@ -106,6 +125,10 @@ export class CoreEventEmitter extends EventEmitter {
event: CoreEvent.FallbackModeChanged,
listener: (payload: FallbackModeChangedPayload) => void,
): this;
override on(
event: CoreEvent.ModelChanged,
listener: (payload: ModelChangedPayload) => void,
): this;
override on(
event: string | symbol,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -122,6 +145,10 @@ export class CoreEventEmitter extends EventEmitter {
event: CoreEvent.FallbackModeChanged,
listener: (payload: FallbackModeChangedPayload) => void,
): this;
override off(
event: CoreEvent.ModelChanged,
listener: (payload: ModelChangedPayload) => void,
): this;
override off(
event: string | symbol,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -138,6 +165,10 @@ export class CoreEventEmitter extends EventEmitter {
event: CoreEvent.FallbackModeChanged,
payload: FallbackModeChangedPayload,
): boolean;
override emit(
event: CoreEvent.ModelChanged,
payload: ModelChangedPayload,
): boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
override emit(event: string | symbol, ...args: any[]): boolean {
return super.emit(event, ...args);