mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-20 19:11:23 -07:00
feat(core, ui): Add /agents refresh command. (#16204)
This commit is contained in:
@@ -162,6 +162,20 @@ describe('A2AClientManager', () => {
|
||||
"[A2AClientManager] Loaded agent 'TestAgent' from http://test.agent/card",
|
||||
);
|
||||
});
|
||||
|
||||
it('should clear the cache', async () => {
|
||||
await manager.loadAgent('TestAgent', 'http://test.agent/card');
|
||||
expect(manager.getAgentCard('TestAgent')).toBeDefined();
|
||||
expect(manager.getClient('TestAgent')).toBeDefined();
|
||||
|
||||
manager.clearCache();
|
||||
|
||||
expect(manager.getAgentCard('TestAgent')).toBeUndefined();
|
||||
expect(manager.getClient('TestAgent')).toBeUndefined();
|
||||
expect(debugLogger.debug).toHaveBeenCalledWith(
|
||||
'[A2AClientManager] Cache cleared.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sendMessage', () => {
|
||||
|
||||
@@ -104,6 +104,15 @@ export class A2AClientManager {
|
||||
return agentCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates all cached clients and agent cards.
|
||||
*/
|
||||
clearCache(): void {
|
||||
this.clients.clear();
|
||||
this.agentCards.clear();
|
||||
debugLogger.debug('[A2AClientManager] Cache cleared.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to a loaded agent.
|
||||
* @param agentName The name of the agent to send the message to.
|
||||
|
||||
@@ -99,7 +99,7 @@ describe('AgentRegistry', () => {
|
||||
|
||||
const agentCount = debugRegistry.getAllDefinitions().length;
|
||||
expect(debugLogSpy).toHaveBeenCalledWith(
|
||||
`[AgentRegistry] Initialized with ${agentCount} agents.`,
|
||||
`[AgentRegistry] Loaded with ${agentCount} agents.`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -444,6 +444,37 @@ describe('AgentRegistry', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('reload', () => {
|
||||
it('should clear existing agents and reload from directories', async () => {
|
||||
const config = makeFakeConfig({ enableAgents: true });
|
||||
const registry = new TestableAgentRegistry(config);
|
||||
|
||||
const initialAgent = { ...MOCK_AGENT_V1, name: 'InitialAgent' };
|
||||
await registry.testRegisterAgent(initialAgent);
|
||||
expect(registry.getDefinition('InitialAgent')).toBeDefined();
|
||||
|
||||
const newAgent = { ...MOCK_AGENT_V1, name: 'NewAgent' };
|
||||
vi.mocked(tomlLoader.loadAgentsFromDirectory).mockResolvedValue({
|
||||
agents: [newAgent],
|
||||
errors: [],
|
||||
});
|
||||
|
||||
const clearCacheSpy = vi.fn();
|
||||
vi.mocked(A2AClientManager.getInstance).mockReturnValue({
|
||||
clearCache: clearCacheSpy,
|
||||
} as unknown as A2AClientManager);
|
||||
|
||||
const emitSpy = vi.spyOn(coreEvents, 'emitAgentsRefreshed');
|
||||
|
||||
await registry.reload();
|
||||
|
||||
expect(clearCacheSpy).toHaveBeenCalled();
|
||||
expect(registry.getDefinition('InitialAgent')).toBeUndefined();
|
||||
expect(registry.getDefinition('NewAgent')).toBeDefined();
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('inheritance and refresh', () => {
|
||||
it('should resolve "inherit" to the current model from configuration', async () => {
|
||||
const config = makeFakeConfig({ model: 'current-model' });
|
||||
|
||||
@@ -46,8 +46,6 @@ export class AgentRegistry {
|
||||
* Discovers and loads agents.
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
this.loadBuiltInAgents();
|
||||
|
||||
coreEvents.on(CoreEvent.ModelChanged, () => {
|
||||
this.refreshAgents().catch((e) => {
|
||||
debugLogger.error(
|
||||
@@ -57,6 +55,22 @@ export class AgentRegistry {
|
||||
});
|
||||
});
|
||||
|
||||
await this.loadAgents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current registry and re-scans for agents.
|
||||
*/
|
||||
async reload(): Promise<void> {
|
||||
A2AClientManager.getInstance().clearCache();
|
||||
this.agents.clear();
|
||||
await this.loadAgents();
|
||||
coreEvents.emitAgentsRefreshed();
|
||||
}
|
||||
|
||||
private async loadAgents(): Promise<void> {
|
||||
this.loadBuiltInAgents();
|
||||
|
||||
if (!this.config.isAgentsEnabled()) {
|
||||
return;
|
||||
}
|
||||
@@ -99,7 +113,7 @@ export class AgentRegistry {
|
||||
|
||||
if (this.config.getDebugMode()) {
|
||||
debugLogger.log(
|
||||
`[AgentRegistry] Initialized with ${this.agents.size} agents.`,
|
||||
`[AgentRegistry] Loaded with ${this.agents.size} agents.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ export enum CoreEvent {
|
||||
SettingsChanged = 'settings-changed',
|
||||
HookStart = 'hook-start',
|
||||
HookEnd = 'hook-end',
|
||||
AgentsRefreshed = 'agents-refreshed',
|
||||
}
|
||||
|
||||
export interface CoreEvents {
|
||||
@@ -119,6 +120,7 @@ export interface CoreEvents {
|
||||
[CoreEvent.SettingsChanged]: never[];
|
||||
[CoreEvent.HookStart]: [HookStartPayload];
|
||||
[CoreEvent.HookEnd]: [HookEndPayload];
|
||||
[CoreEvent.AgentsRefreshed]: never[];
|
||||
}
|
||||
|
||||
type EventBacklogItem = {
|
||||
@@ -220,6 +222,13 @@ export class CoreEventEmitter extends EventEmitter<CoreEvents> {
|
||||
this.emit(CoreEvent.HookEnd, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies subscribers that agents have been refreshed.
|
||||
*/
|
||||
emitAgentsRefreshed(): void {
|
||||
this.emit(CoreEvent.AgentsRefreshed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes buffered messages. Call this immediately after primary UI listener
|
||||
* subscribes.
|
||||
|
||||
Reference in New Issue
Block a user