Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
dcec191
fix(auth): resolve region-specific API and OAuth base URLs
sunshinexcode Jun 16, 2026
409c80e
fix(auth): include region in login and status output
sunshinexcode Jun 16, 2026
9cbdfc2
fix(auth): reset session region and guard repo project mismatch
sunshinexcode Jun 17, 2026
e166d24
refactor(cli): simplify region handling for auth and project setup
sunshinexcode Jun 18, 2026
e8a9c48
fix(auth): default login region flag to global
sunshinexcode Jun 18, 2026
db3e39b
fix(auth): validate and normalize login region on login
sunshinexcode Jun 18, 2026
e82d225
refactor(cli): centralize region normalization logic
sunshinexcode Jun 18, 2026
87c7e08
fix(projects): stop exposing region in project responses
sunshinexcode Jun 18, 2026
b7034b1
fix(open): use auth region for console and product docs
sunshinexcode Jun 18, 2026
b77c2c3
fix(quickstart): use region-specific repo and docs URLs
sunshinexcode Jun 18, 2026
d5f8b52
fix(doctor): use region-specific endpoints for network check
sunshinexcode Jun 18, 2026
20fa03b
refactor(config): stop persisting API/OAuth settings in config
sunshinexcode Jun 18, 2026
9cf696e
refactor(cli): normalize auth endpoint constant names
sunshinexcode Jun 18, 2026
f62ce19
fix(cli): allow project env write to target explicit project
sunshinexcode Jun 18, 2026
c6cae5a
test(quickstart): isolate repo override tests and document --project
sunshinexcode Jun 18, 2026
d06ffb8
docs(error-codes): add PROJECT_REGION_MISMATCH entry
sunshinexcode Jun 18, 2026
f15d696
docs(changelog): document region-aware profile changes
sunshinexcode Jun 18, 2026
5a5d297
test(quickstart): use temp dir path for local clone args
sunshinexcode Jun 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ Earlier entries pre-date this convention and only carry their version's compare

## [Unreleased]

### Changed

- Add region-aware CLI profile support for `global` and `cn`: `agora login --region` now selects the API/OAuth endpoints, Console/docs links, quickstart URLs, doctor network checks, and project context region used by later commands.
- **BREAKING**: Remove `--region` from `agora init` and `agora project create`; new projects now use the active login region instead of a per-command region flag.
- **BREAKING**: Update public JSON shapes for region-aware profiles: `auth login --json` and `auth status --json` include `data.region`, while project list/show API models no longer expose a project `region` field because the project APIs do not return it.
- **BREAKING**: Stop persisting CLI API/OAuth integration values in `config.json`. `apiBaseUrl`, `oauthBaseUrl`, `oauthClientId`, and `oauthScope` are now derived from the selected login region or from explicit environment variable overrides (`AGORA_API_BASE_URL`, `AGORA_OAUTH_BASE_URL`, `AGORA_OAUTH_CLIENT_ID`, `AGORA_OAUTH_SCOPE`). Existing configs auto-migrate to schema version `4` and drop those legacy keys on first load; users who previously pinned custom endpoints in `config.json` should move those values to environment variables.
- Add `PROJECT_REGION_MISMATCH` when a repo-local `.agora/project.json` binding points to a different region than the active login region.

## [0.2.5] - 2026-06-05

