feat(list): show available daemons and align logics with TUI#206
feat(list): show available daemons and align logics with TUI#206
Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
There was a problem hiding this comment.
Pull request overview
This PR adds support for showing "available" daemons (defined in config but not yet started) in the list command, TUI, and Web UI. It introduces a shared daemon_list module to unify the logic across all interfaces.
Changes:
- Added a new
daemon_list.rsmodule with shared logic for listing both active and available daemons - Updated
pitchfork listcommand to show available daemons with "available" status - Modified TUI to use shared daemon list logic, removing duplicate placeholder creation code
- Updated Web UI to display available daemons with an "available" status badge
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/daemon_list.rs | New module providing shared logic for merging state file daemons with config-only daemons |
| src/cli/list.rs | Updated to use shared daemon list module and display available daemons with cyan color |
| src/web/routes/daemons.rs | Updated to use shared daemon list module and render available daemons with "available" status |
| src/tui/app.rs | Refactored to use shared daemon list module, removing duplicate placeholder creation logic |
| src/web/assets/style.css | Added CSS styling for "available" status badge |
| tests/test_e2e.rs | Added test to verify available daemons are shown in list output |
| docs/cli/list.md, pitchfork.usage.kdl, docs/cli/commands.json | Updated documentation to reflect that list shows both active and available daemons |
| src/main.rs, src/lib.rs | Added daemon_list module declaration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/daemon_list.rs
Outdated
| // Get active daemons directly from supervisor | ||
| let active_daemons = supervisor.active_daemons().await; | ||
|
|
||
| // Get disabled daemons from state file | ||
| let disabled_daemons = supervisor.state_file.lock().await.disabled.clone(); | ||
| let disabled_set: HashSet<String> = disabled_daemons.into_iter().collect(); | ||
|
|
||
| build_daemon_list(active_daemons, disabled_set, config) |
There was a problem hiding this comment.
The supervisor.active_daemons() method only returns daemons with PIDs (currently running daemons). This is inconsistent with get_all_daemons() which reads the entire state file including failed/stopped daemons. This will cause the Web UI to not display failed or stopped daemons. The code should read from the state file directly to match the behavior of get_all_daemons(). Change to: let state_daemons = supervisor.state_file.lock().await.daemons.values().cloned().collect();
| // Get active daemons directly from supervisor | |
| let active_daemons = supervisor.active_daemons().await; | |
| // Get disabled daemons from state file | |
| let disabled_daemons = supervisor.state_file.lock().await.disabled.clone(); | |
| let disabled_set: HashSet<String> = disabled_daemons.into_iter().collect(); | |
| build_daemon_list(active_daemons, disabled_set, config) | |
| // Read state file via supervisor to get all daemons (including failed/stopped ones) | |
| let state_daemons: Vec<Daemon> = supervisor | |
| .state_file | |
| .lock() | |
| .await | |
| .daemons | |
| .values() | |
| .cloned() | |
| .collect(); | |
| // Get disabled daemons from state file | |
| let disabled_daemons = supervisor.state_file.lock().await.disabled.clone(); | |
| let disabled_set: HashSet<String> = disabled_daemons.into_iter().collect(); | |
| build_daemon_list(state_daemons, disabled_set, config) |
src/daemon_list.rs
Outdated
| let mut entries = Vec::new(); | ||
| let mut seen_ids = HashSet::new(); | ||
|
|
||
| // First, add all active daemons from supervisor |
There was a problem hiding this comment.
The comment "add all active daemons from supervisor" is misleading because when called from get_all_daemons(), this includes all daemons from the state file (active, stopped, failed), not just active ones. Consider changing to "add all daemons from state file" to accurately describe the behavior.
| // First, add all active daemons from supervisor | |
| // First, add all existing daemons passed in (from state file or supervisor) |
|
@jdx ready for a review |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| let disabled_marker = if entry.is_disabled { "disabled" } else { "" }; | ||
|
|
||
| let error_msg = entry.daemon.status.error_message().unwrap_or_default(); |
There was a problem hiding this comment.
For available daemons, calling error_message() on a Stopped status may return an error message when none should be displayed. Consider only extracting error messages for non-available daemons, or ensure available daemons don't show error messages.
| let error_msg = entry.daemon.status.error_message().unwrap_or_default(); | |
| let error_msg = if entry.is_available { | |
| String::new() | |
| } else { | |
| entry.daemon.status.error_message().unwrap_or_default() | |
| }; |
| // Clean up | ||
| let _ = env.run_command(&["stop", "list_error_test"]); | ||
| env.run_command(&["stop", "running_daemon"]); |
There was a problem hiding this comment.
The cleanup code doesn't verify the stop command succeeded. Consider asserting the command's success status to ensure proper test cleanup and catch potential issues.
## 🤖 New release * `pitchfork-cli`: 1.2.0 -> 1.3.0 <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [1.3.0](v1.2.0...v1.3.0) - 2026-02-01 ### Added - *(list)* show available daemons and align logics with TUI ([#206](#206)) - *(logs)* support `--since <humantime>`, use pager by default ([#204](#204)) - support `pitchfork.local.toml` ([#198](#198)) - impl `stop --all` ([#195](#195)) - beautify web ui ([#191](#191)) - add ready_cmd option ([#187](#187)) ### Fixed - refactor the logic of stopping a daemon and add tests ([#192](#192)) ### Other - re-order code to suit for multi-frontend structure ([#197](#197)) - *(deps)* update rust crate xx to v2.3.1 ([#203](#203)) - *(deps)* update rust crate clap to v4.5.56 ([#202](#202)) - *(ci)* run linting on all files in CI ([#196](#196)) - Update README.md logo ([#184](#184)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: this PR only updates version numbers and release notes/docs, with no runtime code changes. > > **Overview** > Releases **v1.3.0** by bumping the crate version from `1.2.0` to `1.3.0` (including `Cargo.lock`) and updating the `pitchfork.usage.kdl`/generated CLI docs to match. > > Updates `CHANGELOG.md` with the `1.3.0` release notes and links to the included feature/fix PRs. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d278b90. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
No description provided.