Repository navigation
zcode-cli 3.8.1-25
Add BigModel key-name mapping, fix logout leaving BigModel credentials, and isolate env-file config into env- slots
- Add a BigModel API key → display-name mapping file
~/.zcode/cli/bigmodel-users.json: per-key custom sign-in display names (a user name, a key name, or any label — purely local display text), so account switches no longer need re-pinning; a hint is printed after login when no mapping exists yet (newsrc/bigmodel-users.ts,src/identity.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,README.md,README_zh_hans.md,README_zh_hant.md,docs/CONFIGURATION.md).- Why: BigModel logins (OAuth and API-key variants) only write the exchanged / pasted API key into config.json and never learn the account name, so the identity display falls back to the masked key; multi-account users cannot tell who is signed in after a switch, and the existing
zcode identity setmechanism is a provider-level snapshot that must be manually re-pinned on every switch — miss it and the wrong name shows. With a per-key mapping, every key carries its own display name and switches are correct by construction. - What changed: (1) new
src/bigmodel-users.ts—bigmodelUsersPath()(~/.zcode/cli/bigmodel-users.json, owned by the BigModel login channel and deliberately kept out of the model-access.env),readBigmodelUserNames()(fault-tolerant read: a missing file, bad JSON, or a non-object all yield an empty map; non-string and blank entries are skipped),resolveBigmodelUserName(); (2) identity resolution (readLoginIdentitySnapshotinsrc/identity.tsand its TUI mirrorreadLoginIdentityinlogin-identity.ts): priority is vaultuser_infosnapshot → BigModel key lookup in the mapping (a hit returns the new kindnamed; the banner / status bar showSigned in as <name>, status-bar prefixuser) → masked-key fallback; the mapping only applies to providerbigmodel(zai / custom providers are not looked up); (3) hints in three places:readBigModelKeyNameHint()detects "bigmodel + identity resolved to the masked key + no mapping"; the TUI prints it viasuggestBigModelKeyName()after the non-attributable/loginvariants (bigmodel-coding-plan and the two api-key variants), the bare CLIzcode loginprints it viaprintBigModelKeyNameHint()after success, andzcode identityappends a Tip line when showing a masked key; hints contain only the masked key and the file path, never the full key; (4) 13 new test cases (8 src-side: named resolution, oauth priority, provider restriction, read fault tolerance, hint positive/negative cases, identity-command Tip presence; 5 TUI-side: named / not covered / bad file / non-bigmodel / oauth priority, plus aloginIdentityTextassertion for the named wording). - Scope note: the mapped value is entirely up to the user — a user name, a key remark, an account name, or any custom label works; neither the implementation nor the documentation constrains its semantics (purely local display text, no effect on authentication or requests). The
.envchannel'senv-bigmodelslot is not looked up (the established boundary keeping it decoupled from/login). Thezcode identity setmechanism is kept unchanged (it suits renaming within the same account; the mapping suits multiple keys / multiple accounts — the two complement each other).
- Why: BigModel logins (OAuth and API-key variants) only write the exchanged / pasted API key into config.json and never learn the account name, so the identity display falls back to the masked key; multi-account users cannot tell who is signed in after a switch, and the existing
- Fix
/logoutfailing to remove BigModel credentials: intercepted on both the CLI and TUI sides with a complete deletion list (zai + bigmodel + shared markers) (src/identity.ts,src/launcher.ts,packages/zcode-tui/src/index.ts,test/identity.test.ts).- Why: users reported that after
/logoutin the TUI the model still worked and the account username kept showing at the bottom. Reverse engineeringvendor/zcode.cjsconfirmed the root cause — the runtime's logout ultimately callsclearZaiLoginCredentials(), hardcoded to delete only 4 fixed keys (oauth:zai:access_token/oauth:zai:refresh_token/oauth:zai:user_info/zcodejwttoken, plusoauth:active_provideronly when it decrypts tozai), while the keys written by the BigModel OAuth flow —oauth:bigmodel:access_token,oauth:bigmodel:user_info,oauth:login_attribution— are not on the list: the CLIzcode logoutreally prints "Logged out from Z.AI" and the credential file is indeed written, yet not a single vault entry is removed. The direct cause of the lingering username isoauth:bigmodel:user_infonever being deleted (the TUI identity display reads it first). - What changed: (1)
src/identity.tsaddsclearOAuthLoginCredentials()— the deletion list covers both providers' full credential sets plus shared markers (the zai trio, bigmodel access/refresh/user_info,oauth:login_attribution,oauth:active_provider,zcodejwttoken), preserving unrelated entries (e.g. thezcodefeedbackclientidtelemetry ID), idempotent (a missing or already-empty vault both succeed);runLogoutCommand()/isLogoutInvocation()form the CLI command entry; (2)launcher.tsinterceptszcode logoutafter the identity routing instead of passing it through to the runtime (the runtime's deletion list is a subset of this implementation, so the intercepted behavior is a superset); (3) the TUIsubmit()intercepts/logoutlocally (same layer as the suspended/login zai-coding-plan) with the newhandleLocalLogout(): clear credentials → notice feedback → re-check the login state viareadConfiguredModelAccess()(the loginRequired warning is only set when no model access is configured;.env/ manual-config users keep model access after logout, matching the semantic boundary that an API key is model-access configuration, not a login state) →setLoginRequiredtriggers an inline identity refresh (user_info is gone, the display falls back to the masked key or disappears). - Scope note: logout only clears vault login credentials, not the API key in config.json (consistent with official runtime semantics — the OAuth-exchanged key is an independently valid credential; to cut off model access, delete
.envor edit config).
- Why: users reported that after
.envconfiguration now writes its ownenv-<provider-id>slot, fully decoupled from the/login//logoutOAuth system (src/env-config.ts,packages/zcode-tui/src/index.ts,test/env-config.test.ts).- Why: the intent of
.envis a custom-provider channel (universal for z.ai / bigmodel.cn / deepseek or any provider, without affecting normal login/logout), but the old implementation wrote the.envkey directly into the config slot of the declared ID (ZCODE_PROVIDER_ID=bigmodelwroteprovider.bigmodel) — the same official slot OAuth logins write to — creating a three-way tangle: the.envkey was treated as an official login artifact (the TUI showed the OAuth username), an OAuth login would overwrite the.envconfiguration, andzcode loginreported "no login needed" because the official slot had a key. The default was traced back to a deliberate design (borrowing the official slot to satisfy the upstream login gate — the runtime'shasConfiguredCodingPlanApiKeyonly recognizes the zai/bigmodel slots), but the cost was exactly the tangle above, conflicting with.env's positioning as a universal channel for any provider. - What changed: (1)
buildProviderConfig()in env-config.ts now always outputs theenv-<declared id>slot (ZCODE_PROVIDER_ID=bigmodel→ writesprovider["env-bigmodel"],model.main = "env-bigmodel/glm-5.2"; the declared id is still used for the base-URL default table and the provider display name); theenvProviderSlotPrefixconstant is exported; the official zai/bigmodel slots now belong exclusively to the OAuth flow —.envand/loginnever overwrite each other; (2) the TUI'shandleResult()re-checks a runtime-pushedloginRequired=truewithreadConfiguredModelAccess()(slot-agnostic: only checks whether the provider pointed to by model.main has a non-empty key) and suppresses the "Model access is not configured" warning when configured — compensating for the runtime login gate only recognizing the two official slots;env-*slots and manually configured custom providers both benefit; (3) the identity display needed no changes and degrades automatically (login-identity.ts only consults the vault's user_info for zai/bigmodel;env-*slots show the masked key). - Migration note: on the first start after upgrading, the
.envsync switches to theenv-*slot; keys left behind in the old official slots are kept (harmless residue an OAuth login can overwrite normally). Existing users will see the model identifier change frombigmodel/glm-5.3toenv-bigmodel/glm-5.3(semantically more accurate: this is.env-channel configuration). - Verification:
tsc --noEmitpasses; fullbun test644 pass / 0 fail (78 files; env-config slot assertions updated plus a strengthened "official slots are never touched by.env" case; 5 new identity logout cases).
- Why: the intent of
Install
npm install -g https://github.com/xhqing/zcode-cli/releases/download/v3.8.1-25/zcode-cli-3.8.1-25.tgz