merge: ui2/s-agent-ui
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
commit
3df9f35ebe
12 files changed
+732
-68
No files matched your search
@@ -1,31 +1,67 @@
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { Link, useParams } from "react-router";
|
||||
import { ArrowLeft, PanelRightOpen } from "lucide-react";
|
||||
import { Link, useNavigate, useParams } from "react-router";
|
||||
import { agentMockEnabled } from "~/api/agent.ts";
|
||||
import {
|
||||
agentListHref,
|
||||
agentRunHref,
|
||||
pageListMemory,
|
||||
usePageListGroup,
|
||||
useRunGroup,
|
||||
} from "~/components/agent/agent-nav.ts";
|
||||
import { AgentRunPanel } from "~/components/agent/agent-run-panel.tsx";
|
||||
import { AgentSessionList } from "~/components/agent/agent-session-list.tsx";
|
||||
import { agentReturnPath, showAgentRunInDrawer } from "~/components/agent/agent-store.ts";
|
||||
import { Button } from "~/components/ui/button.tsx";
|
||||
|
||||
// 会话页(AGUI-3):左栏会话列表(xl 以上)· 会话列占满其余宽度(顶部概况条、底部输入区)。
|
||||
// 不再有页头目标描述和右侧栏;步骤、子会话、预算与模型在概况条里。
|
||||
export default function AgentRunPage() {
|
||||
const { runId = "" } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const mock = agentMockEnabled();
|
||||
const suffix = mock ? "?mock=1" : "";
|
||||
// 左栏分栏跟随当前会话(巡检会话及其子会话在「自动巡检」),也可以手动切换(记在 URL)
|
||||
const [group, setGroup] = usePageListGroup(useRunGroup(runId));
|
||||
return (
|
||||
<>
|
||||
<h1 className="sr-only">智能体会话</h1>
|
||||
<div className="grid grid-cols-1 gap-4 xl:grid-cols-[minmax(0,17rem)_minmax(0,1fr)]">
|
||||
<div data-agent-page className="grid grid-cols-1 gap-4 xl:grid-cols-[minmax(0,17rem)_minmax(0,1fr)]">
|
||||
<aside className="pg-slab hidden rounded-xl p-3 xl:block xl:h-[calc(100dvh-7rem)] xl:overflow-hidden">
|
||||
<AgentSessionList activeId={runId} hrefFor={(id) => `/console/agent/${id}${suffix}`} className="h-full" />
|
||||
<AgentSessionList
|
||||
activeId={runId}
|
||||
hrefFor={(id) => agentRunHref(id, mock)}
|
||||
group={group}
|
||||
onGroupChange={setGroup}
|
||||
memory={pageListMemory}
|
||||
className="h-full"
|
||||
/>
|
||||
</aside>
|
||||
<div className="pg-slab flex h-[calc(100dvh-7rem)] min-h-[28rem] flex-col gap-2 rounded-xl p-3 md:p-4">
|
||||
<Button asChild variant="ghost" size="sm" className="-mt-1 -ml-2 self-start text-muted-foreground xl:hidden">
|
||||
<Link to={`/console/agent${suffix}`}>
|
||||
<Link to={agentListHref(group, mock)}>
|
||||
<ArrowLeft />
|
||||
全部会话
|
||||
</Link>
|
||||
</Button>
|
||||
<AgentRunPanel key={runId} runId={runId} className="min-h-0 flex-1" />
|
||||
<AgentRunPanel
|
||||
key={runId}
|
||||
runId={runId}
|
||||
className="min-h-0 flex-1"
|
||||
actions={
|
||||
// 整页 → 抽屉:回到进智能体页面之前的页面,会话在抽屉里接着看
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="在侧边打开"
|
||||
title="在侧边打开(回到之前的页面)"
|
||||
onClick={() => {
|
||||
showAgentRunInDrawer(runId);
|
||||
navigate(agentReturnPath() ?? "/console");
|
||||
}}
|
||||
>
|
||||
<PanelRightOpen />
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -2,6 +2,13 @@ import { FlaskConical } from "lucide-react";
|
||||
import { useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { agentMockEnabled, useCreateAgentRun } from "~/api/agent.ts";
|
||||
import {
|
||||
agentRunHref,
|
||||
DRAFT_PAGE_GOAL,
|
||||
pageListMemory,
|
||||
usePageListGroup,
|
||||
writeDraft,
|
||||
} from "~/components/agent/agent-nav.ts";
|
||||
import { GoalComposer } from "~/components/agent/agent-run-panel.tsx";
|
||||
import { AgentSessionList } from "~/components/agent/agent-session-list.tsx";
|
||||
import { quickGoalsFor } from "~/components/agent/quick-goals.ts";
|
||||
@@ -14,6 +21,7 @@ export default function AgentPage() {
|
||||
const create = useCreateAgentRun();
|
||||
const navigate = useNavigate();
|
||||
const mock = agentMockEnabled();
|
||||
const [group, setGroup] = usePageListGroup();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -27,19 +35,32 @@ export default function AgentPage() {
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,20rem)_minmax(0,1fr)] lg:items-start">
|
||||
<div
|
||||
data-agent-page
|
||||
className="grid grid-cols-1 gap-4 lg:grid-cols-[minmax(0,20rem)_minmax(0,1fr)] lg:items-start"
|
||||
>
|
||||
<div className="pg-slab order-2 rounded-xl p-3 lg:order-1 lg:h-[calc(100dvh-12rem)] lg:overflow-hidden">
|
||||
<AgentSessionList hrefFor={(id) => `/console/agent/${id}${mock ? "?mock=1" : ""}`} className="h-full" />
|
||||
<AgentSessionList
|
||||
hrefFor={(id) => agentRunHref(id, mock)}
|
||||
group={group}
|
||||
onGroupChange={setGroup}
|
||||
memory={pageListMemory}
|
||||
className="h-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="pg-slab order-1 mx-auto w-full max-w-[88ch] rounded-xl p-4 lg:order-2">
|
||||
<GoalComposer
|
||||
pending={create.isPending}
|
||||
suggestions={quickGoalsFor("/console/agent")}
|
||||
draftKey={DRAFT_PAGE_GOAL}
|
||||
onSubmit={(goal, opts) =>
|
||||
create.mutate(
|
||||
{ goal, ...opts },
|
||||
{
|
||||
onSuccess: (run) => navigate(`/console/agent/${run.id}${mock ? "?mock=1" : ""}`),
|
||||
onSuccess: (run) => {
|
||||
writeDraft(DRAFT_PAGE_GOAL, "");
|
||||
navigate(agentRunHref(run.id, mock));
|
||||
},
|
||||
onError: (e) => toast.error(errorMessage(e)),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react
|
||||
import { Link, Outlet, useLocation, useMatches } from "react-router";
|
||||
import { useSession } from "~/api/auth.ts";
|
||||
import { AgentDrawer, AgentDrawerTrigger } from "~/components/agent/agent-drawer.tsx";
|
||||
import { outletKey } from "~/components/agent/agent-store.ts";
|
||||
import { AccountMenu } from "~/components/console/account-menu.tsx";
|
||||
import { AgentLauncher, AgentNavEntry } from "~/components/console/agent-launcher.tsx";
|
||||
import { ErrorState } from "~/components/console/empty-state.tsx";
|
||||
@@ -248,7 +249,10 @@ function ConsoleShell({ session }: { session: SessionInfo }) {
|
||||
|
||||
{/* 底部留出悬浮按钮的高度,页面末尾的内容能滚到它上面 */}
|
||||
<main className={cn("relative flex-1 overflow-x-clip", !wide && "px-4 pt-6 pb-24 md:px-6 md:pt-8")}>
|
||||
<div key={location.pathname} className={cn(!wide && "mx-auto max-w-6xl", "motion-safe:animate-blur-in")}>
|
||||
<div
|
||||
key={outletKey(location.pathname)}
|
||||
className={cn(!wide && "mx-auto max-w-6xl", "motion-safe:animate-blur-in")}
|
||||
>
|
||||
<Outlet />
|
||||
</div>
|
||||
</main>
|
||||
|
||||
Reference in new issue
Block a user