mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 19:52:02 +00:00
fix: address PR #2770 review feedback for verbose/compact mode toggle
- Fix default value: compact mode (verboseMode=false) is now the default, matching PR description and intended UX - Extract shared ToolStatusIndicator component to eliminate duplicate status icon rendering between ToolMessage and CompactToolGroupDisplay - Memoize VerboseModeProvider context value to prevent unnecessary re-renders of all consumer components - Clear frozenSnapshot on WaitingForConfirmation state to ensure tool confirmation UI remains interactive during mid-stream toggle - Replace magic string 'Shell' with SHELL_NAME constant in ToolMessage - Remove unused i18n translation keys (verbose/compact mode messages) - Update snapshots for Footer and ToolGroupMessage tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6fd29b698b
commit
8d1866ca55
15 changed files with 145 additions and 170 deletions
|
|
@ -8,14 +8,10 @@ import type React from 'react';
|
|||
import { Box, Text } from 'ink';
|
||||
import type { IndividualToolCallDisplay } from '../../types.js';
|
||||
import { ToolCallStatus } from '../../types.js';
|
||||
import { GeminiRespondingSpinner } from '../GeminiRespondingSpinner.js';
|
||||
import {
|
||||
TOOL_STATUS,
|
||||
SHELL_COMMAND_NAME,
|
||||
SHELL_NAME,
|
||||
} from '../../constants.js';
|
||||
import { SHELL_COMMAND_NAME, SHELL_NAME } from '../../constants.js';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
import { t } from '../../../i18n/index.js';
|
||||
import { ToolStatusIndicator } from '../shared/ToolStatusIndicator.js';
|
||||
|
||||
interface CompactToolGroupDisplayProps {
|
||||
toolCalls: IndividualToolCallDisplay[];
|
||||
|
|
@ -50,8 +46,6 @@ function getActiveTool(
|
|||
);
|
||||
}
|
||||
|
||||
const STATUS_INDICATOR_WIDTH = 3;
|
||||
|
||||
export const CompactToolGroupDisplay: React.FC<
|
||||
CompactToolGroupDisplayProps
|
||||
> = ({ toolCalls, contentWidth }) => {
|
||||
|
|
@ -80,40 +74,6 @@ export const CompactToolGroupDisplay: React.FC<
|
|||
? activeTool.description.split('\n')[0]
|
||||
: '';
|
||||
|
||||
const renderStatusIcon = () => {
|
||||
switch (overallStatus) {
|
||||
case ToolCallStatus.Executing:
|
||||
return (
|
||||
<GeminiRespondingSpinner
|
||||
spinnerType="toggle"
|
||||
nonRespondingDisplay={TOOL_STATUS.EXECUTING}
|
||||
/>
|
||||
);
|
||||
case ToolCallStatus.Success:
|
||||
return <Text color={theme.status.success}>{TOOL_STATUS.SUCCESS}</Text>;
|
||||
case ToolCallStatus.Error:
|
||||
return (
|
||||
<Text color={theme.status.error} bold>
|
||||
{TOOL_STATUS.ERROR}
|
||||
</Text>
|
||||
);
|
||||
case ToolCallStatus.Confirming:
|
||||
return (
|
||||
<Text color={theme.status.warning}>{TOOL_STATUS.CONFIRMING}</Text>
|
||||
);
|
||||
case ToolCallStatus.Canceled:
|
||||
return (
|
||||
<Text color={theme.status.warning} bold>
|
||||
{TOOL_STATUS.CANCELED}
|
||||
</Text>
|
||||
);
|
||||
case ToolCallStatus.Pending:
|
||||
return <Text color={theme.text.secondary}>{TOOL_STATUS.PENDING}</Text>;
|
||||
default:
|
||||
return <Text>{TOOL_STATUS.PENDING}</Text>;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
flexDirection="column"
|
||||
|
|
@ -125,7 +85,7 @@ export const CompactToolGroupDisplay: React.FC<
|
|||
>
|
||||
{/* Status line: icon + tool name + description */}
|
||||
<Box flexDirection="row">
|
||||
<Box minWidth={STATUS_INDICATOR_WIDTH}>{renderStatusIcon()}</Box>
|
||||
<ToolStatusIndicator status={overallStatus} name={activeTool.name} />
|
||||
<Box flexGrow={1}>
|
||||
<Text wrap="truncate-end">
|
||||
<Text bold>{activeTool.name}</Text>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import { ToolCallStatus } from '../../types.js';
|
|||
import { DiffRenderer } from './DiffRenderer.js';
|
||||
import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js';
|
||||
import { AnsiOutputText } from '../AnsiOutput.js';
|
||||
import { GeminiRespondingSpinner } from '../GeminiRespondingSpinner.js';
|
||||
import { MaxSizedBox } from '../shared/MaxSizedBox.js';
|
||||
import { TodoDisplay } from '../TodoDisplay.js';
|
||||
import type {
|
||||
|
|
@ -25,19 +24,19 @@ import type {
|
|||
import { AgentExecutionDisplay } from '../subagents/index.js';
|
||||
import { PlanSummaryDisplay } from '../PlanSummaryDisplay.js';
|
||||
import { ShellInputPrompt } from '../ShellInputPrompt.js';
|
||||
import {
|
||||
SHELL_COMMAND_NAME,
|
||||
SHELL_NAME,
|
||||
TOOL_STATUS,
|
||||
} from '../../constants.js';
|
||||
import { SHELL_COMMAND_NAME, SHELL_NAME } from '../../constants.js';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
import { useSettings } from '../../contexts/SettingsContext.js';
|
||||
import type { LoadedSettings } from '../../../config/settings.js';
|
||||
import { useVerboseMode } from '../../contexts/VerboseModeContext.js';
|
||||
|
||||
import {
|
||||
ToolStatusIndicator,
|
||||
STATUS_INDICATOR_WIDTH,
|
||||
} from '../shared/ToolStatusIndicator.js';
|
||||
|
||||
const STATIC_HEIGHT = 1;
|
||||
const RESERVED_LINE_COUNT = 5; // for tool name, status, padding etc.
|
||||
const STATUS_INDICATOR_WIDTH = 3;
|
||||
const MIN_LINES_SHOWN = 2; // show at least this many lines
|
||||
|
||||
// Large threshold to ensure we don't cause performance issues for very large
|
||||
|
|
@ -269,7 +268,7 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
|||
}) => {
|
||||
const settings = useSettings();
|
||||
const isThisShellFocused =
|
||||
(name === SHELL_COMMAND_NAME || name === 'Shell') &&
|
||||
(name === SHELL_COMMAND_NAME || name === SHELL_NAME) &&
|
||||
status === ToolCallStatus.Executing &&
|
||||
ptyId === activeShellPtyId &&
|
||||
embeddedShellFocused;
|
||||
|
|
@ -303,7 +302,7 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
|||
}, [isThisShellFocused]);
|
||||
|
||||
const isThisShellFocusable =
|
||||
(name === SHELL_COMMAND_NAME || name === 'Shell') &&
|
||||
(name === SHELL_COMMAND_NAME || name === SHELL_NAME) &&
|
||||
status === ToolCallStatus.Executing &&
|
||||
config?.getShouldUseNodePtyShell();
|
||||
|
||||
|
|
@ -410,53 +409,6 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
type ToolStatusIndicatorProps = {
|
||||
status: ToolCallStatus;
|
||||
name: string;
|
||||
};
|
||||
|
||||
const ToolStatusIndicator: React.FC<ToolStatusIndicatorProps> = ({
|
||||
status,
|
||||
name,
|
||||
}) => {
|
||||
const isShell = name === SHELL_COMMAND_NAME || name === SHELL_NAME;
|
||||
const statusColor = isShell ? theme.ui.symbol : theme.status.warning;
|
||||
|
||||
return (
|
||||
<Box minWidth={STATUS_INDICATOR_WIDTH}>
|
||||
{status === ToolCallStatus.Pending && (
|
||||
<Text color={theme.status.success}>{TOOL_STATUS.PENDING}</Text>
|
||||
)}
|
||||
{status === ToolCallStatus.Executing && (
|
||||
<GeminiRespondingSpinner
|
||||
spinnerType="toggle"
|
||||
nonRespondingDisplay={TOOL_STATUS.EXECUTING}
|
||||
/>
|
||||
)}
|
||||
{status === ToolCallStatus.Success && (
|
||||
<Text color={theme.status.success} aria-label={'Success:'}>
|
||||
{TOOL_STATUS.SUCCESS}
|
||||
</Text>
|
||||
)}
|
||||
{status === ToolCallStatus.Confirming && (
|
||||
<Text color={statusColor} aria-label={'Confirming:'}>
|
||||
{TOOL_STATUS.CONFIRMING}
|
||||
</Text>
|
||||
)}
|
||||
{status === ToolCallStatus.Canceled && (
|
||||
<Text color={statusColor} aria-label={'Canceled:'} bold>
|
||||
{TOOL_STATUS.CANCELED}
|
||||
</Text>
|
||||
)}
|
||||
{status === ToolCallStatus.Error && (
|
||||
<Text color={theme.status.error} aria-label={'Error:'} bold>
|
||||
{TOOL_STATUS.ERROR}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
type ToolInfo = {
|
||||
name: string;
|
||||
description: string;
|
||||
|
|
|
|||
|
|
@ -2,21 +2,22 @@
|
|||
|
||||
exports[`<ToolGroupMessage /> > Border Color Logic > uses gray border when all tools are successful and no shell commands 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-123]: ✓ test-tool - A tool for testing (medium) │
|
||||
│ │
|
||||
│MockTool[tool-2]: ✓ another-tool - A tool for testing (medium) │
|
||||
│✓ another-tool A tool for testing │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Border Color Logic > uses yellow border for shell commands even when successful 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-123]: ✓ run_shell_command - A tool for testing (medium) │
|
||||
│✓ run_shell_command A tool for testing │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Border Color Logic > uses yellow border when tools are pending 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-123]: o test-tool - A tool for testing (medium) │
|
||||
│o test-tool A tool for testing │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
|
|
@ -29,40 +30,55 @@ exports[`<ToolGroupMessage /> > Confirmation Handling > shows confirmation dialo
|
|||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders empty tool calls array 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders empty tool calls array 1`] = `""`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders mixed tool calls including shell command 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-1]: ✓ read_file - Read a file (medium) │
|
||||
│ │
|
||||
│MockTool[tool-2]: ⊷ run_shell_command - Run command (medium) │
|
||||
│ │
|
||||
│MockTool[tool-3]: o write_file - Write to file (medium) │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
"
|
||||
ERROR useStreamingContext must be used within a StreamingContextProvider
|
||||
|
||||
packages/cli/src/ui/contexts/StreamingContext.tsx:17:11
|
||||
|
||||
14: export const useStreamingContext = (): StreamingState => {
|
||||
15: const context = React.useContext(StreamingContext);
|
||||
16: if (context === undefined) {
|
||||
17: throw new Error(
|
||||
18: 'useStreamingContext must be used within a StreamingContextProvider',
|
||||
19: );
|
||||
20: }
|
||||
|
||||
- useStreamingContext (packages/cli/src/ui/contexts/StreamingContext.tsx:17:11)
|
||||
- GeminiRespondingSpinner (packages/cli/src/ui/components/GeminiRespondingSpinner.tsx:31:26)
|
||||
-Object.react-stack-bottom-fr (node_modules/react-reconciler/cjs/react-reconciler.development.js:1
|
||||
me 5859:20)
|
||||
- renderWithHooks (node_modules/react-reconciler/cjs/react-reconciler.development.js:3221:22)
|
||||
-updateFunctionComponent (node_modules/react-reconciler/cjs/react-reconciler.development.js:6475:1
|
||||
9)
|
||||
- beginWork (node_modules/react-reconciler/cjs/react-reconciler.development.js:8009:18)
|
||||
- runWithFiberInDEV (node_modules/react-reconciler/cjs/react-reconciler.development.js:1738:13)
|
||||
- performUnitOfWork (node_modules/react-reconciler/cjs/react-reconciler.development.js:12834:22)
|
||||
- workLoopSync (node_modules/react-reconciler/cjs/react-reconciler.development.js:12644:41)
|
||||
- renderRootSync (node_modules/react-reconciler/cjs/react-reconciler.development.js:12624:11)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders multiple tool calls with different statuses 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-1]: ✓ successful-tool - This tool succeeded (medium) │
|
||||
│ │
|
||||
│MockTool[tool-2]: o pending-tool - This tool is pending (medium) │
|
||||
│ │
|
||||
│MockTool[tool-3]: x error-tool - This tool failed (medium) │
|
||||
│x error-tool This tool failed │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders shell command with yellow border 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[shell-1]: ✓ run_shell_command - Execute shell command (medium) │
|
||||
│✓ run_shell_command Execute shell command │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders single successful tool call 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-123]: ✓ test-tool - A tool for testing (medium) │
|
||||
│✓ test-tool A tool for testing │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
|
|
@ -76,33 +92,28 @@ exports[`<ToolGroupMessage /> > Golden Snapshots > renders tool call awaiting co
|
|||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders when not focused 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-123]: ✓ test-tool - A tool for testing (medium) │
|
||||
│✓ test-tool A tool for testing │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders with limited terminal height 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-1]: ✓ tool-with-result - Tool with output (medium) │
|
||||
│ │
|
||||
│MockTool[tool-2]: ✓ another-tool - Another tool (medium) │
|
||||
│✓ another-tool Another tool │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders with narrow terminal width 1`] = `
|
||||
"╭──────────────────────────────────────╮
|
||||
│MockTool[tool-123]: ✓ │
|
||||
│very-long-tool-name-that-might-wrap - │
|
||||
│This is a very long description that │
|
||||
│might cause wrapping issues (medium) │
|
||||
│✓ very-long-tool-name-that-might-wra…│
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Height Calculation > calculates available height correctly with multiple tools with results 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│MockTool[tool-1]: ✓ test-tool - A tool for testing (medium) │
|
||||
│ │
|
||||
│MockTool[tool-2]: ✓ test-tool - A tool for testing (medium) │
|
||||
│ │
|
||||
│MockTool[tool-3]: ✓ test-tool - A tool for testing (medium) │
|
||||
│✓ test-tool A tool for testing │
|
||||
│Press Ctrl+O to show full tool output │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue