feat: add /catch-up and /debug guided commands to draft welcome

Replace the 'What changed recently' draft chip with /catch-up, a command
whose hidden prompt branches on git state: reconstruct intent from an
in-progress diff, check an open PR's review state, or summarize recent
commits.

Add /debug as a new draft chip and command: a guided root-cause
investigation that captures the symptom, forms hypotheses, checks them
against the code, and confirms the cause before proposing a fix.

Both follow the /workspace-review pattern — visible + hidden magic
prompts wired into command autocomplete, the submit handler, draft preset
chips, and the Magic Prompts settings page, with i18n across all locales.
This commit is contained in:
Bohdan Triapitsyn
2026-05-30 02:04:32 +03:00
parent 2b08a51946
commit d49ca7bc43
21 changed files with 237 additions and 18 deletions
+47 -2
View File
@@ -100,8 +100,9 @@ type DraftPreset = {
};
const DRAFT_PRESETS: readonly DraftPreset[] = [
{ id: 'explore', icon: 'compass-3', labelKey: 'chat.draftPresets.explore.label', promptKey: 'chat.draftPresets.explore.prompt' },
{ id: 'changes', icon: 'git-branch', labelKey: 'chat.draftPresets.changes.label', promptKey: 'chat.draftPresets.changes.prompt' },
{ id: 'catchup', icon: 'history', labelKey: 'chat.draftPresets.catchup.label', command: '/catch-up' },
{ id: 'plan', icon: 'survey', labelKey: 'chat.draftPresets.plan.label', command: '/plan-feature' },
{ id: 'debug', icon: 'bug', labelKey: 'chat.draftPresets.debug.label', command: '/debug' },
{ id: 'review', icon: 'search-eye', labelKey: 'chat.draftPresets.review.label', command: '/workspace-review' },
];
@@ -1122,7 +1123,7 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
const availableSkills = useSkillsStore((s) => s.skills);
const knownSlashNames = React.useMemo(() => {
const names = new Set<string>([
'init', 'review', 'undo', 'redo', 'timeline', 'compact', 'summary', 'workspace-review', 'plan-feature',
'init', 'review', 'undo', 'redo', 'timeline', 'compact', 'summary', 'workspace-review', 'plan-feature', 'catch-up', 'debug',
]);
for (const command of availableCommands) names.add(command.name.toLowerCase());
for (const skill of availableSkills) names.add(skill.name.toLowerCase());
@@ -1972,6 +1973,50 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
}
return;
}
else if (commandName === 'catch-up' && (currentSessionId || newSessionDraftOpen)) {
try {
await sessionActions.waitForConnectionOrThrow();
const visibleText = await renderMagicPrompt('session.catchup.visible');
const instructionsText = await renderMagicPrompt('session.catchup.instructions');
await sendMessage(
visibleText,
providerIdToSend,
modelIdToSend,
agentNameToSend,
[],
agentMentionName,
[{ text: instructionsText, synthetic: true }],
variantToSend,
inputMode,
);
scrollToBottom?.();
} catch (error) {
toast.error(error instanceof Error ? error.message : t('chat.chatInput.toast.catchUpFailed'));
}
return;
}
else if (commandName === 'debug' && (currentSessionId || newSessionDraftOpen)) {
try {
await sessionActions.waitForConnectionOrThrow();
const visibleText = await renderMagicPrompt('session.debug.visible');
const instructionsText = await renderMagicPrompt('session.debug.instructions');
await sendMessage(
visibleText,
providerIdToSend,
modelIdToSend,
agentNameToSend,
[],
agentMentionName,
[{ text: instructionsText, synthetic: true }],
variantToSend,
inputMode,
);
scrollToBottom?.();
} catch (error) {
toast.error(error instanceof Error ? error.message : t('chat.chatInput.toast.debugFailed'));
}
return;
}
}
const currentSessionDirectory = currentSessionId
@@ -156,6 +156,14 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
? [{ id: 'openchamber:plan-feature', name: 'plan-feature', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.featurePlanDescription'), isOpenChamber: true }]
: []
),
...(canStartSessionCommand
? [{ id: 'openchamber:catch-up', name: 'catch-up', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.catchUpDescription'), isOpenChamber: true }]
: []
),
...(canStartSessionCommand
? [{ id: 'openchamber:debug', name: 'debug', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.debugDescription'), isOpenChamber: true }]
: []
),
];
const allCommands = [...builtInCommands, ...customCommands, ...skillCommands];
@@ -205,6 +213,14 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
? [{ id: 'openchamber:plan-feature', name: 'plan-feature', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.featurePlanDescription'), isOpenChamber: true }]
: []
),
...(canStartSessionCommand
? [{ id: 'openchamber:catch-up', name: 'catch-up', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.catchUpDescription'), isOpenChamber: true }]
: []
),
...(canStartSessionCommand
? [{ id: 'openchamber:debug', name: 'debug', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.debugDescription'), isOpenChamber: true }]
: []
),
];
const filtered = (searchQuery
@@ -148,6 +148,22 @@ const PROMPT_PAGE_MAP: Record<string, PromptPageConfig> = {
{ id: 'session.plan.instructions', titleKey: 'settings.magicPrompts.page.block.instructions' },
],
},
'session.catchup': {
titleKey: 'settings.magicPrompts.page.group.sessionCatchUp.title',
descriptionKey: 'settings.magicPrompts.page.group.sessionCatchUp.description',
blocks: [
{ id: 'session.catchup.visible', titleKey: 'settings.magicPrompts.page.block.visiblePrompt' },
{ id: 'session.catchup.instructions', titleKey: 'settings.magicPrompts.page.block.instructions' },
],
},
'session.debug': {
titleKey: 'settings.magicPrompts.page.group.sessionDebug.title',
descriptionKey: 'settings.magicPrompts.page.group.sessionDebug.description',
blocks: [
{ id: 'session.debug.visible', titleKey: 'settings.magicPrompts.page.block.visiblePrompt' },
{ id: 'session.debug.instructions', titleKey: 'settings.magicPrompts.page.block.instructions' },
],
},
'session.fusion': {
titleKey: 'settings.magicPrompts.page.group.sessionFusion.title',
descriptionKey: 'settings.magicPrompts.page.group.sessionFusion.description',
@@ -48,6 +48,8 @@ export const MagicPromptsSidebar: React.FC<MagicPromptsSidebarProps> = ({ onItem
{ id: 'session.summary', titleKey: 'settings.magicPrompts.sidebar.item.sessionSummary' },
{ id: 'session.review', titleKey: 'settings.magicPrompts.sidebar.item.sessionWorkspaceReview' },
{ id: 'session.plan', titleKey: 'settings.magicPrompts.sidebar.item.sessionFeaturePlan' },
{ id: 'session.catchup', titleKey: 'settings.magicPrompts.sidebar.item.sessionCatchUp' },
{ id: 'session.debug', titleKey: 'settings.magicPrompts.sidebar.item.sessionDebug' },
{ id: 'session.fusion', titleKey: 'settings.magicPrompts.sidebar.item.sessionFusion' },
],
},