feat: Remove the logic related to region

This commit is contained in:
qcq01083097
2026-06-16 18:16:10 +08:00
parent a5d055f45a
commit d24b41d452
22 changed files with 81 additions and 93 deletions
+6
View File
@@ -6,6 +6,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
[中文版](CHANGELOG.zh.md) · [README](README.md) · [Contributing](CONTRIBUTING.md)
## [Unreleased]
### Removed
- Global `--region`, environment variable `DASHSCOPE_REGION`, and `bl config set --key region`. DashScope API endpoint is selected only via `--base-url`, `DASHSCOPE_BASE_URL`, or `base_url` in `config.json` (defaults to the China mainland URL). Existing `region` entries in `config.json` are ignored; set `base_url` explicitly if you relied on `us` / `intl`.
## [1.3.2] - 2026-06-12
### Fixed
+6
View File
@@ -6,6 +6,12 @@
[English](CHANGELOG.md) · [README](README.zh.md) · [参与贡献](CONTRIBUTING.zh.md)
## [未发布]
### 移除
- 全局 `--region`、环境变量 `DASHSCOPE_REGION` 以及 `bl config set --key region`。DashScope API 地址仅通过 `--base-url`、`DASHSCOPE_BASE_URL` 或 `config.json` 中的 `base_url` 指定(默认中国大陆)。`config.json` 中的 `region` 字段不再读取;若曾依赖 `us` / `intl`,请改为设置对应的 `base_url`。
## [1.3.2] - 2026-06-12
### 修复
+1 -1
View File
@@ -102,7 +102,7 @@ bl auth status --output json
bl text chat --message "ping" --non-interactive --output json
```
若失败:根据 stderr / JSON 中的 `hint` 或 `message` 排查(网络、Key 无效、region 等)。全局 region:`--region cn|us|intl`,默认 `cn`。
若失败:根据 stderr / JSON 中的 `hint` 或 `message` 排查(网络、Key 无效、`base_url` 等)。DashScope 端点:使用 `--base-url` / `bl config set --key base_url` / `DASHSCOPE_BASE_URL`,默认中国大陆 `https://dashscope.aliyuncs.com`。
---
+1 -1
View File
@@ -172,7 +172,7 @@ export BAILIAN_WORKSPACE_ID=ws-...
bl config show
# Set defaults
bl config set --key region --value us
bl config set --key base_url --value https://dashscope-us.aliyuncs.com
bl config set --key default_text_model --value qwen-turbo
bl config set --key timeout --value 600
+1 -1
View File
@@ -167,7 +167,7 @@ export BAILIAN_WORKSPACE_ID=ws-...
bl config show
# 设置默认值
bl config set --key region --value us
bl config set --key base_url --value https://dashscope-us.aliyuncs.com
bl config set --key default_text_model --value qwen-turbo
bl config set --key timeout --value 600
+1 -1
View File
@@ -172,7 +172,7 @@ export BAILIAN_WORKSPACE_ID=ws-...
bl config show
# Set defaults
bl config set --key region --value us
bl config set --key base_url --value https://dashscope-us.aliyuncs.com
bl config set --key default_text_model --value qwen-turbo
bl config set --key timeout --value 600
+1 -1
View File
@@ -167,7 +167,7 @@ export BAILIAN_WORKSPACE_ID=ws-...
bl config show
# 设置默认值
bl config set --key region --value us
bl config set --key base_url --value https://dashscope-us.aliyuncs.com
bl config set --key default_text_model --value qwen-turbo
bl config set --key timeout --value 600
+1 -9
View File
@@ -12,7 +12,6 @@ import {
import { emitResult } from "../../output/output.ts";
const VALID_KEYS = [
"region",
"base_url",
"output",
"output_dir",
@@ -58,7 +57,7 @@ export default defineCommand({
{
flag: "--key <key>",
description:
"Config key (region, base_url, output, output_dir, timeout, api_key, access_token, default_*_model, access_key_id, access_key_secret, workspace_id)",
"Config key (base_url, output, output_dir, timeout, api_key, access_token, default_*_model, access_key_id, access_key_secret, workspace_id)",
},
{ flag: "--value <value>", description: "Value to set" },
],
@@ -90,13 +89,6 @@ export default defineCommand({
}
// Validate specific values
if (resolvedKey === "region" && !["cn", "us", "intl"].includes(value)) {
throw new BailianError(
`Invalid region "${value}". Valid values: cn, us, intl`,
ExitCode.USAGE,
);
}
if (resolvedKey === "output" && !["text", "json"].includes(value)) {
throw new BailianError(
`Invalid output format "${value}". Valid values: text, json`,
+9 -6
View File
@@ -9,6 +9,10 @@ import { API_KEY_PAGE } from "./urls.ts";
const LABEL_WIDTH = 13;
/** Short reminder; full resolution order matches `loadConfig` in bailian-cli-core. */
const BASE_URL_HINT =
"If the DashScope host is wrong, check baseUrl (--base-url, bl config show, or DASHSCOPE_BASE_URL).";
function pad(label: string): string {
return label.padEnd(LABEL_WIDTH);
}
@@ -76,7 +80,7 @@ function pickNetworkHint(code: string | undefined): string {
switch (code) {
case "ENOTFOUND":
case "EAI_AGAIN":
return "DNS resolution failed. Check DASHSCOPE_BASE_URL or your DNS / network.";
return `DNS resolution failed. Check DNS / network. ${BASE_URL_HINT}`;
case "ECONNREFUSED":
return "Connection refused. Check the target host/port and proxy settings.";
case "ECONNRESET":
@@ -86,13 +90,13 @@ function pickNetworkHint(code: string | undefined): string {
"export HTTPS_PROXY=http://127.0.0.1:<proxy-port>"
);
case "ETIMEDOUT":
return "Connection timed out. Check your network or try a different region.";
return `Connection timed out. Check your network. ${BASE_URL_HINT}`;
case "CERT_HAS_EXPIRED":
case "UNABLE_TO_VERIFY_LEAF_SIGNATURE":
case "DEPTH_ZERO_SELF_SIGNED_CERT":
return "TLS certificate error. Check system clock and CA bundle.";
default:
return "Check network connection, proxy settings (HTTP_PROXY / HTTPS_PROXY), and DASHSCOPE_BASE_URL.";
return `Check network and proxy (HTTP_PROXY / HTTPS_PROXY). ${BASE_URL_HINT}`;
}
}
@@ -166,9 +170,8 @@ export function handleError(err: unknown): never {
"Request timed out.",
ExitCode.TIMEOUT,
"Try increasing --timeout (e.g. --timeout 60).\n" +
"If this happens on every request with a valid API key, you may be hitting the wrong region.\n" +
"Run: bl auth status — to check your credentials and region.\n" +
"Run: bl config set --key region --value cn — to override the region.",
`${BASE_URL_HINT}\n` +
"Run: bl auth status — to check credentials.",
{ cause: err },
);
return handleError(timeout);
+21 -16
View File
@@ -160,20 +160,25 @@ describe("e2e: auth", () => {
expect(data.dashscope_commands?.method).toBeDefined();
});
test.skipIf(!isDashScopeE2EReady())("auth status --output json --quiet --region cn", async () => {
const { stdout, stderr, exitCode } = await runCli([
"auth",
"status",
"--non-interactive",
"--output",
"json",
"--quiet",
"--region",
"cn",
]);
expect(exitCode, stderr).toBe(0);
const data = parseStdoutJson<{ authenticated?: boolean; dashscope_commands?: unknown }>(stdout);
expect(data.authenticated).toBe(true);
expect(data.dashscope_commands).toBeDefined();
});
test.skipIf(!isDashScopeE2EReady())(
"auth status --output json --quiet --base-url 国内",
async () => {
const { stdout, stderr, exitCode } = await runCli([
"auth",
"status",
"--non-interactive",
"--output",
"json",
"--quiet",
"--base-url",
"https://dashscope.aliyuncs.com",
]);
expect(exitCode, stderr).toBe(0);
const data = parseStdoutJson<{ authenticated?: boolean; dashscope_commands?: unknown }>(
stdout,
);
expect(data.authenticated).toBe(true);
expect(data.dashscope_commands).toBeDefined();
},
);
});
@@ -9,17 +9,18 @@ type ConsoleDryRunMeta = {
/**
* E2E for global console flags (`--console-region`, `--console-site`,
* `--console-switch-agent`) vs DashScope `--region`.
* `--console-switch-agent`) and DashScope `--base-url`.
*/
describe("e2e: console global flags", () => {
test("根帮助展示 --console-region / --console-site / --console-switch-agent", async () => {
test("根帮助展示 --base-url 与 console 全局标志", async () => {
const { stderr, exitCode } = await runCli(["--help"]);
expect(exitCode, stderr).toBe(0);
expect(stderr).toMatch(/--base-url/);
expect(stderr).toMatch(/--console-region/);
expect(stderr).toMatch(/--console-site/);
expect(stderr).toMatch(/--console-switch-agent/);
expect(stderr).toMatch(/--region.*cn.*us.*intl/i);
expect(stderr).not.toMatch(/^\s*--region\s/m);
});
test("quota check --help 不重复命令级 region,并提示全局 flags", async () => {
@@ -93,8 +94,8 @@ describe("e2e: console global flags", () => {
expect(data.consoleSwitchAgent).toBe(12345);
});
test("console call --dry-run --region cn-beijing 不改变 consoleRegion", async () => {
const { stdout, stderr, exitCode } = await runCli([
test("console call 拒绝未知全局 flag --region", async () => {
const { stderr, exitCode } = await runCli([
"console",
"call",
"--api",
@@ -103,16 +104,11 @@ describe("e2e: console global flags", () => {
"{}",
"--dry-run",
"--non-interactive",
"--output",
"json",
"--region",
"cn-beijing",
"--console-region",
"ap-southeast-1",
"cn",
]);
expect(exitCode, stderr).toBe(0);
const data = parseStdoutJson<ConsoleDryRunMeta>(stdout);
expect(data.consoleRegion).toBe("ap-southeast-1");
expect(exitCode).not.toBe(0);
expect(stderr).toMatch(/Unknown flag.*--region/);
});
test("mcp list --dry-run --console-region 透传", async () => {
+1 -1
View File
@@ -66,7 +66,7 @@ describe("e2e: mcp", () => {
expect(exitCode, stderr).toBe(0);
const data = parseStdoutJson<{
api?: string;
region?: string;
consoleRegion?: string;
data?: {
reqDTO?: {
type?: string;
+2 -13
View File
@@ -1,5 +1,5 @@
import { readFileSync, writeFileSync, renameSync, existsSync } from "fs";
import { parseConfigFile, REGIONS, type Config, type ConfigFile, type Region } from "./schema.ts";
import { parseConfigFile, REGIONS, type Config, type ConfigFile } from "./schema.ts";
import { ensureConfigDir, getConfigPath } from "./paths.ts";
import { detectOutputFormat, type OutputFormat } from "../output/formatter.ts";
import { BailianError } from "../errors/base.ts";
@@ -36,16 +36,7 @@ export function loadConfig(flags: GlobalFlags): Config {
const accessTokenEnv = process.env.DASHSCOPE_ACCESS_TOKEN?.trim() || undefined;
const fileAccessToken = file.access_token?.trim() || undefined;
const explicitRegion = (flags.region as string) || process.env.DASHSCOPE_REGION || undefined;
const cachedRegion = file.region;
const region = (explicitRegion || cachedRegion || "cn") as Region;
const baseUrl =
flags.baseUrl ||
file.base_url ||
process.env.DASHSCOPE_BASE_URL ||
REGIONS[region] ||
REGIONS.cn;
const baseUrl = flags.baseUrl || file.base_url || process.env.DASHSCOPE_BASE_URL || REGIONS.cn;
const output: OutputFormat = detectOutputFormat(
flags.output || process.env.DASHSCOPE_OUTPUT || file.output,
@@ -68,9 +59,7 @@ export function loadConfig(flags: GlobalFlags): Config {
accessTokenEnv,
fileAccessToken,
fileApiKey,
fileRegion: file.region,
configPath: getConfigPath(),
region,
baseUrl,
output,
outputDir: file.output_dir || undefined,
-6
View File
@@ -18,7 +18,6 @@ export interface ConfigFile {
api_key?: string;
/** OAuth-style token from `bl auth login --console` callback; sent as `Authorization: Bearer …` */
access_token?: string;
region?: Region;
base_url?: string;
output?: "text" | "json";
output_dir?: string;
@@ -37,7 +36,6 @@ export interface ConfigFile {
telemetry?: boolean;
}
const VALID_REGIONS = new Set<string>(["cn", "us", "intl"]);
const VALID_OUTPUTS = new Set<string>(["text", "json"]);
const VALID_CONSOLE_SITES = new Set<string>(["domestic", "international"]);
@@ -66,8 +64,6 @@ export function parseConfigFile(raw: unknown): ConfigFile {
out.access_token = obj.access_token;
else if (typeof obj.accessToken === "string" && obj.accessToken.length > 0)
out.access_token = obj.accessToken;
if (typeof obj.region === "string" && VALID_REGIONS.has(obj.region))
out.region = obj.region as Region;
if (typeof obj.base_url === "string" && isHttpUrl(obj.base_url)) out.base_url = obj.base_url;
if (typeof obj.output === "string" && VALID_OUTPUTS.has(obj.output))
out.output = obj.output as ConfigFile["output"];
@@ -110,9 +106,7 @@ export interface Config {
/** `access_token` in config file (console login). */
fileAccessToken?: string;
fileApiKey?: string;
fileRegion?: Region;
configPath?: string;
region: Region;
baseUrl: string;
output: "text" | "json";
outputDir?: string;
-3
View File
@@ -7,7 +7,6 @@ export interface TrackingEvent {
httpStatus?: number;
requestId?: string;
cliVersion: string;
region: string;
nodeVersion: string;
os: string;
authMethod?: string;
@@ -20,7 +19,6 @@ export function createTrackingEvent(opts: {
success: boolean;
error?: { message?: string; httpStatus?: number; requestId?: string };
cliVersion: string;
region: string;
authMethod?: string;
params?: Record<string, unknown>;
}): TrackingEvent {
@@ -30,7 +28,6 @@ export function createTrackingEvent(opts: {
durationMs: opts.durationMs,
success: opts.success,
cliVersion: opts.cliVersion,
region: opts.region,
nodeVersion: process.version,
os: process.platform,
};
-2
View File
@@ -17,7 +17,6 @@ const GLOBAL_FLAG_KEYS = new Set([
"help",
"nonInteractive",
"async",
"region",
"console",
]);
@@ -131,7 +130,6 @@ export async function trackCommandExecution(
success,
error: success ? undefined : { message: errorMessage, httpStatus, requestId },
cliVersion: config.clientVersion ?? "unknown",
region: config.region,
authMethod,
params: extractParams(flags),
});
-1
View File
@@ -40,7 +40,6 @@ export function defineCommand(spec: CommandSpec): Command {
/** Global flags shared by all commands — drives the parser's type resolution. */
export const GLOBAL_OPTIONS: OptionDef[] = [
{ flag: "--api-key <key>", description: "API key" },
{ flag: "--region <region>", description: "API region: cn (default), us, intl" },
{ flag: "--base-url <url>", description: "API base URL" },
{ flag: "--output <format>", description: "Output format: text, json" },
{ flag: "--timeout <seconds>", description: "Request timeout", type: "number" },
+5 -1
View File
@@ -10,7 +10,6 @@ import {
function testConfig(overrides: Partial<Config> = {}): Config {
return {
region: "cn",
baseUrl: "https://dashscope.aliyuncs.com",
output: "json",
timeout: 30,
@@ -199,6 +198,11 @@ test("parseBooleanValue accepts only true and false strings (case-insensitive)",
expect(() => parseBooleanValue("maybe")).toThrow(BailianError);
});
test("parseConfigFile ignores obsolete region field", () => {
const f = parseConfigFile({ region: "intl" });
expect("region" in f).toBe(false);
});
test("parseConfigFile accepts only well-formed http(s) base_url", () => {
expect(parseConfigFile({ base_url: "https://dashscope.aliyuncs.com" }).base_url).toBe(
"https://dashscope.aliyuncs.com",
+9 -9
View File
@@ -117,7 +117,7 @@ bl auth logout --console # clear console token only
Get an API key: https://bailian.console.aliyun.com/cn-beijing/?tab=app#/api-key
**Region:** `cn` (default), `us`, `intl` — `--region` or `DASHSCOPE_REGION` or `bl config set --key region --value us`.
**DashScope endpoint:** default `https://dashscope.aliyuncs.com` (China). Override with `--base-url`, `bl config set --key base_url --value https://dashscope-us.aliyuncs.com` (US), or `DASHSCOPE_BASE_URL` / `https://dashscope-intl.aliyuncs.com` (international).
---
@@ -127,13 +127,13 @@ See [`reference/index.md` → Global flags](reference/index.md#global-flags) for
Commonly used:
| Flag | Purpose |
| ------------------------------------- | --------------------------------------------------------- |
| `--output text\|json` | Structured output (default: text in TTY, json when piped) |
| `--api-key`, `--region`, `--base-url` | Override auth / endpoint |
| `--quiet`, `--verbose`, `--dry-run` | Output control |
| `--non-interactive` | CI / agent mode (no prompts) |
| `--help` | Per-command help |
| Flag | Purpose |
| ----------------------------------- | --------------------------------------------------------- |
| `--output text\|json` | Structured output (default: text in TTY, json when piped) |
| `--api-key`, `--base-url` | Override auth / endpoint |
| `--quiet`, `--verbose`, `--dry-run` | Output control |
| `--non-interactive` | CI / agent mode (no prompts) |
| `--help` | Per-command help |
---
@@ -176,7 +176,7 @@ ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
## Configuration
- **Config file:** `~/.bailian/config.json`
- **Env:** `DASHSCOPE_API_KEY`, `DASHSCOPE_REGION`, `DASHSCOPE_BASE_URL`, `DASHSCOPE_OUTPUT`
- **Env:** `DASHSCOPE_API_KEY`, `DASHSCOPE_BASE_URL`, `DASHSCOPE_OUTPUT`
```bash
bl config show
+3 -3
View File
@@ -20,7 +20,7 @@ function shouldOfferIssueReport(exitCode, apiCode, message, hint):
# Step 2: NETWORK / TIMEOUT — exclude if hint is actionable
if exitCode in [5 (TIMEOUT), 6 (NETWORK)] AND hint is actionable:
return EXCLUDE # user can self-service (DNS, proxy, --timeout, region)
return EXCLUDE # user can self-service (DNS, proxy, --timeout, base_url)
# Step 3: GENERAL (exit code 1) — shared by CLI bugs AND service passthrough
# MUST inspect api_code / message to disambiguate
@@ -80,7 +80,7 @@ These are **user**, **environment**, or **service business** errors. Give fix hi
| **Free quota query** | `bl usage free` business result | Quota used up — not a CLI defect |
| **Obvious local env** | Hint is sufficient | `ENOENT` / `EACCES`, wrong file path, disk full |
| **Network (self-service)** | Exit code **6** (NETWORK) + clear hint | DNS, proxy, TLS — user fixes `DASHSCOPE_BASE_URL`, proxy, or network |
| **Timeout (self-service)** | Exit code **5** (TIMEOUT) + hint works | Increase `--timeout`, check region with `bl auth status` |
| **Timeout (self-service)** | Exit code **5** (TIMEOUT) + hint works | Increase `--timeout`, check `base_url` with `bl auth status` |
**Rule:** If the authoritative source of the error is the **service response** or **user input**, treat it as non-reportable (same boundary as the CLI repo’s error-handling docs).
@@ -172,7 +172,7 @@ Before any paste or `gh issue create`:
- Replace `Authorization: Bearer ...` headers in verbose output → `Authorization: Bearer [REDACTED]`
- Redact `--prompt` / `--message` / `--biz-params` contents if they contain user business data → summarize as `[user prompt about <topic>]`
- Redact `account`, `uid`, `aliuid` from `bl auth status` output → `[REDACTED]`
- Redact sensitive fields from `bl config show` (keep non-secret keys like `region`, model defaults)
- Redact sensitive fields from `bl config show` (keep non-secret keys like `base_url`, model defaults)
- **Keep** `Request ID` / `request_id` — helps the team trace logs
- Local paths may stay or be generalized (`~/path/to/file.png`)
+4 -4
View File
@@ -49,10 +49,10 @@ bl config export-schema --command "video generate"
#### Options
| Flag | Type | Required | Description |
| ----------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--key <key>` | string | no | Config key (region, base*url, output, output_dir, timeout, api_key, access_token, default*\*\_model, access_key_id, access_key_secret, workspace_id) |
| `--value <value>` | string | no | Value to set |
| Flag | Type | Required | Description |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `--key <key>` | string | no | Config key (base*url, output, output_dir, timeout, api_key, access_token, default*\*\_model, access_key_id, access_key_secret, workspace_id) |
| `--value <value>` | string | no | Value to set |
#### Examples
-1
View File
@@ -90,7 +90,6 @@ Available on every command (in addition to command-specific options):
| Flag | Type | Required | Description |
| ------------------------------ | ------- | -------- | -------------------------------------------------------- |
| `--api-key <key>` | string | no | API key |
| `--region <region>` | string | no | API region: cn (default), us, intl |
| `--base-url <url>` | string | no | API base URL |
| `--output <format>` | string | no | Output format: text, json |
| `--timeout <seconds>` | number | no | Request timeout |