mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-30 20:50:34 +00:00
feat(cli): add Coding Plan Global/Intl region support
Add support for Coding Plan international region with separate base URL: - Add CodingPlanRegion enum (CHINA, GLOBAL) for region management - Add CODING_PLAN_INTL_MODELS template with intl base URL - Add version storage for both regions (codingPlan.version/versionIntl) - Update AuthDialog to show both region options - Update useCodingPlanUpdates to handle region-specific updates - Add i18n translations for all supported languages - Fix and update unit tests Users can now choose between: - Coding Plan (Bailian, China) - https://coding.dashscope.aliyuncs.com/v1 - Coding Plan (Bailian, Global/Intl) - https://coding-intl.dashscope.aliyuncs.com/v1 Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
a0a0a70b12
commit
39360dc058
13 changed files with 684 additions and 219 deletions
|
|
@ -17,6 +17,7 @@ import { useUIState } from '../contexts/UIStateContext.js';
|
|||
import { useUIActions } from '../contexts/UIActionsContext.js';
|
||||
import { useConfig } from '../contexts/ConfigContext.js';
|
||||
import { t } from '../../i18n/index.js';
|
||||
import { CodingPlanRegion } from '../../constants/codingPlan.js';
|
||||
|
||||
const MODEL_PROVIDERS_DOCUMENTATION_URL =
|
||||
'https://qwenlm.github.io/qwen-code-docs/en/users/configuration/settings/#modelproviders';
|
||||
|
|
@ -34,7 +35,7 @@ function parseDefaultAuthType(
|
|||
}
|
||||
|
||||
// Sub-mode types for API-KEY authentication
|
||||
type ApiKeySubMode = 'coding-plan' | 'custom';
|
||||
type ApiKeySubMode = 'coding-plan' | 'coding-plan-intl' | 'custom';
|
||||
|
||||
// View level for navigation
|
||||
type ViewLevel = 'main' | 'api-key-sub' | 'api-key-input' | 'custom-info';
|
||||
|
|
@ -52,6 +53,9 @@ export function AuthDialog(): React.JSX.Element {
|
|||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||
const [viewLevel, setViewLevel] = useState<ViewLevel>('main');
|
||||
const [apiKeySubModeIndex, setApiKeySubModeIndex] = useState<number>(0);
|
||||
const [region, setRegion] = useState<CodingPlanRegion>(
|
||||
CodingPlanRegion.CHINA,
|
||||
);
|
||||
|
||||
// Main authentication entries
|
||||
const mainItems = [
|
||||
|
|
@ -71,9 +75,14 @@ export function AuthDialog(): React.JSX.Element {
|
|||
const apiKeySubItems = [
|
||||
{
|
||||
key: 'coding-plan',
|
||||
label: t('Coding Plan (Bailian)'),
|
||||
label: t('Coding Plan (Bailian, China)'),
|
||||
value: 'coding-plan' as ApiKeySubMode,
|
||||
},
|
||||
{
|
||||
key: 'coding-plan-intl',
|
||||
label: t('Coding Plan (Bailian, Global/Intl)'),
|
||||
value: 'coding-plan-intl' as ApiKeySubMode,
|
||||
},
|
||||
{
|
||||
key: 'custom',
|
||||
label: t('Custom'),
|
||||
|
|
@ -135,6 +144,10 @@ export function AuthDialog(): React.JSX.Element {
|
|||
onAuthError(null);
|
||||
|
||||
if (subMode === 'coding-plan') {
|
||||
setRegion(CodingPlanRegion.CHINA);
|
||||
setViewLevel('api-key-input');
|
||||
} else if (subMode === 'coding-plan-intl') {
|
||||
setRegion(CodingPlanRegion.GLOBAL);
|
||||
setViewLevel('api-key-input');
|
||||
} else {
|
||||
setViewLevel('custom-info');
|
||||
|
|
@ -149,8 +162,8 @@ export function AuthDialog(): React.JSX.Element {
|
|||
return;
|
||||
}
|
||||
|
||||
// Submit to parent for processing
|
||||
await handleCodingPlanSubmit(apiKey);
|
||||
// Submit to parent for processing with region info
|
||||
await handleCodingPlanSubmit(apiKey, region);
|
||||
};
|
||||
|
||||
const handleGoBack = () => {
|
||||
|
|
@ -264,7 +277,11 @@ export function AuthDialog(): React.JSX.Element {
|
|||
// Render API key input for coding-plan mode
|
||||
const renderApiKeyInputView = () => (
|
||||
<Box marginTop={1}>
|
||||
<ApiKeyInput onSubmit={handleApiKeyInputSubmit} onCancel={handleGoBack} />
|
||||
<ApiKeyInput
|
||||
onSubmit={handleApiKeyInputSubmit}
|
||||
onCancel={handleGoBack}
|
||||
region={region}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ import { AuthState, MessageType } from '../types.js';
|
|||
import type { HistoryItem } from '../types.js';
|
||||
import { t } from '../../i18n/index.js';
|
||||
import {
|
||||
CODING_PLAN_MODELS,
|
||||
CODING_PLAN_ENV_KEY,
|
||||
CODING_PLAN_VERSION,
|
||||
getCodingPlanConfig,
|
||||
isCodingPlanConfig,
|
||||
CodingPlanRegion,
|
||||
} from '../../constants/codingPlan.js';
|
||||
|
||||
export type { QwenAuthState } from '../hooks/useQwenAuth.js';
|
||||
|
|
@ -285,29 +285,36 @@ export const useAuthCommand = (
|
|||
|
||||
/**
|
||||
* Handle coding plan submission - generates configs from template and stores api-key
|
||||
* @param apiKey - The API key to store
|
||||
* @param region - The region to use (default: CHINA)
|
||||
*/
|
||||
const handleCodingPlanSubmit = useCallback(
|
||||
async (apiKey: string) => {
|
||||
async (
|
||||
apiKey: string,
|
||||
region: CodingPlanRegion = CodingPlanRegion.CHINA,
|
||||
) => {
|
||||
try {
|
||||
setIsAuthenticating(true);
|
||||
setAuthError(null);
|
||||
|
||||
const envKeyName = CODING_PLAN_ENV_KEY;
|
||||
// Get configuration based on region
|
||||
const codingPlanConfig = getCodingPlanConfig(region);
|
||||
const { template, envKey, version } = codingPlanConfig;
|
||||
|
||||
// Get persist scope
|
||||
const persistScope = getPersistScopeForModelSelection(settings);
|
||||
|
||||
// Store api-key in settings.env
|
||||
settings.setValue(persistScope, `env.${envKeyName}`, apiKey);
|
||||
settings.setValue(persistScope, `env.${envKey}`, apiKey);
|
||||
|
||||
// Sync to process.env immediately so refreshAuth can read the apiKey
|
||||
process.env[envKeyName] = apiKey;
|
||||
process.env[envKey] = apiKey;
|
||||
|
||||
// Generate model configs from template
|
||||
const newConfigs: ProviderModelConfig[] = CODING_PLAN_MODELS.map(
|
||||
const newConfigs: ProviderModelConfig[] = template.map(
|
||||
(templateConfig) => ({
|
||||
...templateConfig,
|
||||
envKey: envKeyName,
|
||||
envKey,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -317,17 +324,14 @@ export const useAuthCommand = (
|
|||
settings.merged.modelProviders as ModelProvidersConfig | undefined
|
||||
)?.[AuthType.USE_OPENAI] || [];
|
||||
|
||||
// Identify Coding Plan configs by baseUrl + envKey
|
||||
// Identify Coding Plan configs by baseUrl + envKey for the given region
|
||||
// Remove existing Coding Plan configs to ensure template changes are applied
|
||||
const isCodingPlanConfig = (config: ProviderModelConfig) =>
|
||||
config.envKey === envKeyName &&
|
||||
CODING_PLAN_MODELS.some(
|
||||
(template) => template.baseUrl === config.baseUrl,
|
||||
);
|
||||
const checkIsCodingPlanConfig = (config: ProviderModelConfig) =>
|
||||
isCodingPlanConfig(config.baseUrl, config.envKey, region);
|
||||
|
||||
// Filter out existing Coding Plan configs, keep user custom configs
|
||||
// Filter out existing Coding Plan configs for this region, keep user custom configs
|
||||
const nonCodingPlanConfigs = existingConfigs.filter(
|
||||
(existing) => !isCodingPlanConfig(existing),
|
||||
(existing) => !checkIsCodingPlanConfig(existing),
|
||||
);
|
||||
|
||||
// Add new Coding Plan configs at the beginning
|
||||
|
|
@ -348,11 +352,12 @@ export const useAuthCommand = (
|
|||
);
|
||||
|
||||
// Persist coding plan version for future update detection
|
||||
settings.setValue(
|
||||
persistScope,
|
||||
'codingPlan.version',
|
||||
CODING_PLAN_VERSION,
|
||||
);
|
||||
// Store version with region suffix to distinguish between China and Intl versions
|
||||
const versionKey =
|
||||
region === CodingPlanRegion.GLOBAL
|
||||
? 'codingPlan.versionIntl'
|
||||
: 'codingPlan.version';
|
||||
settings.setValue(persistScope, versionKey, version);
|
||||
|
||||
// If there are configs, use the first one as the model
|
||||
if (updatedConfigs.length > 0 && updatedConfigs[0]?.id) {
|
||||
|
|
@ -382,11 +387,16 @@ export const useAuthCommand = (
|
|||
onAuthChange?.();
|
||||
|
||||
// Add success message
|
||||
const regionLabel =
|
||||
region === CodingPlanRegion.GLOBAL
|
||||
? 'Coding Plan (Global/Intl)'
|
||||
: 'Coding Plan';
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
text: t(
|
||||
'Authenticated successfully with Coding Plan. API key is stored in settings.env.',
|
||||
'Authenticated successfully with {{region}}. API key is stored in settings.env.',
|
||||
{ region: regionLabel },
|
||||
),
|
||||
},
|
||||
Date.now(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue