mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
fix(cli): add "API Key" option to qwen auth interactive menu
The `qwen auth` CLI command only showed 2 options (Coding Plan, Qwen OAuth), while the interactive `/auth` dialog showed 3 (Coding Plan, API Key, Qwen OAuth). Users following the README instructions to configure OpenRouter/Fireworks via `qwen auth` had no API Key entry point. - Add "API Key" option to the `runInteractiveAuth` menu with two sub-paths: "Alibaba Cloud ModelStudio Standard API Key" (guided flow) and "Custom API Key" (prints docs link) - Add `qwen auth api-key` yargs subcommand for direct access - Extract `createMinimalArgv` / `loadAuthConfig` helpers to eliminate duplicated CliArgs boilerplate - Extract `promptForInput` to share raw-mode stdin logic between `promptForKey` and `promptForModelIds` - Improve `showAuthStatus` to distinguish Coding Plan, Standard API Key, and generic OpenAI-compatible configurations - Align menu labels and descriptions with the interactive `/auth` dialog Closes #3413 Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
83d1e6dcae
commit
0d5221490d
2 changed files with 355 additions and 83 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
import type { CommandModule, Argv } from 'yargs';
|
import type { CommandModule, Argv } from 'yargs';
|
||||||
import {
|
import {
|
||||||
handleQwenAuth,
|
handleQwenAuth,
|
||||||
|
handleApiKeyAuth,
|
||||||
runInteractiveAuth,
|
runInteractiveAuth,
|
||||||
showAuthStatus,
|
showAuthStatus,
|
||||||
} from './auth/handler.js';
|
} from './auth/handler.js';
|
||||||
|
|
@ -50,6 +51,14 @@ const codePlanCommand = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const apiKeyCommand = {
|
||||||
|
command: 'api-key',
|
||||||
|
describe: t('Authenticate using an API key'),
|
||||||
|
handler: async () => {
|
||||||
|
await handleApiKeyAuth();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const statusCommand = {
|
const statusCommand = {
|
||||||
command: 'status',
|
command: 'status',
|
||||||
describe: t('Show current authentication status'),
|
describe: t('Show current authentication status'),
|
||||||
|
|
@ -61,12 +70,13 @@ const statusCommand = {
|
||||||
export const authCommand: CommandModule = {
|
export const authCommand: CommandModule = {
|
||||||
command: 'auth',
|
command: 'auth',
|
||||||
describe: t(
|
describe: t(
|
||||||
'Configure Qwen authentication information with Qwen-OAuth or Alibaba Cloud Coding Plan',
|
'Configure Qwen authentication with Coding Plan, API Key, or Qwen-OAuth',
|
||||||
),
|
),
|
||||||
builder: (yargs: Argv) =>
|
builder: (yargs: Argv) =>
|
||||||
yargs
|
yargs
|
||||||
.command(qwenOauthCommand)
|
.command(qwenOauthCommand)
|
||||||
.command(codePlanCommand)
|
.command(codePlanCommand)
|
||||||
|
.command(apiKeyCommand)
|
||||||
.command(statusCommand)
|
.command(statusCommand)
|
||||||
.demandCommand(0) // Don't require a subcommand
|
.demandCommand(0) // Don't require a subcommand
|
||||||
.version(false),
|
.version(false),
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@ import { loadSettings, type LoadedSettings } from '../../config/settings.js';
|
||||||
import { loadCliConfig } from '../../config/config.js';
|
import { loadCliConfig } from '../../config/config.js';
|
||||||
import type { CliArgs } from '../../config/config.js';
|
import type { CliArgs } from '../../config/config.js';
|
||||||
import { InteractiveSelector } from './interactiveSelector.js';
|
import { InteractiveSelector } from './interactiveSelector.js';
|
||||||
|
import {
|
||||||
|
ALIBABA_STANDARD_API_KEY_ENDPOINTS,
|
||||||
|
DASHSCOPE_STANDARD_API_KEY_ENV_KEY,
|
||||||
|
type AlibabaStandardRegion,
|
||||||
|
} from '../../constants/alibabaStandardApiKey.js';
|
||||||
|
|
||||||
interface QwenAuthOptions {
|
interface QwenAuthOptions {
|
||||||
region?: string;
|
region?: string;
|
||||||
|
|
@ -50,17 +55,10 @@ interface MergedSettingsWithCodingPlan {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the authentication process based on the specified command and options
|
* Creates a minimal CliArgs for auth command config loading
|
||||||
*/
|
*/
|
||||||
export async function handleQwenAuth(
|
function createMinimalArgv(): CliArgs {
|
||||||
command: 'qwen-oauth' | 'coding-plan',
|
return {
|
||||||
options: QwenAuthOptions,
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
const settings = loadSettings();
|
|
||||||
|
|
||||||
// Create a minimal argv for config loading
|
|
||||||
const minimalArgv: CliArgs = {
|
|
||||||
query: undefined,
|
query: undefined,
|
||||||
model: undefined,
|
model: undefined,
|
||||||
sandbox: undefined,
|
sandbox: undefined,
|
||||||
|
|
@ -108,19 +106,34 @@ export async function handleQwenAuth(
|
||||||
systemPrompt: undefined,
|
systemPrompt: undefined,
|
||||||
appendSystemPrompt: undefined,
|
appendSystemPrompt: undefined,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Create a minimal config to access settings and storage
|
/**
|
||||||
const config = await loadCliConfig(
|
* Loads settings and config for auth commands
|
||||||
|
*/
|
||||||
|
async function loadAuthConfig(settings: LoadedSettings) {
|
||||||
|
return loadCliConfig(
|
||||||
settings.merged,
|
settings.merged,
|
||||||
minimalArgv,
|
createMinimalArgv(),
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
[], // No extensions for auth command
|
[],
|
||||||
// Pass separated hooks for proper source attribution
|
|
||||||
{
|
{
|
||||||
userHooks: settings.getUserHooks(),
|
userHooks: settings.getUserHooks(),
|
||||||
projectHooks: settings.getProjectHooks(),
|
projectHooks: settings.getProjectHooks(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the authentication process based on the specified command and options
|
||||||
|
*/
|
||||||
|
export async function handleQwenAuth(
|
||||||
|
command: 'qwen-oauth' | 'coding-plan',
|
||||||
|
options: QwenAuthOptions,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const settings = loadSettings();
|
||||||
|
const config = await loadAuthConfig(settings);
|
||||||
|
|
||||||
if (command === 'qwen-oauth') {
|
if (command === 'qwen-oauth') {
|
||||||
await handleQwenOAuth(config, settings);
|
await handleQwenOAuth(config, settings);
|
||||||
|
|
@ -303,16 +316,21 @@ async function promptForRegion(): Promise<CodingPlanRegion> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompts the user to enter an API key
|
* Generic raw-mode text input prompt.
|
||||||
|
* @param promptText - Text displayed before the cursor
|
||||||
|
* @param options.mask - If true, echoes '*' instead of the typed character (for passwords)
|
||||||
|
* @param options.defaultValue - Value returned when the user presses Enter on empty input
|
||||||
*/
|
*/
|
||||||
async function promptForKey(): Promise<string> {
|
async function promptForInput(
|
||||||
// Create a simple password-style input (without echoing characters)
|
promptText: string,
|
||||||
|
options: { mask?: boolean; defaultValue?: string } = {},
|
||||||
|
): Promise<string> {
|
||||||
|
const { mask = false, defaultValue } = options;
|
||||||
const stdin = process.stdin;
|
const stdin = process.stdin;
|
||||||
const stdout = process.stdout;
|
const stdout = process.stdout;
|
||||||
|
|
||||||
stdout.write(t('Enter your Coding Plan API key: '));
|
stdout.write(promptText);
|
||||||
|
|
||||||
// Set raw mode to capture keystrokes
|
|
||||||
const wasRaw = stdin.isRaw;
|
const wasRaw = stdin.isRaw;
|
||||||
if (stdin.setRawMode) {
|
if (stdin.setRawMode) {
|
||||||
stdin.setRawMode(true);
|
stdin.setRawMode(true);
|
||||||
|
|
@ -331,8 +349,10 @@ async function promptForKey(): Promise<string> {
|
||||||
if (stdin.setRawMode) {
|
if (stdin.setRawMode) {
|
||||||
stdin.setRawMode(wasRaw);
|
stdin.setRawMode(wasRaw);
|
||||||
}
|
}
|
||||||
stdout.write('\n'); // New line after input
|
stdout.write('\n');
|
||||||
resolve(input);
|
resolve(
|
||||||
|
defaultValue !== undefined && !input ? defaultValue : input,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
case '\x03': // Ctrl+C
|
case '\x03': // Ctrl+C
|
||||||
stdin.removeListener('data', onData);
|
stdin.removeListener('data', onData);
|
||||||
|
|
@ -351,10 +371,8 @@ async function promptForKey(): Promise<string> {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Add character to input
|
|
||||||
input += char;
|
input += char;
|
||||||
// Print asterisk instead of the actual character for security
|
stdout.write(mask ? '*' : char);
|
||||||
stdout.write('*');
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -364,6 +382,15 @@ async function promptForKey(): Promise<string> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts the user to enter an API key (masked input)
|
||||||
|
*/
|
||||||
|
async function promptForKey(
|
||||||
|
promptText: string = t('Enter your Coding Plan API key: '),
|
||||||
|
): Promise<string> {
|
||||||
|
return promptForInput(promptText, { mask: true });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the interactive authentication flow
|
* Runs the interactive authentication flow
|
||||||
*/
|
*/
|
||||||
|
|
@ -377,6 +404,11 @@ export async function runInteractiveAuth() {
|
||||||
'Paid · Up to 6,000 requests/5 hrs · All Alibaba Cloud Coding Plan Models',
|
'Paid · Up to 6,000 requests/5 hrs · All Alibaba Cloud Coding Plan Models',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'api-key' as const,
|
||||||
|
label: t('API Key'),
|
||||||
|
description: t('Bring your own API key'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'qwen-oauth' as const,
|
value: 'qwen-oauth' as const,
|
||||||
label: t('Qwen OAuth'),
|
label: t('Qwen OAuth'),
|
||||||
|
|
@ -400,9 +432,217 @@ export async function runInteractiveAuth() {
|
||||||
|
|
||||||
if (choice === 'coding-plan') {
|
if (choice === 'coding-plan') {
|
||||||
await handleQwenAuth('coding-plan', {});
|
await handleQwenAuth('coding-plan', {});
|
||||||
|
} else if (choice === 'api-key') {
|
||||||
|
await handleApiKeyAuth();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles API Key authentication - shows sub-menu for Standard or Custom API key
|
||||||
|
*/
|
||||||
|
export async function handleApiKeyAuth() {
|
||||||
|
try {
|
||||||
|
const selector = new InteractiveSelector(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value: 'alibaba-standard' as const,
|
||||||
|
label: t('Alibaba Cloud ModelStudio Standard API Key'),
|
||||||
|
description: t('Quick setup for Model Studio (China/International)'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'custom' as const,
|
||||||
|
label: t('Custom API Key'),
|
||||||
|
description: t(
|
||||||
|
'For other OpenAI / Anthropic / Gemini-compatible providers',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
t('Select API key type:'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const choice = await selector.select();
|
||||||
|
|
||||||
|
if (choice === 'alibaba-standard') {
|
||||||
|
await handleAlibabaStandardApiKeyAuth();
|
||||||
|
} else if (choice === 'custom') {
|
||||||
|
handleCustomApiKeyAuth();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
writeStderrLine(getErrorMessage(error));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Alibaba Cloud ModelStudio Standard API Key authentication
|
||||||
|
*/
|
||||||
|
async function handleAlibabaStandardApiKeyAuth(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const settings = loadSettings();
|
||||||
|
const config = await loadAuthConfig(settings);
|
||||||
|
|
||||||
|
// Step 1: Select region
|
||||||
|
const region = await promptForStandardRegion();
|
||||||
|
|
||||||
|
// Step 2: Enter API key
|
||||||
|
const apiKey = await promptForKey(t('Enter your API key: '));
|
||||||
|
const trimmedApiKey = apiKey.trim();
|
||||||
|
if (!trimmedApiKey) {
|
||||||
|
writeStderrLine(t('API key cannot be empty.'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Enter model IDs
|
||||||
|
const modelIdsInput = await promptForModelIds();
|
||||||
|
const modelIds = modelIdsInput
|
||||||
|
.split(',')
|
||||||
|
.map((id) => id.trim())
|
||||||
|
.filter(
|
||||||
|
(id, index, array) => id.length > 0 && array.indexOf(id) === index,
|
||||||
|
);
|
||||||
|
if (modelIds.length === 0) {
|
||||||
|
writeStderrLine(t('Model IDs cannot be empty.'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeStdoutLine(
|
||||||
|
t('Processing Alibaba Cloud ModelStudio Standard API Key...'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Persist settings
|
||||||
|
const baseUrl = ALIBABA_STANDARD_API_KEY_ENDPOINTS[region];
|
||||||
|
const persistScope = getPersistScopeForModelSelection(settings);
|
||||||
|
const settingsFile = settings.forScope(persistScope);
|
||||||
|
backupSettingsFile(settingsFile.path);
|
||||||
|
|
||||||
|
// Store API key
|
||||||
|
settings.setValue(
|
||||||
|
persistScope,
|
||||||
|
`env.${DASHSCOPE_STANDARD_API_KEY_ENV_KEY}`,
|
||||||
|
trimmedApiKey,
|
||||||
|
);
|
||||||
|
process.env[DASHSCOPE_STANDARD_API_KEY_ENV_KEY] = trimmedApiKey;
|
||||||
|
|
||||||
|
// Build model configs
|
||||||
|
const newConfigs: ModelConfig[] = modelIds.map((modelId) => ({
|
||||||
|
id: modelId,
|
||||||
|
name: `[ModelStudio Standard] ${modelId}`,
|
||||||
|
baseUrl,
|
||||||
|
envKey: DASHSCOPE_STANDARD_API_KEY_ENV_KEY,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Get existing configs and filter out old Alibaba Standard entries
|
||||||
|
const existingConfigs =
|
||||||
|
(settings.merged.modelProviders as Record<string, ModelConfig[]>)?.[
|
||||||
|
AuthType.USE_OPENAI
|
||||||
|
] || [];
|
||||||
|
|
||||||
|
const nonAlibabaStandardConfigs = existingConfigs.filter(
|
||||||
|
(existing) =>
|
||||||
|
!(
|
||||||
|
existing.envKey === DASHSCOPE_STANDARD_API_KEY_ENV_KEY &&
|
||||||
|
typeof existing.baseUrl === 'string' &&
|
||||||
|
Object.values(ALIBABA_STANDARD_API_KEY_ENDPOINTS).includes(
|
||||||
|
existing.baseUrl,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const updatedConfigs = [...newConfigs, ...nonAlibabaStandardConfigs];
|
||||||
|
|
||||||
|
// Persist model providers and auth settings
|
||||||
|
settings.setValue(
|
||||||
|
persistScope,
|
||||||
|
`modelProviders.${AuthType.USE_OPENAI}`,
|
||||||
|
updatedConfigs,
|
||||||
|
);
|
||||||
|
settings.setValue(
|
||||||
|
persistScope,
|
||||||
|
'security.auth.selectedType',
|
||||||
|
AuthType.USE_OPENAI,
|
||||||
|
);
|
||||||
|
settings.setValue(persistScope, 'model.name', modelIds[0]);
|
||||||
|
|
||||||
|
// Reload and refresh
|
||||||
|
const updatedModelProviders: Record<string, ModelConfig[]> = {
|
||||||
|
...(settings.merged.modelProviders as Record<string, ModelConfig[]>),
|
||||||
|
[AuthType.USE_OPENAI]: updatedConfigs,
|
||||||
|
};
|
||||||
|
config.reloadModelProvidersConfig(updatedModelProviders);
|
||||||
|
await config.refreshAuth(AuthType.USE_OPENAI);
|
||||||
|
|
||||||
|
writeStdoutLine(
|
||||||
|
t(
|
||||||
|
'Successfully configured Alibaba Cloud ModelStudio Standard API Key with {{modelCount}} model(s).',
|
||||||
|
{ modelCount: String(modelIds.length) },
|
||||||
|
),
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
writeStderrLine(getErrorMessage(error));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Custom API Key - prints docs link
|
||||||
|
*/
|
||||||
|
function handleCustomApiKeyAuth(): void {
|
||||||
|
writeStdoutLine(
|
||||||
|
t(
|
||||||
|
'\nYou can configure your API key and models in settings.json.\nRefer to the documentation for setup instructions:\n https://qwenlm.github.io/qwen-code-docs/en/users/configuration/model-providers/\n',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts the user to select a region for ModelStudio Standard API Key
|
||||||
|
*/
|
||||||
|
async function promptForStandardRegion(): Promise<AlibabaStandardRegion> {
|
||||||
|
const selector = new InteractiveSelector(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value: 'cn-beijing' as AlibabaStandardRegion,
|
||||||
|
label: t('China (Beijing)'),
|
||||||
|
description: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'sg-singapore' as AlibabaStandardRegion,
|
||||||
|
label: t('Singapore'),
|
||||||
|
description: 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'us-virginia' as AlibabaStandardRegion,
|
||||||
|
label: t('US (Virginia)'),
|
||||||
|
description: 'https://dashscope-us.aliyuncs.com/compatible-mode/v1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'cn-hongkong' as AlibabaStandardRegion,
|
||||||
|
label: t('China (Hong Kong)'),
|
||||||
|
description:
|
||||||
|
'https://cn-hongkong.dashscope.aliyuncs.com/compatible-mode/v1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
t('Select region:'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return await selector.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts the user to enter comma-separated model IDs
|
||||||
|
*/
|
||||||
|
async function promptForModelIds(): Promise<string> {
|
||||||
|
const defaultModels = 'qwen3.5-plus,glm-5,kimi-k2.5';
|
||||||
|
return promptForInput(
|
||||||
|
t('Enter model IDs (comma-separated, default: {{default}}): ', {
|
||||||
|
default: defaultModels,
|
||||||
|
}),
|
||||||
|
{ defaultValue: defaultModels },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the current authentication status
|
* Shows the current authentication status
|
||||||
*/
|
*/
|
||||||
|
|
@ -421,12 +661,15 @@ export async function showAuthStatus(): Promise<void> {
|
||||||
writeStdoutLine(t('Run one of the following commands to get started:\n'));
|
writeStdoutLine(t('Run one of the following commands to get started:\n'));
|
||||||
writeStdoutLine(
|
writeStdoutLine(
|
||||||
t(
|
t(
|
||||||
' qwen auth qwen-oauth - Authenticate with Qwen OAuth (free tier)',
|
' qwen auth coding-plan - Authenticate with Alibaba Cloud Coding Plan',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
writeStdoutLine(
|
||||||
|
t(' qwen auth api-key - Authenticate with an API key'),
|
||||||
|
);
|
||||||
writeStdoutLine(
|
writeStdoutLine(
|
||||||
t(
|
t(
|
||||||
' qwen auth coding-plan - Authenticate with Alibaba Cloud Coding Plan\n',
|
' qwen auth qwen-oauth - Authenticate with Qwen OAuth (discontinued)',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
writeStdoutLine(t('Or simply run:'));
|
writeStdoutLine(t('Or simply run:'));
|
||||||
|
|
@ -451,12 +694,15 @@ export async function showAuthStatus(): Promise<void> {
|
||||||
const codingPlanVersion = mergedSettings.codingPlan?.version;
|
const codingPlanVersion = mergedSettings.codingPlan?.version;
|
||||||
const modelName = mergedSettings.model?.name;
|
const modelName = mergedSettings.model?.name;
|
||||||
|
|
||||||
// Check if API key is set in environment
|
// Check which API key type is configured
|
||||||
const hasApiKey =
|
const hasCodingPlanKey =
|
||||||
!!process.env[CODING_PLAN_ENV_KEY] ||
|
!!process.env[CODING_PLAN_ENV_KEY] ||
|
||||||
!!mergedSettings.env?.[CODING_PLAN_ENV_KEY];
|
!!mergedSettings.env?.[CODING_PLAN_ENV_KEY];
|
||||||
|
const hasStandardKey =
|
||||||
|
!!process.env[DASHSCOPE_STANDARD_API_KEY_ENV_KEY] ||
|
||||||
|
!!mergedSettings.env?.[DASHSCOPE_STANDARD_API_KEY_ENV_KEY];
|
||||||
|
|
||||||
if (hasApiKey) {
|
if (hasCodingPlanKey) {
|
||||||
writeStdoutLine(
|
writeStdoutLine(
|
||||||
t('✓ Authentication Method: Alibaba Cloud Coding Plan'),
|
t('✓ Authentication Method: Alibaba Cloud Coding Plan'),
|
||||||
);
|
);
|
||||||
|
|
@ -484,16 +730,32 @@ export async function showAuthStatus(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
writeStdoutLine(t(' Status: API key configured\n'));
|
writeStdoutLine(t(' Status: API key configured\n'));
|
||||||
} else {
|
} else if (hasStandardKey) {
|
||||||
writeStdoutLine(
|
writeStdoutLine(
|
||||||
t(
|
t(
|
||||||
'⚠️ Authentication Method: Alibaba Cloud Coding Plan (Incomplete)',
|
'✓ Authentication Method: Alibaba Cloud ModelStudio Standard API Key',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (modelName) {
|
||||||
writeStdoutLine(
|
writeStdoutLine(
|
||||||
t(' Issue: API key not found in environment or settings\n'),
|
t(' Current Model: {{model}}', { model: modelName }),
|
||||||
);
|
);
|
||||||
writeStdoutLine(t(' Run `qwen auth coding-plan` to re-configure.\n'));
|
}
|
||||||
|
|
||||||
|
writeStdoutLine(t(' Status: API key configured\n'));
|
||||||
|
} else {
|
||||||
|
writeStdoutLine(
|
||||||
|
t('✓ Authentication Method: OpenAI-compatible API Key'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (modelName) {
|
||||||
|
writeStdoutLine(
|
||||||
|
t(' Current Model: {{model}}', { model: modelName }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeStdoutLine(t(' Status: Configured\n'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeStdoutLine(
|
writeStdoutLine(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue