You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
agyswap alias: standalone alias management (agyswap alias, agyswap alias <slot> <name>, agyswap alias <slot> --unset)
agyswap enable / agyswap disable: hold a slot out of blind rotation (agyswap switch with no target) without removing its credentials; explicit agyswap switch <slot> still works on a disabled slot
agyswap quota: per-account, per-model Gemini API quota tracking (--refresh, --json), TTL-cached (45s) and merge-safe — never clobbers other accounts' cached data on write
Data directory moved from ~/.agy-swap/ to ~/.agyswap/ — automatically migrated in place on first run; the old path collided with an unrelated third-party tool of a similar name
requires-python raised to >=3.9 (matches rich/textual's actual floor; CI already only tested 3.9+)
rich and textual are now required dependencies (used only by tui/watch) — agyswap is no longer zero-dependency
Fixed a packaging bug where the wheel only ever included agyswap.py and silently dropped modules/ (meaning agyswap ctx ... was likely already broken for pip/pipx installs); [tool.hatch.build.targets.wheel] now explicitly includes modules/**/*.py and modules/**/*.tcss
Fixed the same modules/ gap for Homebrew (Formula/agyswap.rb now installs modules/ alongside the binary) and the curl installer (install.sh now fetches modules/ from the repo tarball); agyswap.py now resolves its own real install location (following symlinks) to find modules/ regardless of install method
docs/index.html (GitHub Pages): updated for the above — new Command Reference cards for alias/enable/disable/quota/tui/watch, corrected "zero dependencies" claims, updated storage layout + a migration note, rich/textual install caveats on the Homebrew/curl tabs, 3 new FAQ entries, and fixed a pre-existing duplicate section-letter bug (two sections were both labeled "G")
docs/index.html's Interactive Architecture Topology (section A): added a "Live TUI Dashboard" node and a new "Live TUI Dashboard Path" preset, added a 5th Engine Core bullet for the quota cache + TUI safety layer, and extended the Google endpoints node to show the quota API — verified visually in a real browser (no overlap/clipping, presets highlight correctly)
assets/architecture.svg / docs/assets/architecture.svg (README's Architecture Overview image, two files kept byte-identical per RELEASING.md): same Live TUI Dashboard node + quota cache bullet + quota API line as above, fixed a stray ~/.agy-swap/ (legacy path) it still showed, fixed the "Zero Dependencies" footer, and fixed its header badge which was still stuck at "V0.1.0" despite the Engine Core box already saying v0.4.0 — verified visually
assets/banner.svg / docs/assets/banner.svg: fixed the "DEPENDENCIES: 0 External Deps" feature pill to say "rich+textual (TUI)" — verified visually. logo.svg/logo-icon.svg checked, no stale claims found
Fixed (cross-review pass)
migrate_legacy_data_dir(): config.json now moves last, not first — an interrupted migration (crash, disk full) used to permanently strand slots//backup/ in the legacy directory since the "already migrated" guard only checked for the new config.json
agyswap quota --json (with a target/slot given) no longer dumps every cached account — it's now scoped to the requested account(s), matching the human-readable output
modules/quota.py's quota_cache.json read-modify-write is now protected by a file lock — concurrent writers (the TUI's background poller and a CLI agyswap quota call) could previously clobber each other's just-written updates
A permanently-failing account (e.g. revoked token) is now retried at most once per TTL window instead of on every single call/poll tick
A malformed/unexpected API response shape no longer crashes agyswap quota or the TUI's refresh worker with a raw traceback — it degrades to stale cached data like any other transient failure
modules/tui/actions.py's mutation functions now wrap every StorageManager call and re-raise as ActionError, so a corrupted-config or disk-full error can no longer escape past the TUI's error-handling layer and crash the whole dashboard
The TUI no longer runs blocking, lock-acquiring account mutations (disable/enable/remove) directly on the UI thread — they now run in a background worker like switch/add already did
Switching accounts from the TUI now shows the same "token expiring soon" warning the CLI already shows
Fixed a _menu_stack leak in the TUI dashboard that made "Back" require an extra Escape press after every completed disable/enable/remove action
Fixed a race where a forced TUI refresh (after an account action) could run concurrently with an in-flight periodic refresh instead of replacing it
agyswap.py's bundled-package bootstrap now requires a marker file (modules/quota.py) instead of a bare directory check, so it can't be fooled into loading an unrelated modules/ folder
install.sh's modules/ fetch now stages the new copy before removing the old one, so a failed download can't leave an existing install with no modules/ at all
agyswap rename now rejects an empty alias (previously silently cleared it, inconsistent with agyswap alias's explicit --unset)
StorageManager.load_config()'s corrupted-config recovery no longer calls print() directly — it could garble the TUI's rendered screen since this runs on background worker threads too