mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-13 15:40:57 -07:00
feat(core): Improve validation logic for subagents.
This commit is contained in:
@@ -121,19 +121,22 @@ describe('DelegateToAgentTool', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw helpful error when agent_name does not exist', async () => {
|
||||
// We allow validation to pass now, checking happens in execute.
|
||||
const invocation = tool.build({
|
||||
agent_name: 'non_existent_agent',
|
||||
} as DelegateParams);
|
||||
|
||||
await expect(() =>
|
||||
invocation.execute(new AbortController().signal),
|
||||
).rejects.toThrow(
|
||||
it('should throw helpful error when agent_name does not exist', () => {
|
||||
expect(() =>
|
||||
tool.build({
|
||||
agent_name: 'non_existent_agent',
|
||||
} as DelegateParams),
|
||||
).toThrow(
|
||||
"Agent 'non_existent_agent' not found. Available agents are: 'test_agent' (A test agent), 'remote_agent' (A remote agent). Please choose a valid agent_name.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when agent_name is missing', () => {
|
||||
expect(() => tool.build({} as DelegateParams)).toThrow(
|
||||
"Missing 'agent_name' parameter. Please specify the agent you want to delegate to.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should validate correct arguments', async () => {
|
||||
const invocation = tool.build({
|
||||
agent_name: 'test_agent',
|
||||
@@ -152,28 +155,24 @@ describe('DelegateToAgentTool', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw helpful error for missing required argument', async () => {
|
||||
const invocation = tool.build({
|
||||
agent_name: 'test_agent',
|
||||
arg2: 123,
|
||||
} as DelegateParams);
|
||||
|
||||
await expect(() =>
|
||||
invocation.execute(new AbortController().signal),
|
||||
).rejects.toThrow(
|
||||
it('should throw helpful error for missing required argument', () => {
|
||||
expect(() =>
|
||||
tool.build({
|
||||
agent_name: 'test_agent',
|
||||
arg2: 123,
|
||||
} as DelegateParams),
|
||||
).toThrow(
|
||||
`Invalid arguments for agent 'test_agent': params must have required property 'arg1'. Input schema: ${JSON.stringify(mockAgentDef.inputConfig.inputSchema)}.`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw helpful error for invalid argument type', async () => {
|
||||
const invocation = tool.build({
|
||||
agent_name: 'test_agent',
|
||||
arg1: 123,
|
||||
} as DelegateParams);
|
||||
|
||||
await expect(() =>
|
||||
invocation.execute(new AbortController().signal),
|
||||
).rejects.toThrow(
|
||||
it('should throw helpful error for invalid argument type', () => {
|
||||
expect(() =>
|
||||
tool.build({
|
||||
agent_name: 'test_agent',
|
||||
arg1: 123,
|
||||
} as DelegateParams),
|
||||
).toThrow(
|
||||
`Invalid arguments for agent 'test_agent': params/arg1 must be string. Input schema: ${JSON.stringify(mockAgentDef.inputConfig.inputSchema)}.`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -121,11 +121,33 @@ export class DelegateToAgentTool extends BaseDeclarativeTool<
|
||||
);
|
||||
}
|
||||
|
||||
override validateToolParams(_params: DelegateParams): string | null {
|
||||
// We override the default schema validation because the generic JSON schema validation
|
||||
// produces poor error messages for discriminated unions (anyOf).
|
||||
// Instead, we perform detailed, agent-specific validation in the `execute` method
|
||||
// to provide rich error messages that help the LLM self-heal.
|
||||
override validateToolParams(params: DelegateParams): string | null {
|
||||
if (!params.agent_name) {
|
||||
return "Missing 'agent_name' parameter. Please specify the agent you want to delegate to.";
|
||||
}
|
||||
|
||||
const definition = this.registry.getDefinition(params.agent_name);
|
||||
if (!definition) {
|
||||
const availableAgents = this.registry
|
||||
.getAllDefinitions()
|
||||
.map((def) => `'${def.name}' (${def.description})`)
|
||||
.join(', ');
|
||||
|
||||
return `Agent '${params.agent_name}' not found. Available agents are: ${availableAgents}. Please choose a valid agent_name.`;
|
||||
}
|
||||
|
||||
const { agent_name: _agent_name, ...agentArgs } = params;
|
||||
|
||||
// Validate specific agent arguments here using SchemaValidator to generate helpful error messages.
|
||||
const validationError = SchemaValidator.validate(
|
||||
definition.inputConfig.inputSchema,
|
||||
agentArgs,
|
||||
);
|
||||
|
||||
if (validationError) {
|
||||
return `Invalid arguments for agent '${definition.name}': ${validationError}. Input schema: ${JSON.stringify(definition.inputConfig.inputSchema)}.`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -173,8 +195,8 @@ class DelegateInvocation extends BaseToolInvocation<
|
||||
override async shouldConfirmExecute(
|
||||
abortSignal: AbortSignal,
|
||||
): Promise<ToolCallConfirmationDetails | false> {
|
||||
const definition = this.registry.getDefinition(this.params.agent_name);
|
||||
if (!definition || definition.kind !== 'remote') {
|
||||
const definition = this.registry.getDefinition(this.params.agent_name)!;
|
||||
if (definition.kind !== 'remote') {
|
||||
// Local agents should execute without confirmation. Inner tool calls will bubble up their own confirmations to the user.
|
||||
return false;
|
||||
}
|
||||
@@ -191,32 +213,9 @@ class DelegateInvocation extends BaseToolInvocation<
|
||||
signal: AbortSignal,
|
||||
updateOutput?: (output: string | AnsiOutput) => void,
|
||||
): Promise<ToolResult> {
|
||||
const definition = this.registry.getDefinition(this.params.agent_name);
|
||||
if (!definition) {
|
||||
const availableAgents = this.registry
|
||||
.getAllDefinitions()
|
||||
.map((def) => `'${def.name}' (${def.description})`)
|
||||
.join(', ');
|
||||
|
||||
throw new Error(
|
||||
`Agent '${this.params.agent_name}' not found. Available agents are: ${availableAgents}. Please choose a valid agent_name.`,
|
||||
);
|
||||
}
|
||||
|
||||
const definition = this.registry.getDefinition(this.params.agent_name)!;
|
||||
const { agent_name: _agent_name, ...agentArgs } = this.params;
|
||||
|
||||
// Validate specific agent arguments here using SchemaValidator to generate helpful error messages.
|
||||
const validationError = SchemaValidator.validate(
|
||||
definition.inputConfig.inputSchema,
|
||||
agentArgs,
|
||||
);
|
||||
|
||||
if (validationError) {
|
||||
throw new Error(
|
||||
`Invalid arguments for agent '${definition.name}': ${validationError}. Input schema: ${JSON.stringify(definition.inputConfig.inputSchema)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const invocation = this.buildSubInvocation(
|
||||
definition,
|
||||
agentArgs as AgentInputs,
|
||||
|
||||
Reference in New Issue
Block a user