mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-03 08:24:10 -07:00
fix(cli): prevent informational logs from polluting json output (#26264)
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
CoreEventEmitter,
|
||||
CoreEvent,
|
||||
coreEvents,
|
||||
type CoreEvents,
|
||||
type UserFeedbackPayload,
|
||||
type McpProgressPayload,
|
||||
} from './events.js';
|
||||
@@ -268,6 +269,61 @@ describe('CoreEventEmitter', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('drainBacklogs Transformation', () => {
|
||||
it('should transform events during drain', () => {
|
||||
const listener = vi.fn();
|
||||
events.emitOutput(false, 'stdout chunk');
|
||||
events.emitFeedback('info', 'info message');
|
||||
|
||||
events.on(CoreEvent.Output, listener);
|
||||
events.on(CoreEvent.UserFeedback, listener);
|
||||
|
||||
events.drainBacklogs(
|
||||
<K extends keyof CoreEvents>(event: K, args: CoreEvents[K]) => {
|
||||
if (event === (CoreEvent.Output as string)) {
|
||||
const payload = args[0] as { isStderr: boolean; chunk: string };
|
||||
return {
|
||||
event,
|
||||
args: [
|
||||
{ ...payload, isStderr: true },
|
||||
] as unknown as CoreEvents[K],
|
||||
};
|
||||
}
|
||||
return { event, args };
|
||||
},
|
||||
);
|
||||
|
||||
expect(listener).toHaveBeenCalledTimes(2);
|
||||
expect(listener).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ isStderr: true, chunk: 'stdout chunk' }),
|
||||
);
|
||||
expect(listener).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ message: 'info message' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('should drop events when transform returns undefined', () => {
|
||||
const listener = vi.fn();
|
||||
events.emitOutput(false, 'drop me');
|
||||
events.emitFeedback('info', 'keep me');
|
||||
|
||||
events.on(CoreEvent.Output, listener);
|
||||
events.on(CoreEvent.UserFeedback, listener);
|
||||
|
||||
events.drainBacklogs((event, args) => {
|
||||
if (event === CoreEvent.Output) {
|
||||
return undefined;
|
||||
}
|
||||
return { event, args };
|
||||
});
|
||||
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
expect(listener).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ message: 'keep me' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ModelChanged Event', () => {
|
||||
it('should emit ModelChanged event with correct payload', () => {
|
||||
const listener = vi.fn();
|
||||
|
||||
@@ -422,8 +422,15 @@ export class CoreEventEmitter extends EventEmitter<CoreEvents> {
|
||||
/**
|
||||
* Flushes buffered messages. Call this immediately after primary UI listener
|
||||
* subscribes.
|
||||
*
|
||||
* @param transform - Optional function to transform events before they are emitted.
|
||||
*/
|
||||
drainBacklogs(): void {
|
||||
drainBacklogs(
|
||||
transform?: <K extends keyof CoreEvents>(
|
||||
event: K,
|
||||
args: CoreEvents[K],
|
||||
) => { event: K; args: CoreEvents[K] } | undefined,
|
||||
): void {
|
||||
const backlog = this._eventBacklog;
|
||||
const head = this._backlogHead;
|
||||
this._eventBacklog = [];
|
||||
@@ -431,10 +438,21 @@ export class CoreEventEmitter extends EventEmitter<CoreEvents> {
|
||||
for (let i = head; i < backlog.length; i++) {
|
||||
const item = backlog[i];
|
||||
if (item === undefined) continue;
|
||||
|
||||
let eventToEmit = item.event;
|
||||
let argsToEmit = item.args;
|
||||
|
||||
if (transform) {
|
||||
const transformed = transform(item.event, item.args);
|
||||
if (!transformed) continue;
|
||||
eventToEmit = transformed.event;
|
||||
argsToEmit = transformed.args;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(this.emit as (event: keyof CoreEvents, ...args: unknown[]) => boolean)(
|
||||
item.event,
|
||||
...item.args,
|
||||
eventToEmit,
|
||||
...argsToEmit,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user