mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-19 18:40:57 -07:00
Clean up dead code (#17443)
This commit is contained in:
committed by
GitHub
parent
84e882770b
commit
80e1fa198f
@@ -4,7 +4,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { Logger } from '@opentelemetry/api-logs';
|
||||
import type { Config } from '../config/config.js';
|
||||
import type { HookPlanner, HookEventContext } from './hookPlanner.js';
|
||||
import type { HookRunner } from './hookRunner.js';
|
||||
@@ -38,265 +37,9 @@ import type {
|
||||
} from '@google/genai';
|
||||
import { logHookCall } from '../telemetry/loggers.js';
|
||||
import { HookCallEvent } from '../telemetry/types.js';
|
||||
import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
||||
import {
|
||||
MessageBusType,
|
||||
type HookExecutionRequest,
|
||||
} from '../confirmation-bus/types.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
import { coreEvents } from '../utils/events.js';
|
||||
|
||||
/**
|
||||
* Validates that a value is a non-null object
|
||||
*/
|
||||
function isObject(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates BeforeTool input fields
|
||||
*/
|
||||
function validateBeforeToolInput(input: Record<string, unknown>): {
|
||||
toolName: string;
|
||||
toolInput: Record<string, unknown>;
|
||||
mcpContext?: McpToolContext;
|
||||
} {
|
||||
const toolName = input['tool_name'];
|
||||
const toolInput = input['tool_input'];
|
||||
const mcpContext = input['mcp_context'];
|
||||
if (typeof toolName !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for BeforeTool hook event: tool_name must be a string',
|
||||
);
|
||||
}
|
||||
if (!isObject(toolInput)) {
|
||||
throw new Error(
|
||||
'Invalid input for BeforeTool hook event: tool_input must be an object',
|
||||
);
|
||||
}
|
||||
if (mcpContext !== undefined && !isObject(mcpContext)) {
|
||||
throw new Error(
|
||||
'Invalid input for BeforeTool hook event: mcp_context must be an object',
|
||||
);
|
||||
}
|
||||
return {
|
||||
toolName,
|
||||
toolInput,
|
||||
mcpContext: mcpContext as McpToolContext | undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates AfterTool input fields
|
||||
*/
|
||||
function validateAfterToolInput(input: Record<string, unknown>): {
|
||||
toolName: string;
|
||||
toolInput: Record<string, unknown>;
|
||||
toolResponse: Record<string, unknown>;
|
||||
mcpContext?: McpToolContext;
|
||||
} {
|
||||
const toolName = input['tool_name'];
|
||||
const toolInput = input['tool_input'];
|
||||
const toolResponse = input['tool_response'];
|
||||
const mcpContext = input['mcp_context'];
|
||||
if (typeof toolName !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for AfterTool hook event: tool_name must be a string',
|
||||
);
|
||||
}
|
||||
if (!isObject(toolInput)) {
|
||||
throw new Error(
|
||||
'Invalid input for AfterTool hook event: tool_input must be an object',
|
||||
);
|
||||
}
|
||||
if (!isObject(toolResponse)) {
|
||||
throw new Error(
|
||||
'Invalid input for AfterTool hook event: tool_response must be an object',
|
||||
);
|
||||
}
|
||||
if (mcpContext !== undefined && !isObject(mcpContext)) {
|
||||
throw new Error(
|
||||
'Invalid input for AfterTool hook event: mcp_context must be an object',
|
||||
);
|
||||
}
|
||||
return {
|
||||
toolName,
|
||||
toolInput,
|
||||
toolResponse,
|
||||
mcpContext: mcpContext as McpToolContext | undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates BeforeAgent input fields
|
||||
*/
|
||||
function validateBeforeAgentInput(input: Record<string, unknown>): {
|
||||
prompt: string;
|
||||
} {
|
||||
const prompt = input['prompt'];
|
||||
if (typeof prompt !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for BeforeAgent hook event: prompt must be a string',
|
||||
);
|
||||
}
|
||||
return { prompt };
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates AfterAgent input fields
|
||||
*/
|
||||
function validateAfterAgentInput(input: Record<string, unknown>): {
|
||||
prompt: string;
|
||||
promptResponse: string;
|
||||
stopHookActive: boolean;
|
||||
} {
|
||||
const prompt = input['prompt'];
|
||||
const promptResponse = input['prompt_response'];
|
||||
const stopHookActive = input['stop_hook_active'];
|
||||
if (typeof prompt !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for AfterAgent hook event: prompt must be a string',
|
||||
);
|
||||
}
|
||||
if (typeof promptResponse !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for AfterAgent hook event: prompt_response must be a string',
|
||||
);
|
||||
}
|
||||
// stopHookActive defaults to false if not a boolean
|
||||
return {
|
||||
prompt,
|
||||
promptResponse,
|
||||
stopHookActive:
|
||||
typeof stopHookActive === 'boolean' ? stopHookActive : false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates model-related input fields (llm_request)
|
||||
*/
|
||||
function validateModelInput(
|
||||
input: Record<string, unknown>,
|
||||
eventName: string,
|
||||
): { llmRequest: GenerateContentParameters } {
|
||||
const llmRequest = input['llm_request'];
|
||||
if (!isObject(llmRequest)) {
|
||||
throw new Error(
|
||||
`Invalid input for ${eventName} hook event: llm_request must be an object`,
|
||||
);
|
||||
}
|
||||
return { llmRequest: llmRequest as unknown as GenerateContentParameters };
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates AfterModel input fields
|
||||
*/
|
||||
function validateAfterModelInput(input: Record<string, unknown>): {
|
||||
llmRequest: GenerateContentParameters;
|
||||
llmResponse: GenerateContentResponse;
|
||||
} {
|
||||
const llmRequest = input['llm_request'];
|
||||
const llmResponse = input['llm_response'];
|
||||
if (!isObject(llmRequest)) {
|
||||
throw new Error(
|
||||
'Invalid input for AfterModel hook event: llm_request must be an object',
|
||||
);
|
||||
}
|
||||
if (!isObject(llmResponse)) {
|
||||
throw new Error(
|
||||
'Invalid input for AfterModel hook event: llm_response must be an object',
|
||||
);
|
||||
}
|
||||
return {
|
||||
llmRequest: llmRequest as unknown as GenerateContentParameters,
|
||||
llmResponse: llmResponse as unknown as GenerateContentResponse,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates Notification input fields
|
||||
*/
|
||||
function validateNotificationInput(input: Record<string, unknown>): {
|
||||
notificationType: NotificationType;
|
||||
message: string;
|
||||
details: Record<string, unknown>;
|
||||
} {
|
||||
const notificationType = input['notification_type'];
|
||||
const message = input['message'];
|
||||
const details = input['details'];
|
||||
if (typeof notificationType !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for Notification hook event: notification_type must be a string',
|
||||
);
|
||||
}
|
||||
if (typeof message !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for Notification hook event: message must be a string',
|
||||
);
|
||||
}
|
||||
if (!isObject(details)) {
|
||||
throw new Error(
|
||||
'Invalid input for Notification hook event: details must be an object',
|
||||
);
|
||||
}
|
||||
return {
|
||||
notificationType: notificationType as NotificationType,
|
||||
message,
|
||||
details,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates SessionStart input fields
|
||||
*/
|
||||
function validateSessionStartInput(input: Record<string, unknown>): {
|
||||
source: SessionStartSource;
|
||||
} {
|
||||
const source = input['source'];
|
||||
if (typeof source !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for SessionStart hook event: source must be a string',
|
||||
);
|
||||
}
|
||||
return {
|
||||
source: source as SessionStartSource,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates SessionEnd input fields
|
||||
*/
|
||||
function validateSessionEndInput(input: Record<string, unknown>): {
|
||||
reason: SessionEndReason;
|
||||
} {
|
||||
const reason = input['reason'];
|
||||
if (typeof reason !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for SessionEnd hook event: reason must be a string',
|
||||
);
|
||||
}
|
||||
return {
|
||||
reason: reason as SessionEndReason,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates PreCompress input fields
|
||||
*/
|
||||
function validatePreCompressInput(input: Record<string, unknown>): {
|
||||
trigger: PreCompressTrigger;
|
||||
} {
|
||||
const trigger = input['trigger'];
|
||||
if (typeof trigger !== 'string') {
|
||||
throw new Error(
|
||||
'Invalid input for PreCompress hook event: trigger must be a string',
|
||||
);
|
||||
}
|
||||
return {
|
||||
trigger: trigger as PreCompressTrigger,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook event bus that coordinates hook execution across the system
|
||||
*/
|
||||
@@ -305,29 +48,17 @@ export class HookEventHandler {
|
||||
private readonly hookPlanner: HookPlanner;
|
||||
private readonly hookRunner: HookRunner;
|
||||
private readonly hookAggregator: HookAggregator;
|
||||
private readonly messageBus: MessageBus;
|
||||
|
||||
constructor(
|
||||
config: Config,
|
||||
logger: Logger,
|
||||
hookPlanner: HookPlanner,
|
||||
hookRunner: HookRunner,
|
||||
hookAggregator: HookAggregator,
|
||||
messageBus: MessageBus,
|
||||
) {
|
||||
this.config = config;
|
||||
this.hookPlanner = hookPlanner;
|
||||
this.hookRunner = hookRunner;
|
||||
this.hookAggregator = hookAggregator;
|
||||
this.messageBus = messageBus;
|
||||
|
||||
// Subscribe to hook execution requests from MessageBus
|
||||
if (this.messageBus) {
|
||||
this.messageBus.subscribe<HookExecutionRequest>(
|
||||
MessageBusType.HOOK_EXECUTION_REQUEST,
|
||||
(request) => this.handleHookExecutionRequest(request),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -729,152 +460,4 @@ export class HookEventHandler {
|
||||
private getHookTypeFromResult(result: HookExecutionResult): 'command' {
|
||||
return result.hookConfig.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle hook execution requests from MessageBus
|
||||
* This method routes the request to the appropriate fire*Event method
|
||||
* and publishes the response back through MessageBus
|
||||
*
|
||||
* The request input only contains event-specific fields. This method adds
|
||||
* the common base fields (session_id, cwd, etc.) before routing.
|
||||
*/
|
||||
private async handleHookExecutionRequest(
|
||||
request: HookExecutionRequest,
|
||||
): Promise<void> {
|
||||
try {
|
||||
// Add base fields to the input
|
||||
const enrichedInput = {
|
||||
...this.createBaseInput(request.eventName as HookEventName),
|
||||
...request.input,
|
||||
} as Record<string, unknown>;
|
||||
|
||||
let result: AggregatedHookResult;
|
||||
|
||||
// Route to appropriate event handler based on eventName
|
||||
switch (request.eventName) {
|
||||
case HookEventName.BeforeTool: {
|
||||
const { toolName, toolInput, mcpContext } =
|
||||
validateBeforeToolInput(enrichedInput);
|
||||
result = await this.fireBeforeToolEvent(
|
||||
toolName,
|
||||
toolInput,
|
||||
mcpContext,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case HookEventName.AfterTool: {
|
||||
const { toolName, toolInput, toolResponse, mcpContext } =
|
||||
validateAfterToolInput(enrichedInput);
|
||||
result = await this.fireAfterToolEvent(
|
||||
toolName,
|
||||
toolInput,
|
||||
toolResponse,
|
||||
mcpContext,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case HookEventName.BeforeAgent: {
|
||||
const { prompt } = validateBeforeAgentInput(enrichedInput);
|
||||
result = await this.fireBeforeAgentEvent(prompt);
|
||||
break;
|
||||
}
|
||||
case HookEventName.AfterAgent: {
|
||||
const { prompt, promptResponse, stopHookActive } =
|
||||
validateAfterAgentInput(enrichedInput);
|
||||
result = await this.fireAfterAgentEvent(
|
||||
prompt,
|
||||
promptResponse,
|
||||
stopHookActive,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case HookEventName.BeforeModel: {
|
||||
const { llmRequest } = validateModelInput(
|
||||
enrichedInput,
|
||||
'BeforeModel',
|
||||
);
|
||||
const translatedRequest =
|
||||
defaultHookTranslator.toHookLLMRequest(llmRequest);
|
||||
// Update the enrichedInput with translated request
|
||||
enrichedInput['llm_request'] = translatedRequest;
|
||||
result = await this.fireBeforeModelEvent(llmRequest);
|
||||
break;
|
||||
}
|
||||
case HookEventName.AfterModel: {
|
||||
const { llmRequest, llmResponse } =
|
||||
validateAfterModelInput(enrichedInput);
|
||||
const translatedRequest =
|
||||
defaultHookTranslator.toHookLLMRequest(llmRequest);
|
||||
const translatedResponse =
|
||||
defaultHookTranslator.toHookLLMResponse(llmResponse);
|
||||
// Update the enrichedInput with translated versions
|
||||
enrichedInput['llm_request'] = translatedRequest;
|
||||
enrichedInput['llm_response'] = translatedResponse;
|
||||
result = await this.fireAfterModelEvent(llmRequest, llmResponse);
|
||||
break;
|
||||
}
|
||||
case HookEventName.BeforeToolSelection: {
|
||||
const { llmRequest } = validateModelInput(
|
||||
enrichedInput,
|
||||
'BeforeToolSelection',
|
||||
);
|
||||
const translatedRequest =
|
||||
defaultHookTranslator.toHookLLMRequest(llmRequest);
|
||||
// Update the enrichedInput with translated request
|
||||
enrichedInput['llm_request'] = translatedRequest;
|
||||
result = await this.fireBeforeToolSelectionEvent(llmRequest);
|
||||
break;
|
||||
}
|
||||
case HookEventName.Notification: {
|
||||
const { notificationType, message, details } =
|
||||
validateNotificationInput(enrichedInput);
|
||||
result = await this.fireNotificationEvent(
|
||||
notificationType,
|
||||
message,
|
||||
details,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case HookEventName.SessionStart: {
|
||||
const { source } = validateSessionStartInput(enrichedInput);
|
||||
result = await this.fireSessionStartEvent(source);
|
||||
break;
|
||||
}
|
||||
case HookEventName.SessionEnd: {
|
||||
const { reason } = validateSessionEndInput(enrichedInput);
|
||||
result = await this.fireSessionEndEvent(reason);
|
||||
break;
|
||||
}
|
||||
case HookEventName.PreCompress: {
|
||||
const { trigger } = validatePreCompressInput(enrichedInput);
|
||||
result = await this.firePreCompressEvent(trigger);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported hook event: ${request.eventName}`);
|
||||
}
|
||||
|
||||
// Publish response through MessageBus
|
||||
if (this.messageBus) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.messageBus.publish({
|
||||
type: MessageBusType.HOOK_EXECUTION_RESPONSE,
|
||||
correlationId: request.correlationId,
|
||||
success: result.success,
|
||||
output: result.finalOutput as unknown as Record<string, unknown>,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// Publish error response
|
||||
if (this.messageBus) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.messageBus.publish({
|
||||
type: MessageBusType.HOOK_EXECUTION_RESPONSE,
|
||||
correlationId: request.correlationId,
|
||||
success: false,
|
||||
error: error instanceof Error ? error : new Error(String(error)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user