fix(cli): address review issues in /btw command

- Add pendingItem conflict guard to prevent overwriting other operations
- Use finally block to ensure setPendingItem(null) is always called
- Wrap "Thinking..." with t() for i18n support
- Remove unnecessary type assertion, use typed variable instead

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Shaojin Wen 2026-03-14 15:53:14 +08:00
parent 3818f8acd4
commit 8dc34c385d
2 changed files with 45 additions and 37 deletions

View file

@ -57,6 +57,17 @@ export const btwCommand: SlashCommand = {
};
}
// Guard against concurrent pending operations
if (ui.pendingItem) {
return {
type: 'message',
messageType: 'error',
content: t(
'Another operation is in progress. Please wait for it to complete.',
),
};
}
// Show pending state
const pendingItem: HistoryItemBtw = {
type: MessageType.BTW,
@ -92,7 +103,6 @@ export const btwCommand: SlashCommand = {
);
if (abortSignal?.aborted) {
ui.setPendingItem(null);
return;
}
@ -105,25 +115,20 @@ export const btwCommand: SlashCommand = {
.join('') || t('No response received.');
// Clear pending and show the completed btw item
ui.setPendingItem(null);
ui.addItem(
{
type: MessageType.BTW,
btw: {
question,
answer,
isPending: false,
},
} as HistoryItemBtw,
Date.now(),
);
const completedItem: HistoryItemBtw = {
type: MessageType.BTW,
btw: {
question,
answer,
isPending: false,
},
};
ui.addItem(completedItem, Date.now());
} catch (error) {
if (abortSignal?.aborted) {
ui.setPendingItem(null);
return;
}
ui.setPendingItem(null);
ui.addItem(
{
type: MessageType.ERROR,
@ -133,6 +138,8 @@ export const btwCommand: SlashCommand = {
},
Date.now(),
);
} finally {
ui.setPendingItem(null);
}
},
};

View file

@ -9,6 +9,7 @@ import { Box, Text } from 'ink';
import type { BtwProps } from '../../types.js';
import Spinner from 'ink-spinner';
import { Colors } from '../../colors.js';
import { t } from '../../../i18n/index.js';
export interface BtwDisplayProps {
btw: BtwProps;
@ -19,26 +20,26 @@ export interface BtwDisplayProps {
* Shows an ephemeral question and answer that doesn't affect the main conversation.
*/
export const BtwMessage: React.FC<BtwDisplayProps> = ({ btw }) => (
<Box flexDirection="column">
<Box flexDirection="row">
<Text color={Colors.Gray} dimColor>
{'btw> '}
</Text>
<Text color={Colors.Gray}>{btw.question}</Text>
</Box>
<Box flexDirection="row" marginTop={0}>
{btw.isPending ? (
<Box>
<Box marginRight={1}>
<Spinner type="dots" />
</Box>
<Text color={Colors.AccentPurple}>Thinking...</Text>
</Box>
) : (
<Box flexDirection="column">
<Text color={Colors.AccentCyan}>{btw.answer}</Text>
</Box>
)}
</Box>
<Box flexDirection="column">
<Box flexDirection="row">
<Text color={Colors.Gray} dimColor>
{'btw> '}
</Text>
<Text color={Colors.Gray}>{btw.question}</Text>
</Box>
);
<Box flexDirection="row" marginTop={0}>
{btw.isPending ? (
<Box>
<Box marginRight={1}>
<Spinner type="dots" />
</Box>
<Text color={Colors.AccentPurple}>{t('Thinking...')}</Text>
</Box>
) : (
<Box flexDirection="column">
<Text color={Colors.AccentCyan}>{btw.answer}</Text>
</Box>
)}
</Box>
</Box>
);