Support completion of checkpoint names in /resume (#1063)

This commit is contained in:
Billy Biggs 2025-06-15 11:40:39 -07:00 committed by GitHub
parent 6d772a30c0
commit b67806ae9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 67 additions and 4 deletions

View File

@ -109,11 +109,20 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
const selectedSuggestion = completionSuggestions[indexToUse];
if (query.trimStart().startsWith('/')) {
const parts = query.trimStart().substring(1).split(' ');
const commandName = parts[0];
const slashIndex = query.indexOf('/');
const base = query.substring(0, slashIndex + 1);
const newValue = base + selectedSuggestion.value;
buffer.setText(newValue);
handleSubmitAndClear(newValue);
const command = slashCommands.find((cmd) => cmd.name === commandName);
if (command && command.completion) {
const newValue = `${base}${commandName} ${selectedSuggestion.value}`;
buffer.setText(newValue);
} else {
const newValue = base + selectedSuggestion.value;
buffer.setText(newValue);
handleSubmitAndClear(newValue);
}
} else {
const atIndex = query.lastIndexOf('@');
if (atIndex === -1) return;
@ -131,7 +140,13 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
}
resetCompletionState();
},
[resetCompletionState, handleSubmitAndClear, buffer, completionSuggestions],
[
resetCompletionState,
handleSubmitAndClear,
buffer,
completionSuggestions,
slashCommands,
],
);
useInput(

View File

@ -44,6 +44,7 @@ export interface SlashCommand {
name: string;
altName?: string;
description?: string;
completion?: () => Promise<string[]>;
action: (
mainCommand: string,
subCommand?: string,
@ -643,6 +644,25 @@ Add any other context about the problem here.
name: 'resume',
description:
'resume from conversation checkpoint. Usage: /resume [tag]',
completion: async () => {
const geminiDir = config?.getGeminiDir();
if (!geminiDir) {
return [];
}
try {
const files = await fs.readdir(geminiDir);
return files
.filter(
(file) =>
file.startsWith('checkpoint-') && file.endsWith('.json'),
)
.map((file) =>
file.replace('checkpoint-', '').replace('.json', ''),
);
} catch (_err) {
return [];
}
},
action: async (_mainCommand, subCommand, _args) => {
const tag = (subCommand || '').trim();
const logger = new Logger(config?.getSessionId() || '');

View File

@ -127,6 +127,34 @@ export function useCompletion(
// --- Handle Slash Command Completion ---
if (trimmedQuery.startsWith('/')) {
const parts = trimmedQuery.substring(1).split(' ');
const commandName = parts[0];
const subCommand = parts.slice(1).join(' ');
const command = slashCommands.find(
(cmd) => cmd.name === commandName || cmd.altName === commandName,
);
if (command && command.completion) {
const fetchAndSetSuggestions = async () => {
setIsLoadingSuggestions(true);
if (command.completion) {
const results = await command.completion();
const filtered = results.filter((r) => r.startsWith(subCommand));
const newSuggestions = filtered.map((s) => ({
label: s,
value: s,
}));
setSuggestions(newSuggestions);
setShowSuggestions(newSuggestions.length > 0);
setActiveSuggestionIndex(newSuggestions.length > 0 ? 0 : -1);
}
setIsLoadingSuggestions(false);
};
fetchAndSetSuggestions();
return;
}
const partialCommand = trimmedQuery.substring(1);
const filteredSuggestions = slashCommands
.filter(