Skip to content
This repository was archived by the owner on Jul 30, 2026. It is now read-only.

refactor(cli): split command modules - #106

Merged
makoMakoGo merged 1 commit into
personal/local-clientsfrom
codex/issue-97-split-cli-main
Jul 4, 2026
Merged

refactor(cli): split command modules#106
makoMakoGo merged 1 commit into
personal/local-clientsfrom
codex/issue-97-split-cli-main

Conversation

@makoMakoGo

@makoMakoGo makoMakoGo commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Split root CLI command implementations into commands/ modules for models, monthly, hourly, clients, pricing, and related command surfaces.
  • Move shared rendering, filter, cache, integration, graph, time metrics, and headless helpers out of main.rs.
  • Move the remaining main.rs unit tests into main_tests.rs while leaving crates/tokscale-cli/tests/cli_tests.rs unchanged.
  • Keep the split clients command on the current count_local_client_messages path from R2: 删除 ParsedMessage 遗留管线 #93/perf(cli): route wrapped and clients through cached folds #101.
  • Drop obsolete macOS star-cache migration tests that no longer belong to the local-only CLI surface.
  • Address review cleanup for blank --home, pricing provider parsing, signed token formatting, Trae runtime creation, duplicate tests, and blank TOKSCALE_HEADLESS_DIR.

Closes #97

Built on the current personal/local-clients baseline.

Validation

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets
  • cargo test --workspace (1886 passed, 4 ignored)
  • cargo test -p tokscale-cli --bin tokscale main_tests (96 passed, 602 filtered out)
  • wc -l crates/tokscale-cli/src/main.rs -> 881
  • git diff -- crates/tokscale-cli/tests/cli_tests.rs -> no diff
  • rg -n "parse_local_clients|ParsedMessage|ParsedMessages" crates/tokscale-cli/src crates/tokscale-core/src returns no matches
  • rg -n "load_star_cache|star-cache|star cache|star_cache" crates/tokscale-cli/src/main_tests.rs returns no matches

Summary by CodeRabbit

  • 新功能

    • 新增多项命令行能力:客户端清单、图表导出、小时/月度/模型/时间指标报告,以及定价查询与覆盖项查看。
    • 增加 headless 捕获与各类集成命令支持,输出更灵活,可选择 JSON 或终端表格/文本格式。
    • 改进加载提示、日期范围显示和缓存相关提示,提升命令执行体验。
  • 修复

    • 优化本地缓存与同步判断,减少重复提示与错误输出。
    • 提升日期过滤、客户端选择和输出格式的一致性。

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

本次变更将原本集中在 tokscale-cli 的 main.rs 中的命令逻辑,按功能拆分为 commands/ 目录下的多个模块(cache、clients、graph、headless、hourly、integrations、models、monthly、pricing、render、shared、time_metrics),并新增大量单元测试覆盖这些函数的解析与格式化逻辑。

Changes

CLI 命令模块拆分

