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
17 changes: 14 additions & 3 deletions console/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,22 @@ async function refreshRemote(): Promise<void> {
if (!remoteEl) return;
try {
remoteConfig = await source.remoteConfig();
renderRemote(remoteEl, remoteConfig);
// The panel labels the file "Edit config" opens — the registry
// (`agents.toml`), not the deprecated `remote.toml`. Load it best-effort so a
// registry read error never blanks the connection panel; a later edit/save
// refreshes the cache.
if (!registryConfig) {
try {
registryConfig = await source.registryConfig();
} catch {
/* no path label until it loads — better than mislabelling remote.toml */
}
}
renderRemote(remoteEl, remoteConfig, registryConfig?.path);
} catch (e) {
note("error", `config: remote load failed — ${errText(e)}`);
remoteConfig = null;
renderRemote(remoteEl, null);
renderRemote(remoteEl, null, registryConfig?.path);
}
}

Expand Down Expand Up @@ -655,7 +666,7 @@ async function bindRemoteStatus(): Promise<void> {
// The legacy remote panel shows only the management connection's status.
if (agent === managementName && remoteConfig) {
remoteConfig = { ...remoteConfig, status };
if (remoteEl) renderRemote(remoteEl, remoteConfig);
if (remoteEl) renderRemote(remoteEl, remoteConfig, registryConfig?.path);
}
// Route the live state to the owning chat panel — it re-enables its input on
// `connected` and, on a mid-turn drop, closes the open turn so it doesn't
Expand Down
18 changes: 18 additions & 0 deletions console/src/render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,24 @@ describe("remoteHtml", () => {
);
});

it("labels the registry path (agents.toml) that Edit config opens, not remote.toml", () => {
const html = remoteHtml(
{ ...FIXTURE_REMOTE_CONFIG, path: "~/.config/oab-studio/remote.toml" },
"~/.config/oab-studio/agents.toml",
);
expect(html).toContain("agents.toml");
expect(html).not.toContain("remote.toml");
});

it("omits the path label when no registry path is known (no mislabel)", () => {
const html = remoteHtml({
...FIXTURE_REMOTE_CONFIG,
path: "~/.config/oab-studio/remote.toml",
});
expect(html).not.toContain("cfg-path");
expect(html).not.toContain("remote.toml");
});

it("renders an unavailable state for null", () => {
expect(remoteHtml(null)).toContain("remote connection unavailable");
});
Expand Down
27 changes: 19 additions & 8 deletions console/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,10 @@ export function renderFleetConfig(

// ---- Remote reverse-MCP connection panel (Part B) ---------------------------
// The "activate the remote connection" surface: the /acp endpoint, live status,
// an explicit Activate/Disconnect button, and Edit config (the same editor as
// fleets.toml, over remote.toml).
// an explicit Activate/Disconnect button, and Edit config. Since #69 the editor
// opens the registry (`agents.toml`, the source of truth), not the deprecated
// `remote.toml`, so the panel labels the registry path — passed in, since it
// lives in a different view-model (`RegistryConfig`) than the connection view.

const REMOTE_STATUS_CLASS: Record<string, string> = {
connected: "rm-connected",
Expand All @@ -274,8 +276,13 @@ function remoteStatusBadge(status: string): string {

// Pure: the remote-connection view -> the panel HTML. `null` renders an
// unavailable state. The button is Disconnect while connected/connecting, else
// Activate — disabled until a URL + token are configured.
export function remoteHtml(view: RemoteConfig | null): string {
// Activate — disabled until a URL + token are configured. `registryPath` is the
// `agents.toml` path "Edit config" opens; omitted/empty ⇒ the path label is
// hidden (better than labelling a file the button no longer edits).
export function remoteHtml(
view: RemoteConfig | null,
registryPath?: string | null,
): string {
if (!view) {
return `<div class="remote"><span class="muted">remote connection unavailable</span></div>`;
}
Expand All @@ -286,8 +293,8 @@ export function remoteHtml(view: RemoteConfig | null): string {
const target = view.configured
? `<code class="rm-url">${escapeHtml(view.url)}</code>`
: `<span class="muted">not configured — set <code>url</code> + <code>token</code> in the config</span>`;
const path = view.path
? `<span class="cfg-path" title="edit this file to configure the remote connection"><code>${escapeHtml(view.path)}</code></span>`
const path = registryPath
? `<span class="cfg-path" title="Edit config opens this registry file (agents.toml)"><code>${escapeHtml(registryPath)}</code></span>`
: "";
return `<div class="remote">
<div class="rm-head">
Expand All @@ -303,8 +310,12 @@ export function remoteHtml(view: RemoteConfig | null): string {
</div>`;
}

export function renderRemote(el: HTMLElement, view: RemoteConfig | null): void {
el.innerHTML = remoteHtml(view);
export function renderRemote(
el: HTMLElement,
view: RemoteConfig | null,
registryPath?: string | null,
): void {
el.innerHTML = remoteHtml(view, registryPath);
}

// ---- Agent consoles (ADR agent-consoles, Parts B/C) --------------------------
Expand Down
Loading