Skip to content

Commit 03fd2cc

Browse files
committed
余量页排序与自动存档优化
- 优化,按剩余数量重排账号列表 - 改进,刷新完成后自动清理进度提示 - 新增,当前账号进入列表前自动创建存档
1 parent 38eaae4 commit 03fd2cc

4 files changed

Lines changed: 102 additions & 32 deletions

File tree

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,16 @@ python3 -m pip install "git+https://github.com/mileson/CJFCodexSwitcher.git"
9393

9494
- `Enter`:刷新当前页面
9595
- 输入 `#` 序号:切换到对应账号
96-
- 输入 `S`:存档当前账号(仅当前账号未存档时显示)
9796
- 输入 `0`:退出工具
9897

98+
说明:
99+
100+
- 当前账号如果尚未存档,进入查看余量页时会自动创建存档
101+
99102
### Agent / CLI 快捷命令
100103

101104
```bash
102-
# 实时列出账号,按 5 小时余量、1 周余量排序
105+
# 实时列出账号,按 5 小时剩余数量、1 周剩余数量排序
103106
codex-switcher --list
104107

105108
# 以 JSON 输出账号列表
@@ -127,8 +130,8 @@ codex-switcher --refresh
127130

128131
排序规则:
129132

130-
1. 先按 5 小时剩余量降序
131-
2. 相同则按 1 周剩余量降序
133+
1. 先按 5 小时剩余数量降序
134+
2. 相同则按 1 周剩余数量降序
132135
3. 最后按邮箱升序作为 tie-breaker
133136

134137
### 给 Agent 的可复制提示词
@@ -182,7 +185,7 @@ CJFCodexSwitcher/
182185

183186
当前推荐版本 release notes:
184187

185-
- [v0.1.1 Release Notes](docs/releases/v0.1.1.md)
188+
- [v0.1.2 Release Notes](docs/releases/v0.1.2.md)
186189

187190
### License
188191

codex_switcher.py

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,41 @@ def collect_account_entries() -> List[dict]:
12591259

12601260
return entries
12611261

1262+
def is_current_account_saved(current_record_key: str) -> bool:
1263+
"""检查当前账号是否已经存在于存档中"""
1264+
if not current_record_key:
1265+
return False
1266+
1267+
accounts_dir = get_accounts_dir()
1268+
if not accounts_dir.exists():
1269+
return False
1270+
1271+
for auth_file in sorted(accounts_dir.glob('auth_*.json')):
1272+
auth_data = load_auth_data_from_path(auth_file)
1273+
if not auth_data:
1274+
continue
1275+
info = get_account_info(auth_data, str(auth_file))
1276+
if info and info.get('record_key') == current_record_key:
1277+
return True
1278+
return False
1279+
1280+
def ensure_current_account_saved() -> bool:
1281+
"""自动存档当前未存档账号"""
1282+
auth_data = load_current_auth()
1283+
if not auth_data:
1284+
return False
1285+
1286+
info = get_account_info(auth_data, str(get_auth_file()))
1287+
if not info:
1288+
return False
1289+
1290+
record_key = info.get('record_key', '')
1291+
if is_current_account_saved(record_key):
1292+
return True
1293+
1294+
save_name = info.get('email', 'account')
1295+
return save_current_auth(save_name)
1296+
12621297
def clone_display_info(info: dict, entry: dict) -> dict:
12631298
"""克隆用于展示的账号信息"""
12641299
display = dict(info)
@@ -1384,6 +1419,7 @@ def build_view_all_rows(
13841419

13851420
def load_live_account_rows(show_progress: bool = False) -> List[dict]:
13861421
"""加载并实时刷新账号列表"""
1422+
ensure_current_account_saved()
13871423
entries = collect_account_entries()
13881424
refresh_jobs = build_refresh_jobs(entries)
13891425
results = refresh_jobs_live(refresh_jobs, show_progress=show_progress)
@@ -1397,13 +1433,22 @@ def get_remaining_percent(acc: dict, window: str) -> int:
13971433
return -1
13981434
return max(0, 100 - int(used_percent))
13991435

1436+
def get_remaining_count(acc: dict, window: str) -> int:
1437+
"""获取指定窗口的剩余数量"""
1438+
key = 'hourly_remaining' if window == 'hourly' else 'weekly_remaining'
1439+
value = acc.get(key, '')
1440+
try:
1441+
return int(value)
1442+
except (TypeError, ValueError):
1443+
return -1
1444+
14001445
def sort_accounts_for_agent(rows: List[dict]) -> List[dict]:
1401-
"""按 5 小时余量、每周余量排序账号"""
1446+
"""按 5 小时剩余数量、每周剩余数量排序账号"""
14021447
return sorted(
14031448
rows,
14041449
key=lambda acc: (
1405-
-get_remaining_percent(acc, 'hourly'),
1406-
-get_remaining_percent(acc, 'weekly'),
1450+
-get_remaining_count(acc, 'hourly'),
1451+
-get_remaining_count(acc, 'weekly'),
14071452
str(acc.get('email', '')),
14081453
),
14091454
)
@@ -1464,12 +1509,8 @@ def resolve_account_selector(rows: List[dict], selector: str) -> Optional[dict]:
14641509

14651510
def print_view_all_actions(rows: List[dict]):
14661511
"""打印查看余量页面底部操作"""
1467-
current_unsaved = any(row.get('is_current') and not row.get('is_saved') for row in rows)
1468-
14691512
print(f"{Colors.BOLD} 操作面板{Colors.ENDC}")
14701513
print(f"{Colors.DIM} {'─' * 40}{Colors.ENDC}")
1471-
if current_unsaved:
1472-
print(f" {Colors.CYAN}[S]{Colors.ENDC} 存档当前账号")
14731514
print(f" {Colors.CYAN}[编号]{Colors.ENDC} 切换账号")
14741515
print(f" {Colors.CYAN}[0]{Colors.ENDC} 退出工具")
14751516
print(f" {Colors.DIM}[Enter]{Colors.ENDC} 刷新当前页面")
@@ -1481,7 +1522,10 @@ def view_all_accounts():
14811522
clear_screen()
14821523
print_header()
14831524
print(f"\n{Colors.CYAN}>>> 查看所有账号余量{Colors.ENDC}")
1484-
rows = load_live_account_rows(show_progress=True)
1525+
rows = sort_accounts_for_agent(load_live_account_rows(show_progress=True))
1526+
clear_screen()
1527+
print_header()
1528+
print(f"\n{Colors.CYAN}>>> 查看所有账号余量{Colors.ENDC}")
14851529
if rows:
14861530
print_accounts_table(rows, "账号列表")
14871531
else:
@@ -1502,27 +1546,10 @@ def view_all_accounts():
15021546
if choice == '0':
15031547
return
15041548

1505-
current_row = next((row for row in rows if row.get('is_current')), None)
1506-
current_unsaved = bool(current_row and not current_row.get('is_saved'))
1507-
1508-
if choice.lower() == 's':
1509-
if not current_unsaved:
1510-
print(f"\n{Colors.YELLOW} 当前账号已存档,无需重复保存{Colors.ENDC}")
1511-
input(f"{Colors.DIM}按回车键继续...{Colors.ENDC}")
1512-
continue
1513-
1514-
save_name = current_row.get('email', 'account')
1515-
if save_current_auth(save_name):
1516-
print(f"\n{Colors.GREEN} ✓ 当前账号已存档: {save_name}{Colors.ENDC}")
1517-
else:
1518-
print(f"\n{Colors.RED} ✗ 当前账号存档失败{Colors.ENDC}")
1519-
input(f"{Colors.DIM}按回车键继续...{Colors.ENDC}")
1520-
continue
1521-
15221549
try:
15231550
idx = int(choice) - 1
15241551
except ValueError:
1525-
print(f"\n{Colors.RED} 请输入编号、S 或直接回车{Colors.ENDC}")
1552+
print(f"\n{Colors.RED} 请输入编号、0 或直接回车{Colors.ENDC}")
15261553
input(f"{Colors.DIM}按回车键继续...{Colors.ENDC}")
15271554
continue
15281555

docs/releases/v0.1.2.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# CJFCodexSwitcher v0.1.2
2+
3+
这个版本聚焦查看余量页面的排序与交互优化。
4+
5+
## Highlights
6+
7+
- 账号列表排序改为:
8+
- 先按 5 小时剩余数量降序
9+
- 相同再按每周剩余数量降序
10+
- 刷新完成后会清屏重绘,最终界面不再保留进度条历史
11+
- 当前账号如果还没有存档,会在进入查看余量页时自动创建存档
12+
- 查看余量页不再依赖手动输入 `S` 存档当前账号
13+
14+
## Installation
15+
16+
### Homebrew
17+
18+
```bash
19+
brew tap mileson/cjfcodexswitcher && brew install cjfcodexswitcher
20+
```
21+
22+
### pipx
23+
24+
```bash
25+
pipx install git+https://github.com/mileson/CJFCodexSwitcher.git
26+
```
27+
28+
## Verification
29+
30+
- 交互页面已验证:
31+
- 刷新完成后最终界面仅显示列表和操作面板
32+
- 当前账号未存档时会自动创建存档
33+
- `codex-switcher --list --json` 已验证符合新的排序规则
34+
- `openspec validate improve-live-view-ranking-and-autosave` 已通过
35+
36+
## How To Use
37+
38+
- 新手用户:直接运行 `codex-switcher`
39+
- Agent:优先使用 `codex-switcher --list --json``codex-switcher --best --json`
40+
- 如果需要切换到最佳账号:运行 `codex-switcher --switch best`

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "codex-switcher"
7-
version = "0.1.0"
7+
version = "0.1.2"
88
description = "Codex account switcher with live quota inspection and agent-friendly CLI commands"
99
readme = "README.md"
1010
requires-python = ">=3.8"

0 commit comments

Comments
 (0)