Make agents list force list view on mobile with condensed trailing info. Add mobile bottom bar for config save/cancel and live run indicator on agent detail. Make MetricCard, PageTabBar, Dashboard tasks, and ActivityRow responsive for small screens. Add xs avatar size for inline text flow. Remove redundant budget displays from agent overview, properties panel, costs tab, and config form. Add attachment activity verb labels. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
101 lines
3.4 KiB
TypeScript
101 lines
3.4 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { Link } from "react-router-dom";
|
|
import type { Agent, AgentRuntimeState } from "@paperclip/shared";
|
|
import { agentsApi } from "../api/agents";
|
|
import { useCompany } from "../context/CompanyContext";
|
|
import { queryKeys } from "../lib/queryKeys";
|
|
import { StatusBadge } from "./StatusBadge";
|
|
import { Identity } from "./Identity";
|
|
import { formatDate } from "../lib/utils";
|
|
import { Separator } from "@/components/ui/separator";
|
|
|
|
interface AgentPropertiesProps {
|
|
agent: Agent;
|
|
runtimeState?: AgentRuntimeState;
|
|
}
|
|
|
|
const adapterLabels: Record<string, string> = {
|
|
claude_local: "Claude (local)",
|
|
codex_local: "Codex (local)",
|
|
process: "Process",
|
|
http: "HTTP",
|
|
};
|
|
|
|
function PropertyRow({ label, children }: { label: string; children: React.ReactNode }) {
|
|
return (
|
|
<div className="flex items-center justify-between py-1.5">
|
|
<span className="text-xs text-muted-foreground">{label}</span>
|
|
<div className="flex items-center gap-1.5">{children}</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function AgentProperties({ agent, runtimeState }: AgentPropertiesProps) {
|
|
const { selectedCompanyId } = useCompany();
|
|
|
|
const { data: agents } = useQuery({
|
|
queryKey: queryKeys.agents.list(selectedCompanyId!),
|
|
queryFn: () => agentsApi.list(selectedCompanyId!),
|
|
enabled: !!selectedCompanyId && !!agent.reportsTo,
|
|
});
|
|
|
|
const reportsToAgent = agent.reportsTo ? agents?.find((a) => a.id === agent.reportsTo) : null;
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="space-y-1">
|
|
<PropertyRow label="Status">
|
|
<StatusBadge status={agent.status} />
|
|
</PropertyRow>
|
|
<PropertyRow label="Role">
|
|
<span className="text-sm">{agent.role}</span>
|
|
</PropertyRow>
|
|
{agent.title && (
|
|
<PropertyRow label="Title">
|
|
<span className="text-sm">{agent.title}</span>
|
|
</PropertyRow>
|
|
)}
|
|
<PropertyRow label="Adapter">
|
|
<span className="text-sm font-mono">{adapterLabels[agent.adapterType] ?? agent.adapterType}</span>
|
|
</PropertyRow>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
<div className="space-y-1">
|
|
{(runtimeState?.sessionDisplayId ?? runtimeState?.sessionId) && (
|
|
<PropertyRow label="Session">
|
|
<span className="text-xs font-mono">
|
|
{String(runtimeState.sessionDisplayId ?? runtimeState.sessionId).slice(0, 12)}...
|
|
</span>
|
|
</PropertyRow>
|
|
)}
|
|
{runtimeState?.lastError && (
|
|
<PropertyRow label="Last error">
|
|
<span className="text-xs text-red-400 truncate max-w-[160px]">{runtimeState.lastError}</span>
|
|
</PropertyRow>
|
|
)}
|
|
{agent.lastHeartbeatAt && (
|
|
<PropertyRow label="Last Heartbeat">
|
|
<span className="text-sm">{formatDate(agent.lastHeartbeatAt)}</span>
|
|
</PropertyRow>
|
|
)}
|
|
{agent.reportsTo && (
|
|
<PropertyRow label="Reports To">
|
|
{reportsToAgent ? (
|
|
<Link to={`/agents/${reportsToAgent.id}`} className="hover:underline">
|
|
<Identity name={reportsToAgent.name} size="sm" />
|
|
</Link>
|
|
) : (
|
|
<span className="text-sm font-mono">{agent.reportsTo.slice(0, 8)}</span>
|
|
)}
|
|
</PropertyRow>
|
|
)}
|
|
<PropertyRow label="Created">
|
|
<span className="text-sm">{formatDate(agent.createdAt)}</span>
|
|
</PropertyRow>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|