fix: emit relative container link URLs from harness, update dashboard join

Container link URLs (/screen.html, /stats.html) were root-relative,
which works when the agent is accessed directly at :port/ but resolves
to the gateway root when accessed via /agent/<name>/.

Fix at the source: harness emits relative URLs (screen.html, stats.html)
and the dashboard joins containerBase + '/' + url. The agent page uses
the URL directly and relative resolution is now correct in both paths.
This commit is contained in:
iris 2026-05-31 23:18:35 +02:00 committed by mara
commit c353dc1893
2 changed files with 4 additions and 11 deletions

View file

@ -585,10 +585,7 @@ window.marked = marked;
// "https://forge.pr1ma.darkest.space"), fall back to
// "<hostname>:3000" for gateway-off / local-dev deploys.
const forgeBase = (s && s.forge_public_url) || `http://${hostname}:3000`;
// Container nav-strip links resolve against the same base as the
// primary `name` link — gateway-prefixed when the gateway is in
// front, direct TCP otherwise. Strips the trailing slash so
// `lnk.url` starting with `/` concatenates cleanly.
// Container nav-strip base: gateway prefix or direct TCP.
const containerBase = gatewayLinks
? `/agent/${encodeURIComponent(c.name)}`
: `http://${hostname}:${c.port}`;
@ -600,7 +597,7 @@ window.marked = marked;
for (const lnk of links) {
const href = lnk.kind === 'forge' ? forgeBase + (lnk.url || '')
: lnk.kind === 'external' ? (lnk.url || '')
: /* container */ containerBase + (lnk.url || '');
: /* container */ containerBase + '/' + (lnk.url || '');
const a = el('a', {
class: 'nav-link',
href,

View file

@ -607,12 +607,8 @@ async fn api_state(State(state): State<AppState>) -> axum::Json<StateSnapshot> {
fn agent_links(label: &str, gui_enabled: bool) -> Vec<AgentLink> {
let mut links = Vec::new();
// URLs are the actual HTML files served out of the frontend dist
// (`stats.html` / `screen.html`); the harness serves them as
// static files via ServeDir rather than via Rust routes, so the
// URL has to be the on-disk filename.
links.push(AgentLink {
url: "/stats.html".to_owned(),
url: "stats.html".to_owned(),
icon: "📊".to_owned(),
label: "stats".to_owned(),
kind: AgentLinkKind::Container,
@ -620,7 +616,7 @@ fn agent_links(label: &str, gui_enabled: bool) -> Vec<AgentLink> {
if gui_enabled {
links.push(AgentLink {
url: "/screen.html".to_owned(),
url: "screen.html".to_owned(),
icon: "🖥".to_owned(),
label: "screen".to_owned(),
kind: AgentLinkKind::Container,