Installer migration, quickstart scaffold cleanup, and onboarding doc refresh.
Expand Down
6 changes: 1 addition & 5 deletions config.example.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
{
"version": 3,
"apiBaseUrl": "https://agora-cli.agora.io",
"version": 4,
"browserAutoOpen": true,
"logLevel": "info",
"oauthBaseUrl": "https://sso2.agora.io",
"oauthClientId": "agora_web_cli",
"oauthScope": "basic_info,console",
"output": "pretty",
"telemetryEnabled": true,
"debug": false
Expand Down
19 changes: 16 additions & 3 deletions docs/automation.md
Original file line number Diff line number Diff line change
Expand Up @@ -753,11 +753,13 @@ When authenticated, this command returns a success envelope with these required
- `authenticated`
- `status`
`authenticated`.
- `region`
- `expiresAt`
- `scope`

Safe branch fields:
- `authenticated`
- `region`
- `status`
- `expiresAt`

Expand Down Expand Up @@ -801,10 +803,12 @@ Required `data` fields:
Always `login`.
- `status`
Currently `authenticated`.
- `region`
- `scope`
- `expiresAt`

Safe branch fields:
- `region`
- `status`
- `expiresAt`

Expand Down Expand Up @@ -851,7 +855,7 @@ Required `data` fields:
- `cacheRefreshed`
Boolean. `true` only when `--refresh-cache` successfully refreshed the unfiltered first-page project completion cache.

Each item includes: `projectId`, `name`, `appId`, `projectType`, `status`, `region`, `createdAt`, `updatedAt`.
Each item includes: `projectId`, `name`, `appId`, `projectType`, `status`, `createdAt`, `updatedAt`.

Safe branch fields:
- `items[].projectId`
Expand Down Expand Up @@ -954,14 +958,23 @@ Example:
```

Returns the current resolved config object. Safe branch fields:
- `apiBaseUrl`
- `oauthBaseUrl`
- `output`
- `logLevel`
- `browserAutoOpen`
- `telemetryEnabled`
- `debug` (renamed from legacy `verbose` in v0.2.0; legacy key is migrated on first load)

Endpoint and OAuth integration values are derived from the active login
region and may be temporarily overridden with environment variables such as
`AGORA_API_BASE_URL`, `AGORA_OAUTH_BASE_URL`, `AGORA_OAUTH_CLIENT_ID`, and
`AGORA_OAUTH_SCOPE`; they are not persisted in `config.json`.

Migration note: configs written by older CLI versions may contain
`apiBaseUrl`, `oauthBaseUrl`, `oauthClientId`, or `oauthScope`. Schema version
4 drops those keys on first load. If automation previously depended on those
persisted values, set the corresponding `AGORA_*` environment variable in the
job environment instead.

### `config update`

Example:
Expand Down
12 changes: 3 additions & 9 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Authenticate with Agora Console
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--no-browser` | `bool` | — | print the login URL instead of auto-opening a browser |
| `--region` | `string` | | control plane region for login defaults (global or cn) |
| `--region` | `string` | `global` | control plane region for login (global or cn) |

### `agora auth logout`

Expand Down Expand Up @@ -82,13 +82,9 @@ Update persisted CLI defaults

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--api-base-url` | `string` | `https://agora-cli.agora.io` | default CLI API base URL |
| `--browser-auto-open` | `bool` | — | persist browser auto-open preference; use --browser-auto-open=false to disable |
| `--debug` | `bool` | — | persist the --debug preference (echo structured logs to stderr); use --debug=false to disable |
| `--log-level` | `string` | `info` | persist default log level |
| `--oauth-base-url` | `string` | `https://sso2.agora.io` | default OAuth base URL |
| `--oauth-client-id` | `string` | `agora_web_cli` | default OAuth client ID |
| `--oauth-scope` | `string` | `basic_info,console` | default OAuth scope |
| `--output` | `output` | `pretty` | persist default output mode (pretty or json) |
| `--telemetry-enabled` | `bool` | — | persist telemetry preference; use --telemetry-enabled=false to disable |

Expand All @@ -115,7 +111,6 @@ Create a project, clone a quickstart, and write env in one flow
| `--feature` | `stringArray` | `[]` | enable a feature on the newly created project (repeatable); defaults to rtc, rtm, convoai; convoai also enables rtm |
| `--new-project` | `bool` | — | always create a new Agora project instead of reusing an existing one |
| `--project` | `string` | — | existing project ID or exact project name to bind to |
| `--region` | `string` | — | control plane region for newly created projects (global or cn) |
| `--rtm-data-center` | `string` | — | RTM data center to configure when rtm is enabled on a newly created project (CN, NA, EU, or AP); defaults to NA |
| `--template` | `string` | — | quickstart template ID to use |

Expand All @@ -132,7 +127,7 @@ Authenticate with Agora Console
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--no-browser` | `bool` | — | print the login URL instead of auto-opening a browser |
| `--region` | `string` | | control plane region for login defaults (global or cn) |
| `--region` | `string` | `global` | control plane region for login (global or cn) |

### `agora logout`

Expand Down Expand Up @@ -177,7 +172,6 @@ Create a new remote Agora project
| `--dry-run` | `bool` | — | return the planned project create result without creating remote resources |
| `--feature` | `stringArray` | `[]` | enable one or more features after creation; defaults to rtc, rtm, convoai; convoai also enables rtm |
| `--idempotency-key` | `string` | — | caller-provided key for safe retries when supported by the API |
| `--region` | `string` | — | control plane region for the project context (global or cn) |
| `--rtm-data-center` | `string` | — | RTM data center to configure when rtm is enabled (CN, NA, EU, or AP); defaults to NA |
| `--template` | `string` | — | apply a higher-level project preset such as voice-agent |

Expand Down Expand Up @@ -209,6 +203,7 @@ Write project environment variables to a dotenv file
|------|------|---------|-------------|
| `--append` | `bool` | — | append Agora App ID and App Certificate values when no existing values are present |
| `--overwrite` | `bool` | — | replace the target file with only Agora App ID and App Certificate values |
| `--project` | `string` | — | project ID or exact project name; defaults to the current project context |
| `--template` | `string` | — | credential key layout: nextjs or standard; if omitted, detect Next.js from the workspace |

### `agora project feature`
Expand Down Expand Up @@ -379,4 +374,3 @@ Show the current auth status
**`outputModes`**: `pretty`, `json`

**`doctorStatus`**: `healthy`, `warning`, `not_ready`, `auth_error`

1 change: 1 addition & 0 deletions docs/error-codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This catalog is the source of truth for stable codes. CI runs `make snapshot-err
| `PROJECT_NOT_SELECTED` | 1 | No explicit, repo-local, or global project context is available. | Pass `--project`, work inside a bound quickstart, or run `agora project use <project>`. |
| `PROJECT_NOT_FOUND` | 1 | The requested project ID or exact name was not found. | Run `agora project list` and retry with the project ID. |
| `PROJECT_AMBIGUOUS` | 1 | A project name matched multiple projects. | Retry with the project ID. |
| `PROJECT_REGION_MISMATCH` | 1 | A repo-local `.agora/project.json` binding points to a different region than the active login region. | Run `agora login --region <region>` for the bound project region, or pass `--project` to override the repo-local binding. |
| `PROJECT_NO_CERTIFICATE` | 1 | The selected project has no app certificate for env seeding. | Enable an app certificate in Console or select another project. |
| `PROJECT_ENV_TEMPLATE_UNKNOWN` | 1 | The `--template` value for `project env write` is not supported. | Use `nextjs` or `standard`. |
| `PROJECT_NOT_READY` | 1 | `project doctor` could not surface a more specific issue. | Re-run `project doctor` for details. |
Expand Down
3 changes: 0 additions & 3 deletions internal/cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ type projectContext struct {
CurrentProjectID *string `json:"currentProjectId"`
CurrentProjectName *string `json:"currentProjectName"`
CurrentRegion string `json:"currentRegion"`
PreferredRegion string `json:"preferredRegion"`
}

type projectSummary struct {
Expand All @@ -62,7 +61,6 @@ type projectSummary struct {
Name string `json:"name"`
ProjectID string `json:"projectId"`
ProjectType string `json:"projectType"`
Region *string `json:"region,omitempty"`
SignKey *string `json:"signKey"`
Stage int `json:"stage"`
Status string `json:"status"`
Expand All @@ -78,7 +76,6 @@ type projectDetail struct {
Name string `json:"name"`
ProjectID string `json:"projectId"`
ProjectType string `json:"projectType"`
Region *string `json:"region,omitempty"`
SignKey *string `json:"signKey"`
Stage int `json:"stage"`
Status string `json:"status"`
Expand Down
37 changes: 28 additions & 9 deletions internal/cli/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,11 @@ func TestEnsureAppConfigStateMigratesPreviousDefaults(t *testing.T) {
t.Fatal(err)
}
raw := map[string]any{
"apiBaseUrl": previousAPIBaseURL,
"apiBaseUrl": "https://agora-cli-bff.staging.la3.agoralab.co",
"browserAutoOpen": true,
"logLevel": "info",
"oauthBaseUrl": previousOAuthBaseURL,
"oauthClientId": previousOAuthClientID,
"oauthBaseUrl": "https://staging-sso.agora.io",
"oauthClientId": "cli_demo",
"oauthScope": "basic_info,console",
"output": "pretty",
"telemetryEnabled": true,
Expand All @@ -312,11 +312,18 @@ func TestEnsureAppConfigStateMigratesPreviousDefaults(t *testing.T) {
if state.Status != "migrated" {
t.Fatalf("expected migrated, got %s", state.Status)
}
if state.Config.APIBaseURL != defaultConfig().APIBaseURL {
t.Fatalf("expected prod API base URL, got %s", state.Config.APIBaseURL)
rewritten, err := os.ReadFile(configPath)
if err != nil {
t.Fatal(err)
}
if state.Config.OAuthBaseURL != defaultConfig().OAuthBaseURL {
t.Fatalf("expected prod OAuth base URL, got %s", state.Config.OAuthBaseURL)
var rewrittenMap map[string]any
if err := json.Unmarshal(rewritten, &rewrittenMap); err != nil {
t.Fatal(err)
}
for _, key := range []string{"apiBaseUrl", "oauthBaseUrl", "oauthClientId", "oauthScope"} {
if _, ok := rewrittenMap[key]; ok {
t.Fatalf("expected migrated config to drop %s, got %s", key, string(rewritten))
}
}
}

Expand Down Expand Up @@ -463,9 +470,22 @@ func TestEnsureAppConfigStateMigratesPartialAndCustomPreviousConfigs(t *testing.
if err != nil {
t.Fatal(err)
}
if state.Status != "migrated" || state.Config.APIBaseURL != "https://staging.internal.example.com" || state.Config.OAuthClientID != "custom-dev-client" || state.Config.TelemetryEnabled {
if state.Status != "migrated" || state.Config.BrowserAutoOpen || state.Config.TelemetryEnabled || state.Config.Output != outputJSON || !state.Config.Debug {
t.Fatalf("unexpected migrated custom config: %+v", state)
}
rewritten, err := os.ReadFile(configPath)
if err != nil {
t.Fatal(err)
}
var rewrittenMap map[string]any
if err := json.Unmarshal(rewritten, &rewrittenMap); err != nil {
t.Fatal(err)
}
for _, key := range []string{"apiBaseUrl", "oauthBaseUrl", "oauthClientId", "oauthScope"} {
if _, ok := rewrittenMap[key]; ok {
t.Fatalf("expected migrated custom config to drop %s, got %s", key, string(rewritten))
}
}
}

// TestEnsureAppConfigStateMigratesLegacyVerboseKeyToDebug proves that
Expand Down Expand Up @@ -630,7 +650,6 @@ func TestResolveConfiguredOutputModeAndConfigApplication(t *testing.T) {
"AGORA_OUTPUT": "json",
}
app := &App{env: env, cfg: defaultConfig()}
app.cfg.APIBaseURL = "https://config.example.com"
app.cfg.LogLevel = "warn"
app.cfg.BrowserAutoOpen = false
app.cfg.Debug = true
Expand Down
Loading
Loading