Skip to content

feat(list): show available daemons and align logics with TUI#206

Merged
jdx merged 2 commits intojdx:mainfrom
gaojunran:feat-list
Feb 1, 2026
Merged

feat(list): show available daemons and align logics with TUI#206
jdx merged 2 commits intojdx:mainfrom
gaojunran:feat-list

Conversation

@gaojunran
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings February 1, 2026 07:37
@gemini-code-assist
Copy link

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.rs module with shared logic for listing both active and available daemons
  • Updated pitchfork list command 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.

Comment on lines +60 to +67
// 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)
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

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();

Suggested change
// 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)

Copilot uses AI. Check for mistakes.
let mut entries = Vec::new();
let mut seen_ids = HashSet::new();

// First, add all active daemons from supervisor
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
// First, add all active daemons from supervisor
// First, add all existing daemons passed in (from state file or supervisor)

Copilot uses AI. Check for mistakes.
@gaojunran
Copy link
Contributor Author

@jdx ready for a review

Copilot AI review requested due to automatic review settings February 1, 2026 21:20
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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();
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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()
};

Copilot uses AI. Check for mistakes.
Comment on lines 253 to +254
// Clean up
let _ = env.run_command(&["stop", "list_error_test"]);
env.run_command(&["stop", "running_daemon"]);
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
@jdx jdx merged commit 830d9c7 into jdx:main Feb 1, 2026
4 checks passed
@jdx jdx mentioned this pull request Feb 1, 2026
jdx added a commit that referenced this pull request Feb 1, 2026
## 🤖 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants