The runtime detail page was showing the agent CLI version (claude/codex) as "CLI Version" because metadata.version stored the agent version from agent.DetectVersion(). The multica CLI version was never sent. Fix: daemon now sends cli_version in the registration request, server stores it as metadata.cli_version alongside the existing agent version, and frontend reads metadata.cli_version. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
119 lines
3.8 KiB
TypeScript
119 lines
3.8 KiB
TypeScript
import type { AgentRuntime } from "@/shared/types";
|
|
import { formatLastSeen } from "../utils";
|
|
import { RuntimeModeIcon, StatusBadge, InfoField } from "./shared";
|
|
import { PingSection } from "./ping-section";
|
|
import { UpdateSection } from "./update-section";
|
|
import { UsageSection } from "./usage-section";
|
|
|
|
function getCliVersion(metadata: Record<string, unknown>): string | null {
|
|
if (
|
|
metadata &&
|
|
typeof metadata.cli_version === "string" &&
|
|
metadata.cli_version
|
|
) {
|
|
return metadata.cli_version;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function RuntimeDetail({ runtime }: { runtime: AgentRuntime }) {
|
|
const cliVersion =
|
|
runtime.runtime_mode === "local" ? getCliVersion(runtime.metadata) : null;
|
|
|
|
return (
|
|
<div className="flex h-full flex-col">
|
|
{/* Header */}
|
|
<div className="flex h-12 shrink-0 items-center justify-between border-b px-4">
|
|
<div className="flex min-w-0 items-center gap-2">
|
|
<div
|
|
className={`flex h-7 w-7 shrink-0 items-center justify-center rounded-md ${
|
|
runtime.status === "online" ? "bg-success/10" : "bg-muted"
|
|
}`}
|
|
>
|
|
<RuntimeModeIcon mode={runtime.runtime_mode} />
|
|
</div>
|
|
<div className="min-w-0">
|
|
<h2 className="text-sm font-semibold truncate">{runtime.name}</h2>
|
|
</div>
|
|
</div>
|
|
<StatusBadge status={runtime.status} />
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="flex-1 overflow-y-auto p-6 space-y-6">
|
|
{/* Info grid */}
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<InfoField label="Runtime Mode" value={runtime.runtime_mode} />
|
|
<InfoField label="Provider" value={runtime.provider} />
|
|
<InfoField label="Status" value={runtime.status} />
|
|
<InfoField
|
|
label="Last Seen"
|
|
value={formatLastSeen(runtime.last_seen_at)}
|
|
/>
|
|
{runtime.device_info && (
|
|
<InfoField label="Device" value={runtime.device_info} />
|
|
)}
|
|
{runtime.daemon_id && (
|
|
<InfoField label="Daemon ID" value={runtime.daemon_id} mono />
|
|
)}
|
|
</div>
|
|
|
|
{/* CLI Version & Update */}
|
|
{runtime.runtime_mode === "local" && (
|
|
<div>
|
|
<h3 className="text-xs font-medium text-muted-foreground mb-3">
|
|
CLI Version
|
|
</h3>
|
|
<UpdateSection
|
|
runtimeId={runtime.id}
|
|
currentVersion={cliVersion}
|
|
isOnline={runtime.status === "online"}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{/* Connection Test */}
|
|
<div>
|
|
<h3 className="text-xs font-medium text-muted-foreground mb-3">
|
|
Connection Test
|
|
</h3>
|
|
<PingSection runtimeId={runtime.id} />
|
|
</div>
|
|
|
|
{/* Usage */}
|
|
<div>
|
|
<h3 className="text-xs font-medium text-muted-foreground mb-3">
|
|
Token Usage
|
|
</h3>
|
|
<UsageSection runtimeId={runtime.id} />
|
|
</div>
|
|
|
|
{/* Metadata */}
|
|
{runtime.metadata && Object.keys(runtime.metadata).length > 0 && (
|
|
<div>
|
|
<h3 className="text-xs font-medium text-muted-foreground mb-2">
|
|
Metadata
|
|
</h3>
|
|
<div className="rounded-lg border bg-muted/30 p-3">
|
|
<pre className="text-xs font-mono whitespace-pre-wrap break-all">
|
|
{JSON.stringify(runtime.metadata, null, 2)}
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Timestamps */}
|
|
<div className="grid grid-cols-2 gap-4 border-t pt-4">
|
|
<InfoField
|
|
label="Created"
|
|
value={new Date(runtime.created_at).toLocaleString()}
|
|
/>
|
|
<InfoField
|
|
label="Updated"
|
|
value={new Date(runtime.updated_at).toLocaleString()}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|