feat(commands): Implement argument handling for custom commands via a prompt pipeline (#4702)

This commit is contained in:
Abhi
2025-07-23 16:11:23 -04:00
committed by GitHub
parent 2d1eafae95
commit bbe95f1eaa
9 changed files with 393 additions and 18 deletions
+47 -5
View File
@@ -15,7 +15,20 @@ import {
getUserCommandsDir,
} from '@google/gemini-cli-core';
import { ICommandLoader } from './types.js';
import { CommandKind, SlashCommand } from '../ui/commands/types.js';
import {
CommandContext,
CommandKind,
SlashCommand,
SubmitPromptActionReturn,
} from '../ui/commands/types.js';
import {
DefaultArgumentProcessor,
ShorthandArgumentProcessor,
} from './prompt-processors/argumentProcessor.js';
import {
IPromptProcessor,
SHORTHAND_ARGS_PLACEHOLDER,
} from './prompt-processors/types.js';
/**
* Defines the Zod schema for a command definition file. This serves as the
@@ -156,16 +169,45 @@ export class FileCommandLoader implements ICommandLoader {
.map((segment) => segment.replaceAll(':', '_'))
.join(':');
const processors: IPromptProcessor[] = [];
// The presence of '{{args}}' is the switch that determines the behavior.
if (validDef.prompt.includes(SHORTHAND_ARGS_PLACEHOLDER)) {
processors.push(new ShorthandArgumentProcessor());
} else {
processors.push(new DefaultArgumentProcessor());
}
return {
name: commandName,
description:
validDef.description ||
`Custom command from ${path.basename(filePath)}`,
kind: CommandKind.FILE,
action: async () => ({
type: 'submit_prompt',
content: validDef.prompt,
}),
action: async (
context: CommandContext,
_args: string,
): Promise<SubmitPromptActionReturn> => {
if (!context.invocation) {
console.error(
`[FileCommandLoader] Critical error: Command '${commandName}' was executed without invocation context.`,
);
return {
type: 'submit_prompt',
content: validDef.prompt, // Fallback to unprocessed prompt
};
}
let processedPrompt = validDef.prompt;
for (const processor of processors) {
processedPrompt = await processor.process(processedPrompt, context);
}
return {
type: 'submit_prompt',
content: processedPrompt,
};
},
};
}
}