Layer / File(s) Summary
模块注册
crates/tokscale-cli/src/commands/mod.rs
新增一批 pub mod 声明,将各子模块导出为公开入口。
共享工具:过滤/Cursor/日期/home
crates/tokscale-cli/src/commands/shared.rs
新增客户端过滤器构建、Cursor/Warp 设置警告与自动同步、usage 父级参数校验、home/环境根解析、日期筛选与区间标签、headless 根目录解析。
渲染与格式化工具
crates/tokscale-cli/src/commands/render.rs
新增 LightSpinner、货币/数字/token 格式化、模型名规范化去重、表格边框着色函数。
轻量缓存与 TUI 默认过滤
crates/tokscale-cli/src/commands/cache.rs
新增写缓存决策、默认 TUI 过滤集合解析、轻量缓存写入与 TUI 预热函数。
Models 报表
crates/tokscale-cli/src/commands/models.rs
新增 run_models_report,支持 JSON 与 compact/非 compact 表格输出,并调用缓存写入。
Monthly 报表
crates/tokscale-cli/src/commands/monthly.rs
新增 run_monthly_report,支持 JSON 与表格输出。
Hourly 报表
crates/tokscale-cli/src/commands/hourly.rs
新增 run_hourly_report,支持 JSON 与 compact/非 compact 表格输出(含缓存倍率)。
Time Metrics 报表
crates/tokscale-cli/src/commands/time_metrics.rs
新增 run_time_metrics_report 与时长格式化函数。
Graph 导出
crates/tokscale-cli/src/commands/graph.rs
新增导出数据结构、映射函数与 run_graph_command。
Pricing 查询
crates/tokscale-cli/src/commands/pricing.rs
新增定价查询与覆盖列表命令。
Clients 客户端信息
crates/tokscale-cli/src/commands/clients.rs
新增 run_clients_command 及路径解析辅助函数。
Headless 采集
crates/tokscale-cli/src/commands/headless.rs
新增子进程捕获与 headless 命令入口,含超时处理。
集成命令分发
crates/tokscale-cli/src/commands/integrations.rs
新增 Codex/Cursor/Antigravity/Trae/Warp 子命令分发与 Trae variant 解析。
单元测试
crates/tokscale-cli/src/main_tests.rs
新增覆盖上述各模块解析/格式化/校验逻辑的测试用例。

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as run_headless_command
  participant Capture as run_capture_command
  participant Child as 子进程(codex)
  participant File as 输出文件

  CLI->>Capture: 启动并传入超时
  Capture->>Child: spawn 子进程
  Child-->>Capture: stdout 流
  Capture->>File: 写入捕获内容
  Capture-->>CLI: CaptureCommandOutcome(exit_code, timed_out)
  CLI-->>CLI: 超时则 exit(124),否则按 exit_code 处理
Loading
sequenceDiagram
  participant Command as run_*_report
  participant Shared as shared.rs
  participant Runtime as tokio Runtime
  participant CursorSync as cursor::sync

  Command->>Shared: should_auto_sync_cursor_for_local_report
  Shared-->>Command: true/false
  Command->>Shared: auto_sync_cursor_for_local_report
  Shared->>Runtime: build_runtime
  Runtime->>CursorSync: run sync
  CursorSync-->>Shared: SyncCursorResult
  Shared-->>Command: warnings via emit_cursor_sync_warning
Loading

Possibly related PRs

  • makoMakoGo/tokscale#25: 主 PR 新增的 hourly.rs 报表/表格渲染逻辑与该 PR 的按小时用量布局及列清理改动重叠。
  • makoMakoGo/tokscale#41: 主 PR 新增的 run_warm_tui_cache 与默认 TUI 客户端过滤对齐逻辑与该 PR 中缓存键/默认客户端集合变更直接相关。
  • makoMakoGo/tokscale#75: 主 PR 新增的 run_clients_command 及 antigravity-cli 路径解析逻辑与该 PR 的本地客户端展示/扫描路径改动直接对应。

Poem

