Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions crates/rocm-dash-tui/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,9 @@ impl AppState {
self.chat_detect_offer = Some(cfg);
} else {
self.chat_detect_offer = None;
self.chat_detect_msg =
Some("no local engine found (Lemonade :13305 / vLLM :8000)".into());
self.chat_detect_msg = Some(
"no local engine found (Lemonade :13305 / vLLM :8000 / rocm serve :11435)".into(),
);
}
}

Expand Down
22 changes: 21 additions & 1 deletion crates/rocm-dash-tui/src/llm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,17 @@ pub fn probe_endpoint(base_url: &str, timeout: Duration) -> bool {
false
}

/// Probe the known local serving endpoints in priority order (Lemonade, then vLLM) and return the first reachable one.
/// Probe the known local serving endpoints in priority order (Lemonade, then
/// vLLM, then `rocm serve`'s non-managed default) and return the first
/// reachable one.
///
/// Used by the TUI's in-app "detect a local engine" action so the user need not run the CLI skill first.
/// TCP-only (no HTTP); never blocks longer than [`PROBE_TIMEOUT`] per candidate.
pub fn detect_local_endpoint() -> Option<&'static str> {
[
crate::skills::LEMONADE_ENDPOINT,
crate::skills::VLLM_ENDPOINT,
crate::skills::ROCM_SERVE_ENDPOINT,
]
.into_iter()
.find(|ep| probe_endpoint(ep, PROBE_TIMEOUT))
Expand Down Expand Up @@ -324,4 +327,21 @@ mod tests {
));
assert!(!probe_endpoint("not a url", Duration::from_millis(100)));
}

#[test]
fn detect_local_endpoint_probes_rocm_serve_default_port() {
// A listener on rocm serve's (non-managed) default port must be picked
// up by the fallback probe, not just Lemonade/vLLM's ports.
let Ok(listener) =
std::net::TcpListener::bind(("127.0.0.1", crate::skills::ROCM_SERVE_PORT))
else {
// Port already bound in this environment; skip rather than flake.
return;
};
assert_eq!(
detect_local_endpoint(),
Some(crate::skills::ROCM_SERVE_ENDPOINT)
);
drop(listener);
}
}
7 changes: 7 additions & 0 deletions crates/rocm-dash-tui/src/skills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ pub const LEMONADE_ENDPOINT: &str = "http://localhost:13305/v1";
/// vLLM's conventional OpenAI-compatible endpoint + port.
pub const VLLM_PORT: u16 = 8000;
pub const VLLM_ENDPOINT: &str = "http://localhost:8000/v1";
/// `rocm serve`'s (non-managed) default vLLM port.
///
/// Mirrors `rocm_core::DEFAULT_LOCAL_PORT`; duplicated as a literal because
/// this crate deliberately carries no `rocm-core` dependency (see
/// `AppState::model_recipes`).
pub const ROCM_SERVE_PORT: u16 = 11_435;
pub const ROCM_SERVE_ENDPOINT: &str = "http://localhost:11435/v1";

/// One typed step in a skill manifest. Tagged by `type` in TOML.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down
4 changes: 2 additions & 2 deletions crates/rocm-dash-tui/src/ui/tabs/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fn draw_consent(f: &mut Frame, area: Rect, state: &AppState, theme: &Theme) {
(
" Chat — detecting… ",
vec![Line::from(Span::styled(
"Probing for a local engine (Lemonade :13305 / vLLM :8000)…",
"Probing for a local engine (Lemonade :13305 / vLLM :8000 / rocm serve :11435)…",
Style::default().fg(theme.fg),
))],
)
Expand Down Expand Up @@ -209,7 +209,7 @@ fn consent_gate_lines<'a>(
Style::default().fg(theme.muted),
)),
Line::from(Span::styled(
" • or run a local endpoint at 127.0.0.1:8000",
" • or run a local endpoint (vLLM :8000, rocm serve :11435)",
Style::default().fg(theme.muted),
)),
],
Expand Down
Loading