Skip to content

Commit 270412d

Browse files
lishengzxcclaude
andcommitted
refactor(auth): deduplicate canRetry/validateKey between login.ts and login-console.ts
Export validateAndPersistApiKey from login-console.ts and reuse in login.ts. Remove duplicated canRetry, RETRY_DELAY_BASE_MS, and validateKeyAndPersist from login.ts. Unify validation model to qwen3.7-max. Reorder base_url write before apiKey validation in the --api-key path to avoid double read-modify-write. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 36a60a2 commit 270412d

2 files changed

Lines changed: 8 additions & 70 deletions

File tree

packages/cli/src/commands/auth/login-console.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ function canRetry(err: unknown): boolean {
388388
return false;
389389
}
390390

391-
async function validateAndPersistApiKey(
391+
export async function validateAndPersistApiKey(
392392
config: Config,
393393
key: string,
394394
baseUrl: string,
@@ -400,7 +400,7 @@ async function validateAndPersistApiKey(
400400
method: "POST",
401401
timeout: Math.min(config.timeout, 30),
402402
body: {
403-
model: "qwen-max",
403+
model: "qwen3.7-max",
404404
messages: [{ role: "user", content: "hi" }],
405405
max_tokens: 1,
406406
},

packages/cli/src/commands/auth/login.ts

Lines changed: 6 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import {
2-
BailianError,
3-
ExitCode,
4-
chatEndpoint,
52
defineCommand,
6-
getConfigPath,
73
isInteractive,
84
maskToken,
95
readConfigFile,
10-
requestJson,
116
writeConfigFile,
127
type Config,
138
type GlobalFlags,
@@ -16,68 +11,11 @@ import { printQuickStart } from "../../output/banner.ts";
1611
import { emitBare } from "../../output/output.ts";
1712
import { promptConfirm } from "../../output/prompt.ts";
1813
import { printCurrentCommandHelp } from "../../utils/command-help.ts";
19-
import { resolveConsoleOrigin, runConsoleLogin } from "./login-console.ts";
20-
21-
const RETRY_DELAY_BASE_MS = 500;
22-
23-
function canRetry(err: unknown): boolean {
24-
if (err instanceof BailianError) {
25-
if (err.exitCode === ExitCode.NETWORK || err.exitCode === ExitCode.TIMEOUT) {
26-
return true;
27-
}
28-
const status = err.api?.httpStatus;
29-
return status === 401 || (status !== undefined && status >= 500);
30-
}
31-
if (err instanceof Error) {
32-
return (
33-
err.name === "AbortError" ||
34-
err.name === "TimeoutError" ||
35-
err.message.includes("timed out") ||
36-
err.message === "fetch failed"
37-
);
38-
}
39-
return false;
40-
}
41-
42-
async function validateKeyAndPersist(config: Config, key: string): Promise<void> {
43-
process.stderr.write("Testing key... ");
44-
45-
const testConfig = { ...config, apiKey: key };
46-
const requestOpts = {
47-
url: chatEndpoint(testConfig.baseUrl),
48-
method: "POST",
49-
timeout: Math.min(config.timeout, 30),
50-
body: {
51-
model: "qwen3.7-max",
52-
messages: [{ role: "user", content: "hi" }],
53-
max_tokens: 1,
54-
},
55-
};
56-
57-
for (let attempt = 1; attempt <= 3; attempt++) {
58-
try {
59-
await requestJson<unknown>(testConfig, requestOpts);
60-
break;
61-
} catch (err) {
62-
if (attempt >= 3 || !canRetry(err)) {
63-
process.stderr.write("\n");
64-
throw new BailianError("API key validation failed", ExitCode.AUTH, "Invalid API key.", {
65-
cause: err,
66-
});
67-
}
68-
// retry delay: 500ms, 1000ms, 2000ms
69-
const delayMs = RETRY_DELAY_BASE_MS * 2 ** (attempt - 1);
70-
await new Promise((resolve) => setTimeout(resolve, delayMs));
71-
}
72-
}
73-
74-
process.stderr.write("Valid\n");
75-
76-
const existing = readConfigFile() as Record<string, unknown>;
77-
existing.api_key = key;
78-
await writeConfigFile(existing);
79-
process.stderr.write(`Saved to ${getConfigPath()}\n`);
80-
}
14+
import {
15+
resolveConsoleOrigin,
16+
runConsoleLogin,
17+
validateAndPersistApiKey,
18+
} from "./login-console.ts";
8119

8220
export default defineCommand({
8321
name: "auth login",
@@ -138,12 +76,12 @@ export default defineCommand({
13876
const effectiveConfig = baseUrl ? { ...config, baseUrl } : config;
13977

14078
if (!config.dryRun) {
141-
await validateKeyAndPersist(effectiveConfig, key);
14279
if (baseUrl) {
14380
const existing = readConfigFile() as Record<string, unknown>;
14481
existing.base_url = baseUrl;
14582
await writeConfigFile(existing);
14683
}
84+
await validateAndPersistApiKey(effectiveConfig, key, effectiveConfig.baseUrl);
14785
printQuickStart();
14886
} else {
14987
emitBare("Would validate and save API key.");

0 commit comments

Comments
 (0)