diff --git a/AgentCompany-New/src/renderer/src/pages/HomePage.tsx b/AgentCompany-New/src/renderer/src/pages/HomePage.tsx
index cc3b75d1..4a9dbe57 100644
--- a/AgentCompany-New/src/renderer/src/pages/HomePage.tsx
+++ b/AgentCompany-New/src/renderer/src/pages/HomePage.tsx
@@ -4,14 +4,16 @@ import { TopbarActions } from "../shared/TopbarActions";
import type {
AgentRecord,
ApprovalRecord,
+ ChatMessageRecord,
EmployeeRecord,
GoalRecord,
ProviderRecord,
TaskRecord,
+ TaskRunRecord,
} from "../../../shared/domain";
import { NewTaskDialog } from "./NewTaskDialog";
import type { PageProps } from "./types";
-import { activeOrgId, formatTime, money, requireActiveEmployee, requireActiveOrganization } from "./types";
+import { activeOrgId, formatRelative, formatTime, money, requireActiveEmployee, requireActiveOrganization } from "./types";
export function HomePage({ snapshot, actions, navigate }: PageProps) {
const orgId = activeOrgId(snapshot);
@@ -32,6 +34,9 @@ export function HomePage({ snapshot, actions, navigate }: PageProps) {
.reduce((sum, policy) => sum + policy.monthlyBudgetLimitCents, 0),
[snapshot.hiringPolicies, orgId],
);
+ const taskRuns = useMemo(() => snapshot.taskRuns.filter((run) => run.orgId === orgId), [snapshot.taskRuns, orgId]);
+ const chatMessages = useMemo(() => snapshot.chatMessages.filter((m) => m.orgId === orgId), [snapshot.chatMessages, orgId]);
+ const chatSpaces = useMemo(() => snapshot.chatSpaces.filter((s) => s.orgId === orgId), [snapshot.chatSpaces, orgId]);
const [newTaskOpen, setNewTaskOpen] = useState(false);
const pendingApprovals = approvals.filter((approval) => approval.state === "pending");
@@ -77,6 +82,11 @@ export function HomePage({ snapshot, actions, navigate }: PageProps) {
+
+ navigate("work")} />
+ navigate("chat")} />
+
+
setNewTaskOpen(false)} />
);
@@ -366,3 +376,115 @@ function resolveRequester(approval: ApprovalRecord, employees: EmployeeRecord[],
}
return "System";
}
+
+function RunActivityCard({
+ taskRuns,
+ tasks,
+ agents,
+ onViewAll,
+}: {
+ taskRuns: TaskRunRecord[];
+ tasks: TaskRecord[];
+ agents: AgentRecord[];
+ onViewAll: () => void;
+}) {
+ const recent = taskRuns.slice(0, 8);
+ return (
+
+
+ Agent runs
+
+
+
+ {recent.map((run) => {
+ const task = tasks.find((t) => t.id === run.taskId);
+ const agent = agents.find((a) => a.id === run.agentId);
+ return (
+
+ {agent &&
}
+
+
+ {task?.title ?? run.taskId}
+
+
+ {agent?.name ?? "Agent"} · {run.trigger}
+
+
+
{runStateLabel(run.state)}
+
{formatRelative(run.createdAt)}
+
+ );
+ })}
+ {recent.length === 0 &&
No runs yet
}
+
+
+ );
+}
+
+function RecentMessagesCard({
+ messages,
+ agents,
+ employees,
+ spaces,
+ onViewAll,
+}: {
+ messages: ChatMessageRecord[];
+ agents: AgentRecord[];
+ employees: EmployeeRecord[];
+ spaces: Array<{ id: string; name: string }>;
+ onViewAll: () => void;
+}) {
+ const recent = messages.slice(-8).reverse();
+ return (
+
+
+ Recent messages
+
+
+
+ {recent.map((msg) => {
+ const senderAgent = msg.senderType === "agent" ? agents.find((a) => a.id === msg.senderId) : null;
+ const senderEmployee = msg.senderType === "employee" ? employees.find((e) => e.id === msg.senderId) : null;
+ const name = senderAgent?.name ?? senderEmployee?.displayName ?? msg.senderType;
+ const space = spaces.find((s) => s.id === msg.spaceId);
+ const preview = msg.bodyMd.length > 80 ? `${msg.bodyMd.slice(0, 77)}...` : msg.bodyMd;
+ return (
+
+
+
+
+ {name}
+ {space && #{space.name}}
+ {formatTime(msg.createdAt)}
+
+
+ {preview}
+
+
+
+ );
+ })}
+ {recent.length === 0 &&
No messages yet
}
+
+
+ );
+}
+
+function runStateTone(state: string): "red" | "amber" | "violet" | undefined {
+ if (state === "failed") return "red";
+ if (state === "running") return "violet";
+ if (state === "queued") return "amber";
+ return undefined;
+}
+
+function runStateLabel(state: string): string {
+ if (state === "queued") return "Queued";
+ if (state === "running") return "Running";
+ if (state === "completed") return "Done";
+ if (state === "failed") return "Failed";
+ return state;
+}