qwen-code/packages/cli/src/ui/components/ApiKeyInput.tsx
tanzhenxin fa5bd26b68 fix(auth): validate Coding Plan API key prefix for China region
- Add validation to check API key starts with "sk-sp-" for China region
- Add Chinese translation for the validation error message
- Only apply prefix validation when region is aliyun.com (China)

This prevents users from submitting invalid API keys for the China region, providing immediate feedback with a localized error message.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-02 21:19:41 +08:00

95 lines
2.6 KiB
TypeScript

/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/
import type React from 'react';
import { useState } from 'react';
import { Box, Text } from 'ink';
import { TextInput } from './shared/TextInput.js';
import { theme } from '../semantic-colors.js';
import { useKeypress } from '../hooks/useKeypress.js';
import { t } from '../../i18n/index.js';
import { CodingPlanRegion } from '../../constants/codingPlan.js';
import Link from 'ink-link';
interface ApiKeyInputProps {
onSubmit: (apiKey: string) => void;
onCancel: () => void;
region?: CodingPlanRegion;
}
const CODING_PLAN_API_KEY_URL =
'https://bailian.console.aliyun.com/?tab=model#/efm/coding_plan';
const CODING_PLAN_INTL_API_KEY_URL =
'https://modelstudio.console.alibabacloud.com/?tab=dashboard#/efm/coding_plan';
export function ApiKeyInput({
onSubmit,
onCancel,
region = CodingPlanRegion.CHINA,
}: ApiKeyInputProps): React.JSX.Element {
const [apiKey, setApiKey] = useState('');
const [error, setError] = useState<string | null>(null);
const apiKeyUrl =
region === CodingPlanRegion.GLOBAL
? CODING_PLAN_INTL_API_KEY_URL
: CODING_PLAN_API_KEY_URL;
useKeypress(
(key) => {
if (key.name === 'escape') {
onCancel();
} else if (key.name === 'return') {
const trimmedKey = apiKey.trim();
if (!trimmedKey) {
setError(t('API key cannot be empty.'));
return;
}
// Only validate sk-sp- prefix for China region (aliyun.com)
if (
region === CodingPlanRegion.CHINA &&
!trimmedKey.startsWith('sk-sp-')
) {
setError(
t(
'Invalid API key. Coding Plan API keys start with "sk-sp-". Please check.',
),
);
return;
}
onSubmit(trimmedKey);
}
},
{ isActive: true },
);
return (
<Box flexDirection="column">
<TextInput value={apiKey} onChange={setApiKey} placeholder="sk-sp-..." />
{error && (
<Box marginTop={1}>
<Text color={theme.status.error}>{error}</Text>
</Box>
)}
<Box marginTop={1}>
<Text>{t('You can get your Coding Plan API key here')}</Text>
</Box>
<Box marginTop={0}>
<Link url={apiKeyUrl} fallback={false}>
<Text color={theme.text.link} underline>
{apiKeyUrl}
</Text>
</Link>
</Box>
<Box marginTop={1}>
<Text color={theme.text.secondary}>
{t('Enter to submit, Esc to go back')}
</Text>
</Box>
</Box>
);
}