feat(droid): attribute session usage to agent roles - #147
Conversation
Walkthrough本次变更重构了 v4 CLI 的解析、执行计划、错误与 TUI 退出流程,统一本地 JSON 报表信封,移除 Cursor/Trae 集成及旧凭据管理,并更新 Codex、Droid、缓存、客户端目录、测试和相关文档。 ChangesCLI 与报表执行
客户端与凭据边界
文档与验证
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/tokscale-cli/src/commands/clients.rs (1)
119-151: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win仅在选择 OpenCode 时探测其数据库。
all_clients现在代表显式范围,但discover_opencode_dbs仍无条件执行。因此tokscale clients --client codex可能进行无关 I/O,并在 JSONhealth中报告范围外的 OpenCode 故障。建议修改
- let opencode_auto_dbs = match discover_opencode_dbs(&opencode_data_root) { - Ok(paths) => paths, - Err(_) => { - health.record_unavailable_source(ClientId::OpenCode.as_str()); - Vec::new() - } - }; + let opencode_auto_dbs = if selected_clients.contains(&ClientId::OpenCode) { + match discover_opencode_dbs(&opencode_data_root) { + Ok(paths) => paths, + Err(_) => { + health.record_unavailable_source(ClientId::OpenCode.as_str()); + Vec::new() + } + } + } else { + Vec::new() + };🤖 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 119 - 151, Update the OpenCode discovery flow around all_clients and discover_opencode_dbs so it only calls discover_opencode_dbs when ClientId::OpenCode is included in the explicitly selected clients; otherwise use an empty database list without recording OpenCode health failures. Preserve the existing discovery error handling when OpenCode is selected.
🧹 Nitpick comments (4)
crates/tokscale-cli/src/tui/cache.rs (1)
1935-1944: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win不要在测试中硬编码 Unix 本地路径。
/tmp/other-tokscale-home违反测试路径约束,也引入不必要的平台假设。请基于当前TempDir创建不同的 scope 值。建议修改
let other_home_scope = CacheReportScope::new( - Some("/tmp/other-tokscale-home".to_string()), + Some( + temp_dir + .path() + .join("other-home") + .to_string_lossy() + .into_owned(), + ),As per coding guidelines, “Use temporary directories or fixtures instead of developer-local paths in tests.” <coding_guidelines>
🤖 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/tui/cache.rs` around lines 1935 - 1944, Update the test around other_home_scope to derive its home path from the existing TempDir rather than hardcoding "/tmp/other-tokscale-home". Use a distinct child path or otherwise different scope value based on that temporary directory, preserving the expected CacheResult::Miss assertion.Source: Coding guidelines
crates/tokscale-cli/src/tui/ui/header.rs (1)
225-237: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win统一隔离测试文件系统与用户设置。 当前测试或读取开发者的真实配置,或依赖固定的本机风格绝对路径。
crates/tokscale-cli/src/tui/ui/header.rs#L225-L237: 注入测试Settings或临时 home。crates/tokscale-cli/src/tui/app.rs#L2294-L2305: 改用现有test_settings()fixture。crates/tokscale-cli/src/tui/app.rs#L2344-L2355: 改用现有test_settings()fixture。crates/tokscale-cli/src/tui/app.rs#L2394-L2405: 改用现有test_settings()fixture。crates/tokscale-cli/src/tui/app.rs#L2435-L2446: 改用现有test_settings()fixture。crates/tokscale-cli/src/tui/app.rs#L3509-L3521: 改用现有test_settings()fixture。crates/tokscale-cli/src/commands/usage/codex.rs#L203-L225: 从TempDir构造 home 和CODEX_HOME。As per coding guidelines, “Use temporary directories or fixtures instead of developer-local paths in tests.”
🤖 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/tui/ui/header.rs` around lines 225 - 237, Isolate all affected tests from developer-local configuration and fixed paths: in crates/tokscale-cli/src/tui/ui/header.rs lines 225-237, inject test Settings or a temporary home; in crates/tokscale-cli/src/tui/app.rs lines 2294-2305, 2344-2355, 2394-2405, 2435-2446, and 3509-3521, reuse the existing test_settings() fixture; and in crates/tokscale-cli/src/commands/usage/codex.rs lines 203-225, construct the home and CODEX_HOME from a TempDir.Source: Coding guidelines
crates/tokscale-cli/src/tui/data/mod.rs (1)
120-129: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value提取重复的
home_dir解析逻辑。这三处具有完全相同的逻辑(解析
home_dir并决定use_env_roots)。建议将其提取为DataLoader的辅助方法(例如resolve_home(&self) -> Result<(String, bool)>),以减少代码重复。
crates/tokscale-cli/src/tui/data/mod.rs#L120-L129: 在prepare中复用提取出的resolve_home方法。crates/tokscale-cli/src/tui/data/mod.rs#L196-L205: 在execute_with_diagnostics中复用。crates/tokscale-cli/src/tui/data/mod.rs#L278-L287: 在测试的load_with_pricing中复用。♻️ 提取辅助方法的重构建议
首先在
DataLoader中添加辅助方法:fn resolve_home(&self) -> Result<(String, bool)> { match &self.home_dir { Some(home) => Ok((home.to_string_lossy().into_owned(), false)), None => Ok(( dirs::home_dir() .ok_or_else(|| anyhow::anyhow!("Could not find home directory"))? .to_string_lossy() .into_owned(), true, )), } }随后在这三个地方替换为:
let (home, use_env_roots) = self.resolve_home()?;(注:对于测试模块中的
loader变量,请使用loader.resolve_home()?)🤖 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/tui/data/mod.rs` around lines 120 - 129, 提取重复的 home_dir 解析逻辑:在 DataLoader 中新增 resolve_home 方法,返回与现有逻辑一致的 (String, bool) 结果,并保留找不到 home 目录时的错误行为。更新 crates/tokscale-cli/src/tui/data/mod.rs#L120-L129 的 prepare、#L196-L205 的 execute_with_diagnostics,以及#L278-L287 的测试 load_with_pricing,分别复用 self.resolve_home()? 或 loader.resolve_home()?。crates/tokscale-core/src/message_cache.rs (1)
255-283: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win补充退休解析器标签的持久化回归测试。 固定旧
Cursor/Trae值仍解码为RetiredCursor/RetiredTrae,并保持stable_name()的cursor/trae映射,避免后续重排枚举时静默破坏现有缓存。🤖 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-core/src/message_cache.rs` around lines 255 - 283, 在消息缓存解析器标签相关测试中补充持久化回归测试:验证固定的旧 Cursor 和 Trae bincode 值仍分别解码为 RetiredCursor 与 RetiredTrae,并验证 stable_name() 对这两个退休标签仍返回 cursor 和 trae。测试应固定原始判别值,确保后续枚举重排不会改变现有缓存兼容性。Source: Coding guidelines
🤖 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.
Inline comments:
In `@crates/tokscale-cli/src/cli.rs`:
- Around line 522-527: Remove the `token` command-line argument from the `Login`
command and obtain Warp credentials through a non-argv mechanism, such as
no-echo interactive input, stdin, a restricted-permission file, or a dedicated
environment variable. Preserve the existing `cookie` mode behavior while
ensuring bearer tokens and cookie header values are never exposed in shell
history or process listings.
In `@crates/tokscale-cli/src/commands/usage/codex.rs`:
- Around line 73-77: Update read_current_credentials to retain the first
parse/read error from parse_auth_file, continue checking all remaining
current_auth_paths and keychain sources, and return the first error only when no
valid credentials are found. Add a regression test covering a corrupted
preferred credential path followed by a valid fallback.
In `@crates/tokscale-cli/tests/cli_tests.rs`:
- Line 2468: Update the JSON assertions in the affected CLI tests to inspect the
`data` envelope rather than the root `json` object. Apply this to the
`totalReasoning`, `warnings`, and `diagnostics` checks, ensuring the assertions
fail when any prohibited field appears inside `data`.
In `@crates/tokscale-cli/tests/tui_exit_tests.rs`:
- Around line 128-130: Update the readiness wait in the TUI test so a
recv_timeout failure explicitly terminates and waits for the child process
before propagating the test failure. Ensure the associated reader thread is also
cleaned up on this failure path, while preserving the existing success behavior
after ready_rx receives a signal.
In `@crates/tokscale-core/src/adapters/file.rs`:
- Around line 35-40: 将 crates/tokscale-core/src/adapters/file.rs:35-40 的
CachedFileAdapter 依赖钩子改为返回路径集合;在 crates/tokscale-core/src/adapters/file.rs:61-74
更新构造器以接收多依赖回调,并在 crates/tokscale-core/src/adapters/file.rs:111-119
将所有依赖纳入扫描单元指纹。更新 crates/tokscale-core/src/sessions/droid.rs:346-358,使继承角色返回子
transcript、父 settings 和父 Mission features,并添加父 feature 变化使子代理缓存失效的回归测试。
In `@docs/adr/0015-local-only-product-surface.md`:
- Around line 7-8: Update the Decision section of ADR 0015, specifically the
requirement around lines 34–36, to remove the Cursor and Trae references or
explicitly mark that requirement as superseded by ADR 0024. Ensure the ADR no
longer conflicts with its statement that these integrations are unmaintained.
In `@docs/adr/0023-provider-owned-credentials.md`:
- Around line 42-52: Update the Cursor section in ADR 0023 to be historical
context only, removing the claim that local reports currently parse Cursor usage
CSV files or preserve related behavior. Replace the deprecated behavior details
with a concise reference to ADR 0024 as the authoritative record, while
retaining only necessary migration context.
---
Outside diff comments:
In `@crates/tokscale-cli/src/commands/clients.rs`:
- Around line 119-151: Update the OpenCode discovery flow around all_clients and
discover_opencode_dbs so it only calls discover_opencode_dbs when
ClientId::OpenCode is included in the explicitly selected clients; otherwise use
an empty database list without recording OpenCode health failures. Preserve the
existing discovery error handling when OpenCode is selected.
---
Nitpick comments:
In `@crates/tokscale-cli/src/tui/cache.rs`:
- Around line 1935-1944: Update the test around other_home_scope to derive its
home path from the existing TempDir rather than hardcoding
"/tmp/other-tokscale-home". Use a distinct child path or otherwise different
scope value based on that temporary directory, preserving the expected
CacheResult::Miss assertion.
In `@crates/tokscale-cli/src/tui/data/mod.rs`:
- Around line 120-129: 提取重复的 home_dir 解析逻辑:在 DataLoader 中新增 resolve_home
方法,返回与现有逻辑一致的 (String, bool) 结果,并保留找不到 home 目录时的错误行为。更新
crates/tokscale-cli/src/tui/data/mod.rs#L120-L129 的 prepare、#L196-L205 的
execute_with_diagnostics,以及#L278-L287 的测试 load_with_pricing,分别复用
self.resolve_home()? 或 loader.resolve_home()?。
In `@crates/tokscale-cli/src/tui/ui/header.rs`:
- Around line 225-237: Isolate all affected tests from developer-local
configuration and fixed paths: in crates/tokscale-cli/src/tui/ui/header.rs lines
225-237, inject test Settings or a temporary home; in
crates/tokscale-cli/src/tui/app.rs lines 2294-2305, 2344-2355, 2394-2405,
2435-2446, and 3509-3521, reuse the existing test_settings() fixture; and in
crates/tokscale-cli/src/commands/usage/codex.rs lines 203-225, construct the
home and CODEX_HOME from a TempDir.
In `@crates/tokscale-core/src/message_cache.rs`:
- Around line 255-283: 在消息缓存解析器标签相关测试中补充持久化回归测试:验证固定的旧 Cursor 和 Trae bincode
值仍分别解码为 RetiredCursor 与 RetiredTrae,并验证 stable_name() 对这两个退休标签仍返回 cursor 和
trae。测试应固定原始判别值,确保后续枚举重排不会改变现有缓存兼容性。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 05035f84-9be0-431c-a959-576f8b0e19f9
⛔ Files ignored due to path filters (3)
.github/assets/client-cursor.jpgis excluded by!**/*.jpg.github/assets/client-trae.pngis excluded by!**/*.pngCargo.lockis excluded by!**/*.lock
📒 Files selected for processing (72)
AGENTS.mdCargo.tomlREADME.mdREADME.zh-cn.mdcrates/tokscale-cli/Cargo.tomlcrates/tokscale-cli/src/cli.rscrates/tokscale-cli/src/commands/cache.rscrates/tokscale-cli/src/commands/clients.rscrates/tokscale-cli/src/commands/graph.rscrates/tokscale-cli/src/commands/headless.rscrates/tokscale-cli/src/commands/hourly.rscrates/tokscale-cli/src/commands/integrations.rscrates/tokscale-cli/src/commands/models.rscrates/tokscale-cli/src/commands/monthly.rscrates/tokscale-cli/src/commands/pricing.rscrates/tokscale-cli/src/commands/shared.rscrates/tokscale-cli/src/commands/time_metrics.rscrates/tokscale-cli/src/commands/usage/codex.rscrates/tokscale-cli/src/commands/usage/mod.rscrates/tokscale-cli/src/commands/wrapped.rscrates/tokscale-cli/src/cursor.rscrates/tokscale-cli/src/failure.rscrates/tokscale-cli/src/main.rscrates/tokscale-cli/src/main_tests.rscrates/tokscale-cli/src/trae.rscrates/tokscale-cli/src/tui/app.rscrates/tokscale-cli/src/tui/cache.rscrates/tokscale-cli/src/tui/colors.rscrates/tokscale-cli/src/tui/data/mod.rscrates/tokscale-cli/src/tui/mod.rscrates/tokscale-cli/src/tui/settings.rscrates/tokscale-cli/src/tui/ui/agents.rscrates/tokscale-cli/src/tui/ui/daily.rscrates/tokscale-cli/src/tui/ui/dialog/source_picker.rscrates/tokscale-cli/src/tui/ui/footer.rscrates/tokscale-cli/src/tui/ui/header.rscrates/tokscale-cli/src/tui/ui/hourly.rscrates/tokscale-cli/src/tui/ui/usage.rscrates/tokscale-cli/src/tui/ui/widgets.rscrates/tokscale-cli/tests/cli_tests.rscrates/tokscale-cli/tests/copilot_memory.rscrates/tokscale-cli/tests/tui_exit_tests.rscrates/tokscale-core/client-catalog.jsoncrates/tokscale-core/src/adapters/file.rscrates/tokscale-core/src/adapters/mod.rscrates/tokscale-core/src/adapters/trae.rscrates/tokscale-core/src/aggregate/tui.rscrates/tokscale-core/src/clients.rscrates/tokscale-core/src/lib.rscrates/tokscale-core/src/lib_tests.rscrates/tokscale-core/src/local_clients.rscrates/tokscale-core/src/message_cache.rscrates/tokscale-core/src/scanner.rscrates/tokscale-core/src/sessionize.rscrates/tokscale-core/src/sessions/cursor.rscrates/tokscale-core/src/sessions/droid.rscrates/tokscale-core/src/sessions/mod.rscrates/tokscale-core/src/sessions/trae.rsdocs/adr/0007-client-identity-catalog.mddocs/adr/0014-explicit-subscription-usage-boundary.mddocs/adr/0015-local-only-product-surface.mddocs/adr/0018-bounded-source-fold-pipeline.mddocs/adr/0022-deterministic-cli-command-semantics.mddocs/adr/0023-provider-owned-credentials.mddocs/adr/0024-subscription-usage-redesign.mddocs/cli.mddocs/clients.mddocs/configuration.mddocs/development.mddocs/pricing.mdpackages/cli/package.jsonpackages/tokscale/package.json
💤 Files with no reviewable changes (13)
- packages/tokscale/package.json
- crates/tokscale-cli/src/trae.rs
- packages/cli/package.json
- crates/tokscale-core/src/sessions/cursor.rs
- crates/tokscale-core/src/sessions/mod.rs
- crates/tokscale-core/client-catalog.json
- crates/tokscale-core/src/adapters/trae.rs
- crates/tokscale-core/src/sessions/trae.rs
- Cargo.toml
- crates/tokscale-cli/src/tui/ui/widgets.rs
- crates/tokscale-cli/src/cursor.rs
- crates/tokscale-cli/src/tui/colors.rs
- crates/tokscale-core/src/local_clients.rs
There was a problem hiding this comment.
All reported issues were addressed across 75 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Summary
Droid ExplorerorDroid Worker.Droid Orchestrator,Droid Worker, orDroid Validatorusing Factory's persisted tags and Mission feature assignments.Droid Validator.Why
The Droid parser only read model, provider, timestamp, and token totals from
*.settings.json. It never populatedUnifiedMessage.agent, so Droid usage appeared in model totals but was absent from the Agents panel.This change preserves each session's own
tokenUsageaccounting while projecting Factory's persisted role metadata into four stable Agent labels:Droid Explorer,Droid Worker,Droid Orchestrator, andDroid Validator.Validation
cargo fmt --all -- --checkcargo test— 2293 passed, 5 ignoredcargo clippy --workspace --all-targets -- -D warningsDroid Workerinstances, and 7Droid OrchestratorinstancesBranch relationship
This PR temporarily targets the head branch of #145 (
agent/cli-v5-contract) so its diff contains only the Droid attribution commits. After #145 is squash-merged intopersonal/local-clients, rebase this branch onto the updated default branch and retarget the PR before merging.Summary by cubic
Adds role attribution to Droid sessions so usage appears under clear agent labels in reports. Also removes Cursor and Trae, and makes CLI commands deterministic with clearer exits.
New Features
Droid ExplorerorDroid Worker; attribute Mission sessions toDroid Orchestrator,Droid Worker, orDroid Validatorvia persisted tags and feature assignments; workers require the built‑inmission-workertag; validator-spawned review/flow-check subagents stay underDroid Validator.features.jsonso Mission role changes invalidate stale results; Agents panel shows stable role labels.tokscaleequalstokscale tui; reports are explicit subcommands (models,monthly,hourly,graph,time-metrics);--no-spinneris honored consistently; TUI returns exit 130 on Ctrl-C and restores the terminal.Migration
tokscale --no-spinner --lightwithtokscale models --no-spinner; usetokscale tui --tab modelsto open the models tab.tokscale pricing lookup <model> [--source <catalog>]andtokscale pricing overrides --json.codexis supported; pass the child command after--; invalidTOKSCALE_NATIVE_TIMEOUT_MSfails early with exit 2.sessions_pathremoved; addedno_refreshand optionalhome_dir; cache scope includeshome_dirand schema bumped.Written for commit 53eb07a. Summary will update on new commits.
Summary by CodeRabbit
新功能
models、monthly、hourly、clients、graph、tui、headless等子命令及参数校验。变更
pricing lookup,覆盖查询更新为pricing overrides。cache warm预热 TUI 缓存。文档