Skip to content

zcode-cli 3.8.1-26

Choose a tag to compare

@xhqing xhqing released this 05 Sep 09:40
· 19 commits to main since this release

Make sign-in state first-class: instant identity switch after /login, custom-provider.env as the signed-out fallback with automatic hand-off

  • Make sign-in state first-class: after /login completes browser OAuth the banner and status bar switch to the signed-in account immediately, and the custom-provider env file is repositioned as the signed-out-only channel with automatic hand-off in both directions (src/identity.ts, src/env-config.ts, src/launcher.ts, packages/zcode-tui/src/login-identity.ts, packages/zcode-tui/src/index.ts, test/identity.test.ts, test/login-identity.test.ts, test/env-config.test.ts, README.md, README_zh_hans.md, README_zh_hant.md, docs/CONFIGURATION.md, .env.example renamed to custom-provider.env.example).
    • Why: after completing OAuth in the TUI (/login), the banner kept showing the masked API key from the custom-provider file — a successful login with zero visible feedback. The root cause sits in the 3.8.1-25 decoupling design: identity display followed the model.main prefix, which the custom-provider file pinned to its env-<id> slot on every start, so the official slots and the credential vault written by OAuth never got a turn; and under the old design, seeing your login account required deleting the file and re-creating it after logout — unusable as a product. The ruling product principle: a user action must produce correct feedback — signed in shows the signed-in account, signed out shows Not signed in, and the two states must hand off automatically without manual file juggling.
    • What changed: (1) sign-in detection (new readStoredOAuthLogin() in src/identity.ts): the presence of oauth:<provider>:access_token in the credential vault ~/.zcode/v2/credentials.json is the sign-in state (the oauth:active_provider marker takes priority; a stale marker falls back to scanning both providers' tokens); (2) login-first identity display (readLoginIdentitySnapshot() rewritten): signed in → show the login provider's account identity (vault user_info snapshot → BigModel key-name mapping → masked key), regardless of which slot model.main points to — visible on the refresh right after login; signed out with model access → new kind signedOut, banner / status bar show "Not signed in" and the provider displays the declared value with the env- prefix stripped; no access at all → the sign-in wizard warning stays. The TUI side (login-identity.ts) no longer mirrors the logic — it reuses the src snapshot functions (single implementation, no duplicate drift); (3) automatic model-ownership switch (env-config.ts): while signed in, the startup sync sets skipModelBlock (refresh only the env- slot data, never rewrite the model block); a leftover model block pointing at an env- slot is switched to the login provider's official slot by the new switchModelBlockToOfficialProvider() (model ID kept if the official slot already declares it, otherwise its first declared model); after logout the next start is signed out and the file takes the model block back — both directions seamless, the file never needs manual removal or restore; (4) file rename .env → custom-provider.env (template renamed to custom-provider.env.example with its header rewritten to the new semantics): the first start automatically renames a legacy ~/.zcode/cli/.env and prints one notice line (no migration when ZCODE_ENV_FILE pins an explicit path); (5) prefix-stripped display (new displayProviderId() / displayModelRef() in env-config.ts): the TUI model display, the zcode identity Provider line, and <provider-id>/<model-id> all show the value declared in the file (env-bigmodel/glm-5.3 → bigmodel/glm-5.3); the env- prefix lives only in config.json internal slot names (the isolation mechanism is unchanged); (6) the bare zcode login gate now blocks only when already signed in: signed in it prints "Already signed in as " and exits (--oauth forces a re-login), signed out it lets OAuth proceed even when a custom-provider file is configured — "running login means the user wants to log in"; (7) zcode identity set is refused while signed out (display names follow the login account; nothing to set when signed out); (8) zcode identity while signed out prints Identity: not signed in (model access via custom provider).
    • Behavior map (login / logout feedback loop): signed out + file → model via the env- slot, banner "Not signed in", model shown as <declared id>/<model>; /login OAuth completes → vault + official slot written, TUI refreshes instantly to "Signed in as ", next start the model block belongs to the official slot; /logout → vault cleared, banner flips back to "Not signed in" instantly, next start the file takes the model back over.
    • Migration note: the first start after upgrading renames ~/.zcode/cli/.env → custom-provider.env automatically (one console notice); set ZCODE_ENV_FILE to the old path to opt out. Signed-in users' model.main is moved from env-<id>/... back to the official slot on the next start.
    • Verification: tsc --noEmit passes; full bun test 674 pass / 0 fail (78 files; identity gains 3 sign-in-detection + 3 snapshot cases, login-identity re-signs signedOut semantics + 2 new cases, env-config gains 2 migration + 1 display + 1 skipModelBlock + 3 model-block-switch cases).

Install

npm install -g https://github.com/xhqing/zcode-cli/releases/download/v3.8.1-26/zcode-cli-3.8.1-26.tgz