feat(core,cli): enforce mandatory MessageBus injection (Phase 3 Hard Migration) (#15776)

This commit is contained in:
Abhi
2026-01-04 17:11:43 -05:00
committed by GitHub
parent 90be9c3587
commit 12c7c9cc42
57 changed files with 442 additions and 278 deletions

View File

@@ -13,10 +13,10 @@ import {
getMCPServerStatus,
getMCPDiscoveryState,
DiscoveredMCPTool,
type MessageBus,
} from '@google/gemini-cli-core';
import type { CallableTool } from '@google/genai';
import { Type } from '@google/genai';
import { MessageType } from '../types.js';
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
@@ -37,6 +37,12 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
};
});
const mockMessageBus = {
publish: vi.fn(),
subscribe: vi.fn(),
unsubscribe: vi.fn(),
} as unknown as MessageBus;
// Helper function to create a mock DiscoveredMCPTool
const createMockMCPTool = (
name: string,
@@ -50,8 +56,14 @@ const createMockMCPTool = (
} as unknown as CallableTool,
serverName,
name,
description || `Description for ${name}`,
{ type: Type.OBJECT, properties: {} },
description || 'Mock tool description',
{ type: 'object', properties: {} },
mockMessageBus,
undefined, // trust
undefined, // nameOverride
undefined, // cliConfig
undefined, // extensionName
undefined, // extensionId
);
describe('mcpCommand', () => {

View File

@@ -54,6 +54,12 @@ describe('handleAtCommand', () => {
const getToolRegistry = vi.fn();
const mockMessageBus = {
publish: vi.fn(),
subscribe: vi.fn(),
unsubscribe: vi.fn(),
} as unknown as core.MessageBus;
mockConfig = {
getToolRegistry,
getTargetDir: () => testRootDir,
@@ -94,11 +100,12 @@ describe('handleAtCommand', () => {
getMcpClientManager: () => ({
getClient: () => undefined,
}),
getMessageBus: () => mockMessageBus,
} as unknown as Config;
const registry = new ToolRegistry(mockConfig);
registry.registerTool(new ReadManyFilesTool(mockConfig));
registry.registerTool(new GlobTool(mockConfig));
const registry = new ToolRegistry(mockConfig, mockMessageBus);
registry.registerTool(new ReadManyFilesTool(mockConfig, mockMessageBus));
registry.registerTool(new GlobTool(mockConfig, mockMessageBus));
getToolRegistry.mockReturnValue(registry);
});

View File

@@ -164,7 +164,10 @@ export async function handleAtCommand({
};
const toolRegistry = config.getToolRegistry();
const readManyFilesTool = new ReadManyFilesTool(config);
const readManyFilesTool = new ReadManyFilesTool(
config,
config.getMessageBus(),
);
const globTool = toolRegistry.getTool('glob');
if (!readManyFilesTool) {

View File

@@ -24,6 +24,7 @@ import {
ReadManyFilesTool,
type GeminiChat,
type Config,
type MessageBus,
} from '@google/gemini-cli-core';
import { SettingScope, type LoadedSettings } from '../config/settings.js';
import { loadCliConfig, type CliArgs } from '../config/config.js';
@@ -97,6 +98,11 @@ describe('GeminiAgent', () => {
getGeminiClient: vi.fn().mockReturnValue({
startChat: vi.fn().mockResolvedValue({}),
}),
getMessageBus: vi.fn().mockReturnValue({
publish: vi.fn(),
subscribe: vi.fn(),
unsubscribe: vi.fn(),
}),
} as unknown as Mocked<Awaited<ReturnType<typeof loadCliConfig>>>;
mockSettings = {
merged: {
@@ -261,6 +267,7 @@ describe('Session', () => {
let session: Session;
let mockToolRegistry: { getTool: Mock };
let mockTool: { kind: string; build: Mock };
let mockMessageBus: Mocked<MessageBus>;
beforeEach(() => {
mockChat = {
@@ -279,6 +286,11 @@ describe('Session', () => {
mockToolRegistry = {
getTool: vi.fn().mockReturnValue(mockTool),
};
mockMessageBus = {
publish: vi.fn(),
subscribe: vi.fn(),
unsubscribe: vi.fn(),
} as unknown as Mocked<MessageBus>;
mockConfig = {
getModel: vi.fn().mockReturnValue('gemini-pro'),
getPreviewFeatures: vi.fn().mockReturnValue({}),
@@ -290,6 +302,7 @@ describe('Session', () => {
getTargetDir: vi.fn().mockReturnValue('/tmp'),
getEnableRecursiveFileSearch: vi.fn().mockReturnValue(false),
getDebugMode: vi.fn().mockReturnValue(false),
getMessageBus: vi.fn().mockReturnValue(mockMessageBus),
} as unknown as Mocked<Config>;
mockConnection = {
sessionUpdate: vi.fn(),

View File

@@ -609,7 +609,10 @@ export class Session {
const ignoredPaths: string[] = [];
const toolRegistry = this.config.getToolRegistry();
const readManyFilesTool = new ReadManyFilesTool(this.config);
const readManyFilesTool = new ReadManyFilesTool(
this.config,
this.config.getMessageBus(),
);
const globTool = toolRegistry.getTool('glob');
if (!readManyFilesTool) {