feat: support multiple workspaces for the same email (#491) (#493)
* feat(accounts): persist and surface per-account workspaces (#491) Support a single OpenAI/Google account that belongs to multiple ChatGPT workspaces (personal Plus vs business/team), each a distinct quota pool keyed by its org_id. The composite accountId+email matching already keeps such entries separate, but the workspace metadata captured at login did not survive a reload and was invisible in list/status output. - schemas: add WorkspaceSchema and declare workspaces and currentWorkspaceIndex on AccountMetadataV3Schema. The strict z.object stripped these fields on every load, so login-captured workspaces vanished after one read/write round-trip. This is the root cause of the reported "workspaceName always empty even after login". - accounts: surface the active workspace name in formatAccountLabel so two same-email accounts in different workspaces stay distinguishable, while preserving every existing label format. - tests: schema round-trip preservation plus label disambiguation coverage. * feat(workspace): show and switch per-account workspaces (#491) Build on the workspace-persistence fix by making an email's multiple workspaces visible and selectable, so personal Plus and business/team under one Google account can be tracked and rotated between independently. - accounts: add formatWorkspaceLines, one display line per workspace with the active one marked and disabled ones flagged. - status/list: list every workspace beneath an account when it tracks more than one, so both stay visible at once. - new "workspace <account> [workspace]" command: with an account index it lists that account's workspaces; with a workspace index it sets the active workspace and persists it. Wired into the command registry, dispatch, and help. - tests: formatWorkspaceLines coverage and nine workspace-command cases. * feat(login): add --org flag to bind a workspace at login (#491) Let a user register a specific workspace for an email that belongs to more than one (personal Plus vs business/team). `--org <org_id>` reuses the CODEX_AUTH_ACCOUNT_ID override that every login resolver already honors, so the chosen org is bound for that login and a second workspace can be added on demand instead of always resolving to the default one. - help: parse --org <id> and --org=<id> (rejects a missing value), document it in the login usage line. - codex-manager: runAuthLogin sets the override env var from --org for the invocation, taking precedence over any inherited value. - tests: --org parsing and missing-value cases. * fix(workspace): guard undefined workspace id and cover non-numeric indices (#491) Address review feedback on the workspace command. - guard `target.id` with optional chaining when building the id suffix, matching formatWorkspaceLines, so non-conforming on-disk data cannot throw. - add tests for non-numeric account and workspace indices. * fix(login): scope --org override and restore it after login (#491) The --org flag set process.env.CODEX_AUTH_ACCOUNT_ID without restoring it, so it leaked for the whole process: a later login in the same invocation (menu re-entry) or a reused test worker would silently bind to the stale org. Split runAuthLogin into a thin wrapper that saves the prior override, sets it for the org-bound login, and restores (or deletes) it in a finally, delegating the unchanged flow to runAuthLoginFlow.
N
Neil Daquioag committed
7ecb4adcf731e57591acb0ccea6c4bf50e24679b
Parent: 9807f12
Committed by GitHub <noreply@github.com>
on 5/31/2026, 2:22:38 AM