Merge remote-tracking branch 'origin/main' into feat/review-skill-improvements

This commit is contained in:
wenshao 2026-04-09 08:52:01 +08:00
commit 6de5c9e530
20 changed files with 705 additions and 48 deletions

View file

@ -235,6 +235,10 @@ describe('InputPrompt', () => {
await wait();
expect(props.onSubmit).toHaveBeenCalledWith('commit this');
// Enter path must NOT call buffer.insert — it passes text directly to
// handleSubmitAndClear. Calling insert would re-fill the buffer after
// it was already cleared (the microtask race bug).
expect(mockBuffer.insert).not.toHaveBeenCalled();
unmount();
});

View file

@ -882,7 +882,11 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
followup.state.suggestion
) {
const text = followup.state.suggestion;
followup.accept('enter');
// Skip onAccept (buffer.insert) — we pass the text directly to
// handleSubmitAndClear which clears the buffer synchronously.
// Without skipOnAccept the microtask in accept() would re-insert
// the suggestion into the buffer after it was already cleared.
followup.accept('enter', { skipOnAccept: true });
handleSubmitAndClear(text);
return true;
}

View file

@ -43,7 +43,10 @@ export interface UseFollowupSuggestionsReturn {
/** Set suggestion text (called by parent component) */
setSuggestion: (text: string | null) => void;
/** Accept the current suggestion */
accept: (method?: 'tab' | 'enter' | 'right') => void;
accept: (
method?: 'tab' | 'enter' | 'right',
options?: { skipOnAccept?: boolean },
) => void;
/** Dismiss the current suggestion */
dismiss: () => void;
/** Clear all state */

View file

@ -111,7 +111,9 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({
lines[index + 1].match(tableSeparatorRegex)
) {
inTable = true;
tableHeaders = tableRowMatch[1].split(/(?<!\\)\|/).map((cell) => cell.trim().replaceAll('\\|', '|'));
tableHeaders = tableRowMatch[1]
.split(/(?<!\\)\|/)
.map((cell) => cell.trim().replaceAll('\\|', '|'));
tableRows = [];
} else {
// Not a table, treat as regular text
@ -127,7 +129,9 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({
// Skip separator line - already handled
} else if (inTable && tableRowMatch) {
// Add table row
const cells = tableRowMatch[1].split(/(?<!\\)\|/).map((cell) => cell.trim().replaceAll('\\|', '|'));
const cells = tableRowMatch[1]
.split(/(?<!\\)\|/)
.map((cell) => cell.trim().replaceAll('\\|', '|'));
// Ensure row has same column count as headers
while (cells.length < tableHeaders.length) {
cells.push('');

View file

@ -36,7 +36,10 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
// Ensure table fits within terminal width
const totalWidth = columnWidths.reduce((sum, width) => sum + width + 1, 1);
const fixedWidth = columnWidths.length + 1;
const scaleFactor = totalWidth > contentWidth ? (contentWidth - fixedWidth) / (totalWidth - fixedWidth) : 1;
const scaleFactor =
totalWidth > contentWidth
? (contentWidth - fixedWidth) / (totalWidth - fixedWidth)
: 1;
const adjustedWidths = columnWidths.map((width) =>
Math.floor(width * scaleFactor),
);