一只兔子搬砖忙,
main.rs 太胖要减肥,
拆成模块排整齐,
cache、clients、graph 各归位,
测试跟着蹦蹦跳,
代码清爽心欢喜 🐇✂️📦

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed 代码将 main.rs 中的命令实现和测试迁移到 commands/* 与 main_tests.rs,符合 #97 的拆分目标。
Out of Scope Changes check ✅ Passed 新增内容都围绕 CLI 命令拆分、共享辅助和测试迁移,没有明显与 #97 无关的功能扩张。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了将 CLI 命令拆分到多个模块的主要改动。
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-97-split-cli-main

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@makoMakoGo makoMakoGo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#97 的决策记录看了这次拆分,整体方向符合“函数级平移 / main.rs 保留 clap+dispatch / 不引入 trait 层”。

需要先修一个迁移遗漏:main_tests.rs 里两个 macOS-only 的 load_star_cache 测试被原样搬出来了,但新的 test module 只 import 了 cache/clients/integrations/render/sharedmain.rs 也不再把 load_star_cache 带进 super::*。这些测试在 Linux 不会编译到,所以当前 cargo test --workspace 可能看起来是绿的;在 macOS target 上会因找不到 load_star_cache 直接编译失败。

处理方式建议保持边界干净:把测试移动到现在真正拥有 load_star_cache 的模块,或显式用现在的 owner 路径;如果 #102 已经删除 hosted/star-cache surface,那就删掉这两条陈旧测试和相关文档引用,不要为旧 surface 做兜底。

@makoMakoGo
makoMakoGo force-pushed the codex/issue-97-split-cli-main branch from 9e4839d to faaa7b0 Compare July 3, 2026 13:19
@makoMakoGo
makoMakoGo changed the base branch from codex/issue-91-local-only-surface to personal/local-clients July 3, 2026 13:19

@makoMakoGo makoMakoGo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retarget 后重新看了一遍。

clients 拆分现在已经对齐 personal/local-clients baseline:用的是 count_local_client_messages,没有把旧的 parse_local_clients 路径带回来,这块 OK。

仍需要修一个 blocker:main_tests.rs 里还保留了两个 macOS-only load_star_cache 测试。这个 PR 的新 main.rs 不再拥有/导入 load_star_cache,所以 Linux 上会因为 cfg 没暴露而绿,macOS target 会在编译这些测试时找不到符号。既然 retarget 到 local-clients 后 hosted/star-cache surface 已经不是这个 PR 的职责,最干净的处理是删除这两条陈旧测试;不要为了它在 main.rsmain_tests.rs 重新兜底引入旧 surface。

Comment thread crates/tokscale-cli/src/main_tests.rs
@makoMakoGo
makoMakoGo force-pushed the codex/issue-97-split-cli-main branch from faaa7b0 to 22b3221 Compare July 3, 2026 13:30

@makoMakoGo makoMakoGo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after the cleanup.

The previous blocker is fixed: the obsolete macOS load_star_cache migration tests are gone from main_tests.rs, and there is no new import/fallback/compat bridge added for that old surface. I resolved the old inline thread.

The retargeted clients split still stays on count_local_client_messages, and the changed-file set remains scoped to the CLI split. From this review pass, this looks good to merge once you are ready to move the PR out of draft / after your normal validation gates pass.

@makoMakoGo
makoMakoGo marked this pull request as ready for review July 3, 2026 13:35

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 15 files

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Comment thread crates/tokscale-cli/src/commands/pricing.rs
Comment thread crates/tokscale-cli/src/commands/clients.rs
Comment thread crates/tokscale-cli/src/commands/render.rs
Comment thread crates/tokscale-cli/src/commands/integrations.rs Outdated
Comment thread crates/tokscale-cli/src/main_tests.rs Outdated
Comment thread crates/tokscale-cli/src/commands/pricing.rs Outdated
Comment thread crates/tokscale-cli/src/commands/shared.rs Outdated
@codspeed-hq

codspeed-hq Bot commented Jul 3, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 27 untouched benchmarks


Comparing codex/issue-97-split-cli-main (212d84b) with personal/local-clients (be21304)

Open in CodSpeed

@makoMakoGo makoMakoGo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed after moving out of draft.

LGTM for #97. The previous blocker is fixed: the obsolete macOS load_star_cache tests are gone, with no new import/fallback/compat bridge. clients remains on count_local_client_messages, main.rs stays at the intended clap + dispatch shape, and the PR remains scoped to the CLI split.

Cubic opened a few new threads after draft removal. I checked the important ones against the personal/local-clients base: they are pre-existing behavior moved out of main.rs, not regressions introduced by this split. They can be tracked separately if desired, but I would not block this refactor PR on them.

GitHub does not allow me to formally approve my own PR, so leaving this as a review comment rather than an approval.

@makoMakoGo makoMakoGo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cubic triage after ready-for-review:

  1. commands/pricing.rs:107 — reject. The unwrap_or(0.0) behavior for base input/output pricing is intentional for the local CLI pricing contract: a resolved pricing record has numeric base pricing fields, and missing upstream values are normalized to zero for local cost math/reporting. Cache read/write pricing remains optional because it is an extra pricing lane, not the base lane. Changing input/output to Option<f64> would be a JSON output contract change, not a refactor, and contradicts the current design decision. I am resolving this thread.

  2. commands/pricing.rs:30 — design decision, not a split regression. If we want to improve it, the clean choice is not a tiny branch patch; decide whether invalid --provider is a clap argument error or a JSON-mode command error, then make that contract explicit with tests.

  3. commands/clients.rs:14 — real edge case, but Cubic's suggested fallback is the wrong shape. --home "" is an explicit invalid override, not an omitted flag. Clean fix: validate the global --home value at the CLI boundary and reject empty/whitespace-only values, instead of silently falling back to the real home.

  4. commands/render.rs:215 — real bug in the formatter for negative values with digit counts divisible by three. Clean fix: handle the sign separately and add the missing -123, -123456, and i64::MIN-safe coverage.

  5. commands/integrations.rs:64 — valid cleanup. Clean fix: construct the Tokio runtime only in branches that actually call async Trae operations; manual login/logout/status should not inherit runtime creation as a failure surface.

  6. main_tests.rs:311 — valid cleanup. Delete the duplicate default-client test and keep one canonical assertion.

  7. commands/shared.rs:603 — valid cleanup. Match the existing env-root convention: a blank/whitespace-only TOKSCALE_HEADLESS_DIR should be treated like unset, with a focused unit test.

@makoMakoGo
makoMakoGo force-pushed the codex/issue-97-split-cli-main branch from 22b3221 to 212d84b Compare July 4, 2026 03:46

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (7)
crates/tokscale-cli/src/main_tests.rs (1)

778-793: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

环境变量清理未做异常安全处理

antigravity_cli_conversations_path_falls_back_for_blank_envheadless_roots_ignore_blank_env_override 都是先 set_var → 执行断言 → 最后才恢复原值。如果中间的 assert_eq!/assert! 失败导致 panic,恢复逻辑不会执行,GEMINI_CLI_HOME / TOKSCALE_HEADLESS_DIR 会保持被污染的状态,进而可能导致同一测试进程中后续测试(即使标了 #[serial],也只能防止并发写入,不能防止 panic 后状态泄漏)产生级联失败,增加排查难度。

建议使用 RAII guard(在 Drop::drop 中恢复)或 std::panic::catch_unwind 包裹断言部分,确保无论成功还是 panic 都能恢复环境变量。

♻️ 建议修复方向(以 antigravity_cli_conversations_path_falls_back_for_blank_env 为例)
+struct EnvVarGuard {
+    key: &'static str,
+    previous: Option<String>,
+}
+
+impl EnvVarGuard {
+    fn set(key: &'static str, value: &str) -> Self {
+        let previous = std::env::var(key).ok();
+        unsafe { std::env::set_var(key, value) };
+        Self { key, previous }
+    }
+}
+
+impl Drop for EnvVarGuard {
+    fn drop(&mut self) {
+        match &self.previous {
+            Some(value) => unsafe { std::env::set_var(self.key, value) },
+            None => unsafe { std::env::remove_var(self.key) },
+        }
+    }
+}
+
 #[test]
 #[serial_test::serial]
 fn antigravity_cli_conversations_path_falls_back_for_blank_env() {
-    let previous = std::env::var("GEMINI_CLI_HOME").ok();
-    unsafe { std::env::set_var("GEMINI_CLI_HOME", "   ") };
+    let _guard = EnvVarGuard::set("GEMINI_CLI_HOME", "   ");

     assert_eq!(
         antigravity_cli_conversations_path("/tmp/home", true),
         PathBuf::from("/tmp/home/.gemini/antigravity-cli/conversations")
     );
-
-    match previous {
-        Some(value) => unsafe { std::env::set_var("GEMINI_CLI_HOME", value) },
-        None => unsafe { std::env::remove_var("GEMINI_CLI_HOME") },
-    }
 }

Also applies to: 795-812

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/main_tests.rs` around lines 778 - 793, The test setup
in antigravity_cli_conversations_path_falls_back_for_blank_env and
headless_roots_ignore_blank_env_override mutates process environment state and
only restores it after the assertions, so a panic can leak GEMINI_CLI_HOME or
TOKSCALE_HEADLESS_DIR into later tests. Update the test helpers around
antigravity_cli_conversations_path and headless_roots_ignore_blank_env_override
to restore the original env value via RAII (a guard with Drop) or another
panic-safe cleanup approach, so the cleanup always runs even if an assertion
fails.
crates/tokscale-cli/src/commands/shared.rs (1)

115-131: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议用 ClientId::as_str() 替代硬编码字符串比较。

client_filter_includes_cursorclient_filter_explicitly_requests_cursorclient_filter_explicitly_requests_warp 三个函数都用字面量 "cursor"/"warp" 做比较,而不是复用 ClientId::Cursor.as_str()/ClientId::Warp.as_str()。如果未来 ClientId::as_str() 的输出发生变化,这里会静默失效而不报编译错误。

♻️ 建议改动示例
 pub(crate) fn client_filter_includes_cursor(clients: &Option<Vec<String>>) -> bool {
     clients
         .as_ref()
-        .is_none_or(|sources| sources.iter().any(|source| source == "cursor"))
+        .is_none_or(|sources| sources.iter().any(|source| source == ClientId::Cursor.as_str()))
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/commands/shared.rs` around lines 115 - 131, The three
client filter helpers in shared.rs currently compare against hardcoded "cursor"
and "warp" strings, so update client_filter_includes_cursor,
client_filter_explicitly_requests_cursor, and
client_filter_explicitly_requests_warp to use ClientId::Cursor.as_str() and
ClientId::Warp.as_str() instead. Keep the existing Option<Vec<String>> logic
intact, but route all matching through the ClientId enum’s as_str() so the
behavior stays aligned with ClientId if its string representation changes.
crates/tokscale-cli/src/commands/integrations.rs (1)

62-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

多处重复创建 tokio::runtime::Runtime::new() 执行单个异步调用

Line 101 与 Line 180 各自新建了一个完整的多线程 Runtime 仅用于执行一次 block_on 调用,commands/graph.rs(Line 233-248)和 commands/pricing.rs(Line 32-36)中也是同样的模式。这是跨文件重复的样板代码,且默认的多线程 runtime 对单次异步调用来说存在不必要的线程池创建开销。可以在共享模块中提取一个 fn block_on_async<F: Future>(fut: F) -> Result<F::Output> 之类的辅助函数,内部使用 Builder::new_current_thread().enable_all().build()?,供各命令模块复用。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/commands/integrations.rs` around lines 62 - 193,
Repeated ad hoc creation of tokio::runtime::Runtime in run_trae_command and
similar command handlers is unnecessary and duplicated across modules. Extract a
shared helper such as block_on_async in a common commands/util module, and have
run_trae_command, graph.rs, and pricing.rs call it instead of building a new
multi-thread runtime for each single block_on use. Implement the helper with a
current-thread runtime via Builder::new_current_thread().enable_all().build()?
and return the wrapped async result consistently.
crates/tokscale-cli/src/commands/clients.rs (1)

299-306: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

基于字符串硬编码判断 amp 客户端,建议改用枚举比较

row.client == "amp" 依赖 ClientId::as_str() 的具体字符串值来判断展示文案("source" vs "sessions"),一旦该字符串常量发生变化容易悄悄失效且不会有编译期提示。可以在构造 ClientRow 时(Line 117-260 循环内,此时仍持有 client: ClientId)直接按枚举比较并把结果存入结构体字段,而不是在渲染阶段对字符串做二次判断。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/commands/clients.rs` around lines 299 - 306, The
display-label logic is still branching on the string value of row.client, which
should be replaced with enum-based selection. Move this decision into the
ClientRow construction path in the clients loop where ClientId is still
available, store the derived label field on ClientRow, and have the rendering
code only read that field instead of checking row.client == "amp". Use ClientId
and ClientRow as the key symbols to update.
crates/tokscale-cli/src/commands/pricing.rs (1)

15-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

model_id 参数复用为子命令分发标记("list-overrides"

list-overrides 作为特殊的 model_id 值来分发到 run_pricing_list_overrides,这种基于魔法字符串的函数内部分发方式略显隐晦,容易与真实模型 ID 冲突(虽然概率很低)。如果 CLI 层已有独立的子命令定义这只是别名兼容处理,可以保留;否则更清晰的做法是在 clap 子命令层面区分。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/commands/pricing.rs` around lines 15 - 17, The
current `pricing` command handler uses the `model_id` parameter in `run_pricing`
as a magic dispatch flag for `"list-overrides"`, which can conflict with real
model IDs. Update the CLI flow so `run_pricing_list_overrides` is selected
through a dedicated clap subcommand or explicit command variant instead of
branching inside `run_pricing`; if this value must remain for backward
compatibility, keep it only as an alias path and make the main dispatch use the
named command structure.
crates/tokscale-cli/src/commands/models.rs (2)

19-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

四个报表命令存在大量重复的启动样板代码。

run_models_report 中 spinner 启动、auto_sync_cursor_for_local_reportsetup_warnings_for_reportuse_env_roots 的调用顺序,与 monthly.rshourly.rstime_metrics.rs 中几乎完全一致(仅细节参数不同)。这种跨四个文件的重复逻辑意味着未来任何一处 cursor 同步/警告逻辑变更都需要同步修改四处,容易产生行为分叉风险。

建议将这段样板逻辑抽取为 commands/shared.rs 中的一个统一辅助函数(例如返回一个包含 spinner、cursor_sync_result、setup_warnings、use_env_roots 的上下文结构体),供四个命令复用。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/commands/models.rs` around lines 19 - 52, The startup
boilerplate in run_models_report is duplicated across the report commands,
including spinner setup, auto_sync_cursor_for_local_report,
setup_warnings_for_report, and use_env_roots. Extract this shared sequence into
a reusable helper in commands/shared.rs that returns a small context object (for
example, with spinner, cursor_sync_result, setup_warnings, and use_env_roots),
and update run_models_report plus the matching monthly, hourly, and time_metrics
command paths to call that helper instead of repeating the same initialization
logic.

36-38: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

将一次性 CLI runtime 改成 current_thread
run_models_report 这里只做一次 block_onmonthly.rs / hourly.rs / time_metrics.rs 也一样;统一改用 tokio::runtime::Builder::new_current_thread().enable_all().build()?,可以减少线程池初始化开销。tokscale_core 里的 tokio::join!tokio::spawn 不会阻止这个切换。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/tokscale-cli/src/commands/models.rs` around lines 36 - 38, The
one-shot CLI runtime setup in run_models_report still uses Runtime, but it only
performs a single block_on; switch this and the similar monthly.rs, hourly.rs,
and time_metrics.rs paths to
tokio::runtime::Builder::new_current_thread().enable_all().build()? to avoid
thread-pool overhead. Update the runtime creation code in the affected command
entrypoints while keeping the existing block_on logic and leaving tokscale_core
usage (including tokio::join! and tokio::spawn) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/tokscale-cli/src/commands/clients.rs`:
- Around line 299-306: The display-label logic is still branching on the string
value of row.client, which should be replaced with enum-based selection. Move
this decision into the ClientRow construction path in the clients loop where
ClientId is still available, store the derived label field on ClientRow, and
have the rendering code only read that field instead of checking row.client ==
"amp". Use ClientId and ClientRow as the key symbols to update.

In `@crates/tokscale-cli/src/commands/integrations.rs`:
- Around line 62-193: Repeated ad hoc creation of tokio::runtime::Runtime in
run_trae_command and similar command handlers is unnecessary and duplicated
across modules. Extract a shared helper such as block_on_async in a common
commands/util module, and have run_trae_command, graph.rs, and pricing.rs call
it instead of building a new multi-thread runtime for each single block_on use.
Implement the helper with a current-thread runtime via
Builder::new_current_thread().enable_all().build()? and return the wrapped async
result consistently.

In `@crates/tokscale-cli/src/commands/models.rs`:
- Around line 19-52: The startup boilerplate in run_models_report is duplicated
across the report commands, including spinner setup,
auto_sync_cursor_for_local_report, setup_warnings_for_report, and use_env_roots.
Extract this shared sequence into a reusable helper in commands/shared.rs that
returns a small context object (for example, with spinner, cursor_sync_result,
setup_warnings, and use_env_roots), and update run_models_report plus the
matching monthly, hourly, and time_metrics command paths to call that helper
instead of repeating the same initialization logic.
- Around line 36-38: The one-shot CLI runtime setup in run_models_report still
uses Runtime, but it only performs a single block_on; switch this and the
similar monthly.rs, hourly.rs, and time_metrics.rs paths to
tokio::runtime::Builder::new_current_thread().enable_all().build()? to avoid
thread-pool overhead. Update the runtime creation code in the affected command
entrypoints while keeping the existing block_on logic and leaving tokscale_core
usage (including tokio::join! and tokio::spawn) unchanged.

In `@crates/tokscale-cli/src/commands/pricing.rs`:
- Around line 15-17: The current `pricing` command handler uses the `model_id`
parameter in `run_pricing` as a magic dispatch flag for `"list-overrides"`,
which can conflict with real model IDs. Update the CLI flow so
`run_pricing_list_overrides` is selected through a dedicated clap subcommand or
explicit command variant instead of branching inside `run_pricing`; if this
value must remain for backward compatibility, keep it only as an alias path and
make the main dispatch use the named command structure.

In `@crates/tokscale-cli/src/commands/shared.rs`:
- Around line 115-131: The three client filter helpers in shared.rs currently
compare against hardcoded "cursor" and "warp" strings, so update
client_filter_includes_cursor, client_filter_explicitly_requests_cursor, and
client_filter_explicitly_requests_warp to use ClientId::Cursor.as_str() and
ClientId::Warp.as_str() instead. Keep the existing Option<Vec<String>> logic
intact, but route all matching through the ClientId enum’s as_str() so the
behavior stays aligned with ClientId if its string representation changes.

In `@crates/tokscale-cli/src/main_tests.rs`:
- Around line 778-793: The test setup in
antigravity_cli_conversations_path_falls_back_for_blank_env and
headless_roots_ignore_blank_env_override mutates process environment state and
only restores it after the assertions, so a panic can leak GEMINI_CLI_HOME or
TOKSCALE_HEADLESS_DIR into later tests. Update the test helpers around
antigravity_cli_conversations_path and headless_roots_ignore_blank_env_override
to restore the original env value via RAII (a guard with Drop) or another
panic-safe cleanup approach, so the cleanup always runs even if an assertion
fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 127259f9-c885-409d-add7-92832c0bda08

📥 Commits

Reviewing files that changed from the base of the PR and between be21304 and 212d84b.

📒 Files selected for processing (15)
  • crates/tokscale-cli/src/commands/cache.rs
  • crates/tokscale-cli/src/commands/clients.rs
  • crates/tokscale-cli/src/commands/graph.rs
  • crates/tokscale-cli/src/commands/headless.rs
  • crates/tokscale-cli/src/commands/hourly.rs
  • crates/tokscale-cli/src/commands/integrations.rs
  • crates/tokscale-cli/src/commands/mod.rs
  • crates/tokscale-cli/src/commands/models.rs
  • crates/tokscale-cli/src/commands/monthly.rs
  • crates/tokscale-cli/src/commands/pricing.rs
  • crates/tokscale-cli/src/commands/render.rs
  • crates/tokscale-cli/src/commands/shared.rs
  • crates/tokscale-cli/src/commands/time_metrics.rs
  • crates/tokscale-cli/src/main.rs
  • crates/tokscale-cli/src/main_tests.rs

@makoMakoGo makoMakoGo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed head 212d84b4.

LGTM. The Cubic cleanup pass is now resolved cleanly:

  • --home empty/blank is rejected at the clap boundary instead of falling through to path handling.
  • pricing --provider is now a clap-level enum-like parser error, so invalid providers do not enter runtime lookup or JSON command-error handling.
  • format_tokens_with_commas now handles the sign separately with unsigned_abs(), including i64::MIN coverage.
  • Trae runtime creation is no longer eager for manual login/logout/status.
  • The duplicate default-client test is gone.
  • Blank TOKSCALE_HEADLESS_DIR follows the existing blank-env semantics and falls back to default roots.

All Cubic threads are resolved. This still reads as a scoped #97 CLI split, with the review cleanups folded in without compatibility bridges or fallback behavior.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A2: 拆分 CLI main.rs

1 participant