feat(ui): add visual indicators for hook execution (#15408)

This commit is contained in:
Abhi
2026-01-06 15:52:12 -05:00
committed by GitHub
parent 86b5995f12
commit 61dbab03e0
27 changed files with 1124 additions and 73 deletions

View File

@@ -274,4 +274,35 @@ describe('CoreEventEmitter', () => {
expect(listener).toHaveBeenCalledWith({ model: newModel });
});
});
describe('Hook Events', () => {
it('should emit HookStart event with correct payload using helper', () => {
const listener = vi.fn();
events.on(CoreEvent.HookStart, listener);
const payload = {
hookName: 'test-hook',
eventName: 'before-agent',
hookIndex: 1,
totalHooks: 1,
};
events.emitHookStart(payload);
expect(listener).toHaveBeenCalledWith(payload);
});
it('should emit HookEnd event with correct payload using helper', () => {
const listener = vi.fn();
events.on(CoreEvent.HookEnd, listener);
const payload = {
hookName: 'test-hook',
eventName: 'before-agent',
success: true,
};
events.emitHookEnd(payload);
expect(listener).toHaveBeenCalledWith(payload);
});
});
});

View File

@@ -67,6 +67,36 @@ export interface MemoryChangedPayload {
fileCount: number;
}
/**
* Base payload for hook-related events.
*/
export interface HookPayload {
hookName: string;
eventName: string;
}
/**
* Payload for the 'hook-start' event.
*/
export interface HookStartPayload extends HookPayload {
/**
* The 1-based index of the current hook in the execution sequence.
* Used for progress indication (e.g. "Hook 1/3").
*/
hookIndex?: number;
/**
* The total number of hooks in the current execution sequence.
*/
totalHooks?: number;
}
/**
* Payload for the 'hook-end' event.
*/
export interface HookEndPayload extends HookPayload {
success: boolean;
}
export enum CoreEvent {
UserFeedback = 'user-feedback',
ModelChanged = 'model-changed',
@@ -75,6 +105,8 @@ export enum CoreEvent {
MemoryChanged = 'memory-changed',
ExternalEditorClosed = 'external-editor-closed',
SettingsChanged = 'settings-changed',
HookStart = 'hook-start',
HookEnd = 'hook-end',
}
export interface CoreEvents {
@@ -85,6 +117,8 @@ export interface CoreEvents {
[CoreEvent.MemoryChanged]: [MemoryChangedPayload];
[CoreEvent.ExternalEditorClosed]: never[];
[CoreEvent.SettingsChanged]: never[];
[CoreEvent.HookStart]: [HookStartPayload];
[CoreEvent.HookEnd]: [HookEndPayload];
}
type EventBacklogItem = {
@@ -172,6 +206,20 @@ export class CoreEventEmitter extends EventEmitter<CoreEvents> {
this.emit(CoreEvent.SettingsChanged);
}
/**
* Notifies subscribers that a hook execution has started.
*/
emitHookStart(payload: HookStartPayload): void {
this.emit(CoreEvent.HookStart, payload);
}
/**
* Notifies subscribers that a hook execution has ended.
*/
emitHookEnd(payload: HookEndPayload): void {
this.emit(CoreEvent.HookEnd, payload);
}
/**
* Flushes buffered messages. Call this immediately after primary UI listener
* subscribes.