From a11d2dfa07603bff4d114b2a983b72482eae69da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 6 Jul 2026 22:57:52 -0400 Subject: [PATCH] Trim the sidebar to the surfaces that earn their place Inbox, Knowledge, Meetings, and Sprints leave the navigation and their page components go with them; the backend services and data they surfaced stay intact for agents and automation. The secondary rail is now Documents, Social, and Office. --- AgentCompany-New/src/renderer/src/app/App.tsx | 8 - .../src/renderer/src/pages/InboxPage.tsx | 197 ------------------ .../src/renderer/src/pages/KnowledgePage.tsx | 94 --------- .../src/renderer/src/pages/MeetingsPage.tsx | 97 --------- .../src/renderer/src/pages/SprintsPage.tsx | 107 ---------- .../src/renderer/src/shared/Shell.tsx | 8 - 6 files changed, 511 deletions(-) delete mode 100644 AgentCompany-New/src/renderer/src/pages/InboxPage.tsx delete mode 100644 AgentCompany-New/src/renderer/src/pages/KnowledgePage.tsx delete mode 100644 AgentCompany-New/src/renderer/src/pages/MeetingsPage.tsx delete mode 100644 AgentCompany-New/src/renderer/src/pages/SprintsPage.tsx diff --git a/AgentCompany-New/src/renderer/src/app/App.tsx b/AgentCompany-New/src/renderer/src/app/App.tsx index 6da70369..d25f1ef4 100644 --- a/AgentCompany-New/src/renderer/src/app/App.tsx +++ b/AgentCompany-New/src/renderer/src/app/App.tsx @@ -10,11 +10,7 @@ import { FilesPage } from "../pages/FilesPage"; import { ApprovalsPage } from "../pages/ApprovalsPage"; import { SocialPage } from "../pages/SocialPage"; import { DocumentsPage } from "../pages/DocumentsPage"; -import { KnowledgePage } from "../pages/KnowledgePage"; -import { InboxPage } from "../pages/InboxPage"; import { RunsPage } from "../pages/RunsPage"; -import { MeetingsPage } from "../pages/MeetingsPage"; -import { SprintsPage } from "../pages/SprintsPage"; import { SettingsPage } from "../pages/SettingsPage"; import { OfficePage } from "../pages/OfficePage"; @@ -45,11 +41,7 @@ export function App() { chat: , files: , docs: , - knowledge: , - inbox: , runs: , - meetings: , - sprints: , approvals: , social: , office: , diff --git a/AgentCompany-New/src/renderer/src/pages/InboxPage.tsx b/AgentCompany-New/src/renderer/src/pages/InboxPage.tsx deleted file mode 100644 index 86687141..00000000 --- a/AgentCompany-New/src/renderer/src/pages/InboxPage.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import { useMemo, useState } from "react"; -import { Avatar, Pill, Segmented } from "../shared/ui"; -import { TopbarActions } from "../shared/TopbarActions"; -import type { AgentRecord, ApprovalRecord, ChatMessageRecord, TaskRecord, TaskRunRecord } from "../../../shared/domain"; -import { TASK_STATUS } from "../../../shared/domain"; -import type { PageProps } from "./types"; -import { activeOrgId, formatRelative } from "./types"; - -type InboxFilter = "all" | "approvals" | "failures" | "blocked" | "messages"; -const FILTERS: Array<{ id: InboxFilter; label: string }> = [ - { id: "all", label: "All" }, - { id: "approvals", label: "Approvals" }, - { id: "failures", label: "Failures" }, - { id: "blocked", label: "Blocked" }, - { id: "messages", label: "Messages" }, -]; - -type View = "inbox" | "standup" | "performance"; -const VIEWS: Array<{ id: View; label: string }> = [ - { id: "inbox", label: "Inbox" }, - { id: "standup", label: "Standup" }, - { id: "performance", label: "Performance" }, -]; - -interface InboxItem { - id: string; - kind: InboxFilter; - title: string; - detail: string; - agentName: string | null; - timestamp: string; - tone: "amber" | "red" | "violet" | undefined; -} - -export function InboxPage({ snapshot }: PageProps) { - const orgId = activeOrgId(snapshot); - const agents = useMemo(() => snapshot.agents.filter((a) => a.orgId === orgId), [snapshot.agents, orgId]); - const tasks = useMemo(() => snapshot.tasks.filter((t) => t.orgId === orgId), [snapshot.tasks, orgId]); - const taskRuns = useMemo(() => snapshot.taskRuns.filter((r) => r.orgId === orgId), [snapshot.taskRuns, orgId]); - const approvals = useMemo(() => snapshot.approvals.filter((a) => a.orgId === orgId), [snapshot.approvals, orgId]); - const messages = useMemo(() => snapshot.chatMessages.filter((m) => m.orgId === orgId), [snapshot.chatMessages, orgId]); - const [filter, setFilter] = useState("all"); - const [view, setView] = useState("inbox"); - - const items = useMemo(() => buildInboxItems(approvals, taskRuns, tasks, messages, agents), [approvals, taskRuns, tasks, messages, agents]); - const filtered = filter === "all" ? items : items.filter((item) => item.kind === filter); - - return ( -
- - - -

Inbox

-

{items.length} {items.length === 1 ? "item" : "items"}

- - {view === "inbox" && ( - <> -
-
- {filtered.map((item) => ( -
-
- {item.agentName && } -
-
{item.title}
-
{item.detail}
-
- {humanize(item.kind)} - {formatRelative(item.timestamp)} -
-
- ))} -
- - )} - - {view === "standup" && } - {view === "performance" && } -
- ); -} - -function StandupView({ agents, tasks, taskRuns }: { agents: AgentRecord[]; tasks: TaskRecord[]; taskRuns: TaskRunRecord[] }) { - return ( -
- {agents.map((agent) => { - const agentTasks = tasks.filter((t) => t.assigneeAgentId === agent.id); - const inProgress = agentTasks.filter((t) => t.status === TASK_STATUS.IN_PROGRESS).length; - const done = agentTasks.filter((t) => t.status === TASK_STATUS.DONE).length; - const agentRuns = taskRuns.filter((r) => r.agentId === agent.id); - const lastRun = agentRuns[agentRuns.length - 1]; - return ( -
-
- - {agent.name} - {agent.role} · {agent.department} -
-
- {inProgress} in progress - {done} done - {agentRuns.length} runs - {lastRun && {formatRelative(lastRun.createdAt)}} -
-
- ); - })} -
- ); -} - -function PerformanceView({ agents, tasks, taskRuns }: { agents: AgentRecord[]; tasks: TaskRecord[]; taskRuns: TaskRunRecord[] }) { - const totalTasks = tasks.length; - const doneTasks = tasks.filter((t) => t.status === TASK_STATUS.DONE).length; - const completedRuns = taskRuns.filter((r) => r.state === "completed").length; - const failedRuns = taskRuns.filter((r) => r.state === "failed").length; - const successRate = completedRuns + failedRuns > 0 ? Math.round((completedRuns / (completedRuns + failedRuns)) * 100) : 0; - - return ( -
-
- - - - a.lifecycle === "active").length)} /> -
-
Agent throughput
-
-
-
Agent
Tasks done
Runs
Failures
-
- {agents.map((agent, i) => { - const agentDone = tasks.filter((t) => t.assigneeAgentId === agent.id && t.status === TASK_STATUS.DONE).length; - const agentRuns = taskRuns.filter((r) => r.agentId === agent.id); - const agentFailed = agentRuns.filter((r) => r.state === "failed").length; - return ( -
-
- - {agent.name} -
-
{agentDone}
-
{agentRuns.length}
-
{agentFailed > 0 ? {agentFailed} : 0}
-
- ); - })} -
-
- ); -} - -function MetricCard({ label, value, sub }: { label: string; value: string; sub?: string }) { - return ( -
-
{label}
-
- {value} - {sub && {sub}} -
-
- ); -} - -function buildInboxItems( - approvals: ApprovalRecord[], - taskRuns: TaskRunRecord[], - tasks: TaskRecord[], - messages: ChatMessageRecord[], - agents: AgentRecord[], -): InboxItem[] { - const items: InboxItem[] = []; - for (const a of approvals.filter((a) => a.state === "pending")) { - items.push({ id: `app-${a.id}`, kind: "approvals", title: a.title, detail: a.kind.replace(/_/g, " "), agentName: null, timestamp: a.createdAt, tone: "amber" }); - } - for (const r of taskRuns.filter((r) => r.state === "failed")) { - const task = tasks.find((t) => t.id === r.taskId); - const agent = agents.find((a) => a.id === r.agentId); - items.push({ id: `fail-${r.id}`, kind: "failures", title: task?.title ?? r.taskId, detail: r.errorMessage ?? "Run failed", agentName: agent?.name ?? null, timestamp: r.completedAt ?? r.createdAt, tone: "red" }); - } - for (const t of tasks.filter((t) => t.status === TASK_STATUS.REVIEW)) { - const agent = agents.find((a) => a.id === t.assigneeAgentId); - items.push({ id: `blk-${t.id}`, kind: "blocked", title: t.title, detail: "Awaiting review", agentName: agent?.name ?? null, timestamp: t.updatedAt, tone: "violet" }); - } - const recent = messages.filter((m) => m.senderType === "agent").slice(-10); - for (const m of recent) { - const agent = agents.find((a) => a.id === m.senderId); - const preview = m.bodyMd.length > 60 ? `${m.bodyMd.slice(0, 57)}...` : m.bodyMd; - items.push({ id: `msg-${m.id}`, kind: "messages", title: agent?.name ?? "Agent", detail: preview, agentName: agent?.name ?? null, timestamp: m.createdAt, tone: undefined }); - } - items.sort((a, b) => b.timestamp.localeCompare(a.timestamp)); - return items; -} - -function humanize(value: string): string { - return value.charAt(0).toUpperCase() + value.slice(1); -} diff --git a/AgentCompany-New/src/renderer/src/pages/KnowledgePage.tsx b/AgentCompany-New/src/renderer/src/pages/KnowledgePage.tsx deleted file mode 100644 index 2cd54f5e..00000000 --- a/AgentCompany-New/src/renderer/src/pages/KnowledgePage.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useMemo, useState, type FormEvent } from "react"; -import { Button, Field, Icon, IconButton, Pill } from "../shared/ui"; -import { TopbarActions } from "../shared/TopbarActions"; -import { Dialog } from "../shared/Dialog"; -import type { PageProps } from "./types"; -import { activeOrgId, formatRelative } from "./types"; - -const CATEGORIES = ["process", "technical", "product", "market", "legal", "financial", "operational", "general"] as const; -const IMPORTANCES = ["critical", "high", "medium", "low"] as const; - -function text(form: FormData, key: string): string { - return String(form.get(key) ?? "").trim(); -} - -export function KnowledgePage({ snapshot, actions }: PageProps) { - const orgId = activeOrgId(snapshot); - const entries = useMemo(() => snapshot.knowledgeEntries.filter((e) => e.orgId === orgId), [snapshot.knowledgeEntries, orgId]); - const [createOpen, setCreateOpen] = useState(false); - const [filter, setFilter] = useState("all"); - - const filtered = filter === "all" ? entries : entries.filter((e) => e.category === filter); - - const create = (event: FormEvent) => { - event.preventDefault(); - const form = new FormData(event.currentTarget); - void actions.run(() => window.agentCompany.createKnowledgeEntry({ - orgId, - topic: text(form, "topic"), - category: text(form, "category"), - content: text(form, "content"), - importance: text(form, "importance"), - sourceType: "manual", - sourceId: null, - })).then((r) => { if (r) setCreateOpen(false); }); - }; - - const remove = (entryId: string) => { - void actions.run(() => window.agentCompany.deleteKnowledgeEntry({ orgId, entryId })); - }; - - return ( -
- - - - -

Knowledge Base

-

{entries.length} {entries.length === 1 ? "entry" : "entries"}

- -
- {filtered.map((entry) => ( -
-
- {entry.topic} - remove(entry.id)} /> -
-
- {entry.category} - {entry.importance} -
-
- {entry.content} -
-
{formatRelative(entry.updatedAt)}
-
- ))} -
- - setCreateOpen(false)} onSubmit={create}> - - - - - - - -