mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-29 12:11:09 +00:00
Sync upstream Gemini-CLI v0.8.2 (#838)
This commit is contained in:
parent
096fabb5d6
commit
eb95c131be
644 changed files with 70389 additions and 23709 deletions
|
|
@ -5,9 +5,9 @@
|
|||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { DiffRenderer } from './DiffRenderer.js';
|
||||
import { Colors } from '../../colors.js';
|
||||
import { RenderInline } from '../../utils/InlineMarkdownRenderer.js';
|
||||
import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js';
|
||||
import type {
|
||||
|
|
@ -16,11 +16,12 @@ import type {
|
|||
ToolMcpConfirmationDetails,
|
||||
Config,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import { ToolConfirmationOutcome } from '@qwen-code/qwen-code-core';
|
||||
import { IdeClient, ToolConfirmationOutcome } from '@qwen-code/qwen-code-core';
|
||||
import type { RadioSelectItem } from '../shared/RadioButtonSelect.js';
|
||||
import { RadioButtonSelect } from '../shared/RadioButtonSelect.js';
|
||||
import { MaxSizedBox } from '../shared/MaxSizedBox.js';
|
||||
import { useKeypress } from '../../hooks/useKeypress.js';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
|
||||
export interface ToolConfirmationMessageProps {
|
||||
confirmationDetails: ToolCallConfirmationDetails;
|
||||
|
|
@ -44,10 +45,29 @@ export const ToolConfirmationMessage: React.FC<
|
|||
const { onConfirm } = confirmationDetails;
|
||||
const childWidth = terminalWidth - 2; // 2 for padding
|
||||
|
||||
const [ideClient, setIdeClient] = useState<IdeClient | null>(null);
|
||||
const [isDiffingEnabled, setIsDiffingEnabled] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
if (config.getIdeMode()) {
|
||||
const getIdeClient = async () => {
|
||||
const client = await IdeClient.getInstance();
|
||||
if (isMounted) {
|
||||
setIdeClient(client);
|
||||
setIsDiffingEnabled(client?.isDiffingEnabled() ?? false);
|
||||
}
|
||||
};
|
||||
getIdeClient();
|
||||
}
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
}, [config]);
|
||||
|
||||
const handleConfirm = async (outcome: ToolConfirmationOutcome) => {
|
||||
if (confirmationDetails.type === 'edit') {
|
||||
const ideClient = config.getIdeClient();
|
||||
if (config.getIdeMode()) {
|
||||
if (config.getIdeMode() && isDiffingEnabled) {
|
||||
const cliOutcome =
|
||||
outcome === ToolConfirmationOutcome.Cancel ? 'rejected' : 'accepted';
|
||||
await ideClient?.resolveDiffFromCli(
|
||||
|
|
@ -59,7 +79,7 @@ export const ToolConfirmationMessage: React.FC<
|
|||
onConfirm(outcome);
|
||||
};
|
||||
|
||||
const isTrustedFolder = config.isTrustedFolder() !== false;
|
||||
const isTrustedFolder = config.isTrustedFolder();
|
||||
|
||||
useKeypress(
|
||||
(key) => {
|
||||
|
|
@ -77,14 +97,17 @@ export const ToolConfirmationMessage: React.FC<
|
|||
if (compactMode) {
|
||||
const compactOptions: Array<RadioSelectItem<ToolConfirmationOutcome>> = [
|
||||
{
|
||||
key: 'proceed-once',
|
||||
label: 'Yes, allow once',
|
||||
value: ToolConfirmationOutcome.ProceedOnce,
|
||||
},
|
||||
{
|
||||
key: 'proceed-always',
|
||||
label: 'Allow always',
|
||||
value: ToolConfirmationOutcome.ProceedAlways,
|
||||
},
|
||||
{
|
||||
key: 'cancel',
|
||||
label: 'No',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
},
|
||||
|
|
@ -150,13 +173,13 @@ export const ToolConfirmationMessage: React.FC<
|
|||
<Box
|
||||
minWidth="90%"
|
||||
borderStyle="round"
|
||||
borderColor={Colors.Gray}
|
||||
borderColor={theme.border.default}
|
||||
justifyContent="space-around"
|
||||
padding={1}
|
||||
overflow="hidden"
|
||||
>
|
||||
<Text>Modify in progress: </Text>
|
||||
<Text color={Colors.AccentGreen}>
|
||||
<Text color={theme.text.primary}>Modify in progress: </Text>
|
||||
<Text color={theme.status.success}>
|
||||
Save and close external editor to continue
|
||||
</Text>
|
||||
</Box>
|
||||
|
|
@ -167,29 +190,29 @@ export const ToolConfirmationMessage: React.FC<
|
|||
options.push({
|
||||
label: 'Yes, allow once',
|
||||
value: ToolConfirmationOutcome.ProceedOnce,
|
||||
key: 'Yes, allow once',
|
||||
});
|
||||
if (isTrustedFolder) {
|
||||
options.push({
|
||||
label: 'Yes, allow always',
|
||||
value: ToolConfirmationOutcome.ProceedAlways,
|
||||
key: 'Yes, allow always',
|
||||
});
|
||||
}
|
||||
if (config.getIdeMode()) {
|
||||
options.push({
|
||||
label: 'No (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
});
|
||||
} else {
|
||||
if (!config.getIdeMode() || !isDiffingEnabled) {
|
||||
options.push({
|
||||
label: 'Modify with external editor',
|
||||
value: ToolConfirmationOutcome.ModifyWithEditor,
|
||||
});
|
||||
options.push({
|
||||
label: 'No, suggest changes (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
key: 'Modify with external editor',
|
||||
});
|
||||
}
|
||||
|
||||
options.push({
|
||||
label: 'No, suggest changes (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
key: 'No, suggest changes (esc)',
|
||||
});
|
||||
|
||||
bodyContent = (
|
||||
<DiffRenderer
|
||||
diffContent={confirmationDetails.fileDiff}
|
||||
|
|
@ -206,16 +229,19 @@ export const ToolConfirmationMessage: React.FC<
|
|||
options.push({
|
||||
label: 'Yes, allow once',
|
||||
value: ToolConfirmationOutcome.ProceedOnce,
|
||||
key: 'Yes, allow once',
|
||||
});
|
||||
if (isTrustedFolder) {
|
||||
options.push({
|
||||
label: `Yes, allow always ...`,
|
||||
value: ToolConfirmationOutcome.ProceedAlways,
|
||||
key: `Yes, allow always ...`,
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
label: 'No, suggest changes (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
key: 'No, suggest changes (esc)',
|
||||
});
|
||||
|
||||
let bodyContentHeight = availableBodyContentHeight();
|
||||
|
|
@ -230,7 +256,7 @@ export const ToolConfirmationMessage: React.FC<
|
|||
maxWidth={Math.max(childWidth - 4, 1)}
|
||||
>
|
||||
<Box>
|
||||
<Text color={Colors.AccentCyan}>{executionProps.command}</Text>
|
||||
<Text color={theme.text.link}>{executionProps.command}</Text>
|
||||
</Box>
|
||||
</MaxSizedBox>
|
||||
</Box>
|
||||
|
|
@ -241,14 +267,17 @@ export const ToolConfirmationMessage: React.FC<
|
|||
|
||||
question = planProps.title;
|
||||
options.push({
|
||||
key: 'proceed-always',
|
||||
label: 'Yes, and auto-accept edits',
|
||||
value: ToolConfirmationOutcome.ProceedAlways,
|
||||
});
|
||||
options.push({
|
||||
key: 'proceed-once',
|
||||
label: 'Yes, and manually approve edits',
|
||||
value: ToolConfirmationOutcome.ProceedOnce,
|
||||
});
|
||||
options.push({
|
||||
key: 'cancel',
|
||||
label: 'No, keep planning (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
});
|
||||
|
|
@ -273,26 +302,29 @@ export const ToolConfirmationMessage: React.FC<
|
|||
options.push({
|
||||
label: 'Yes, allow once',
|
||||
value: ToolConfirmationOutcome.ProceedOnce,
|
||||
key: 'Yes, allow once',
|
||||
});
|
||||
if (isTrustedFolder) {
|
||||
options.push({
|
||||
label: 'Yes, allow always',
|
||||
value: ToolConfirmationOutcome.ProceedAlways,
|
||||
key: 'Yes, allow always',
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
label: 'No, suggest changes (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
key: 'No, suggest changes (esc)',
|
||||
});
|
||||
|
||||
bodyContent = (
|
||||
<Box flexDirection="column" paddingX={1} marginLeft={1}>
|
||||
<Text color={Colors.AccentCyan}>
|
||||
<Text color={theme.text.link}>
|
||||
<RenderInline text={infoProps.prompt} />
|
||||
</Text>
|
||||
{displayUrls && infoProps.urls && infoProps.urls.length > 0 && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text>URLs to fetch:</Text>
|
||||
<Text color={theme.text.primary}>URLs to fetch:</Text>
|
||||
{infoProps.urls.map((url) => (
|
||||
<Text key={url}>
|
||||
{' '}
|
||||
|
|
@ -309,8 +341,8 @@ export const ToolConfirmationMessage: React.FC<
|
|||
|
||||
bodyContent = (
|
||||
<Box flexDirection="column" paddingX={1} marginLeft={1}>
|
||||
<Text color={Colors.AccentCyan}>MCP Server: {mcpProps.serverName}</Text>
|
||||
<Text color={Colors.AccentCyan}>Tool: {mcpProps.toolName}</Text>
|
||||
<Text color={theme.text.link}>MCP Server: {mcpProps.serverName}</Text>
|
||||
<Text color={theme.text.link}>Tool: {mcpProps.toolName}</Text>
|
||||
</Box>
|
||||
);
|
||||
|
||||
|
|
@ -318,20 +350,24 @@ export const ToolConfirmationMessage: React.FC<
|
|||
options.push({
|
||||
label: 'Yes, allow once',
|
||||
value: ToolConfirmationOutcome.ProceedOnce,
|
||||
key: 'Yes, allow once',
|
||||
});
|
||||
if (isTrustedFolder) {
|
||||
options.push({
|
||||
label: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`,
|
||||
value: ToolConfirmationOutcome.ProceedAlwaysTool, // Cast until types are updated
|
||||
key: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`,
|
||||
});
|
||||
options.push({
|
||||
label: `Yes, always allow all tools from server "${mcpProps.serverName}"`,
|
||||
value: ToolConfirmationOutcome.ProceedAlwaysServer,
|
||||
key: `Yes, always allow all tools from server "${mcpProps.serverName}"`,
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
label: 'No, suggest changes (esc)',
|
||||
value: ToolConfirmationOutcome.Cancel,
|
||||
key: 'No, suggest changes (esc)',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +381,9 @@ export const ToolConfirmationMessage: React.FC<
|
|||
|
||||
{/* Confirmation Question */}
|
||||
<Box marginBottom={1} flexShrink={0}>
|
||||
<Text wrap="truncate">{question}</Text>
|
||||
<Text color={theme.text.primary} wrap="truncate">
|
||||
{question}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Select Input for Options */}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue