fix(agent): 切回看过的会话直接铺出历史,长内容不再从顶滚到底
- 事件流按会话缓存最近 30 条会话的已读事件,切回时直接用缓存渲染,再从最后一个 seq 之后补读 - 消息区跟随:一次多出一屏以上直接跳到底,流式小段增长才平滑跟随 (原来只有第一次 ResizeObserver 回调算首屏,事件补读回来时整段平滑滚动) Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
9f499ac7c2
commit
93a5341688
3 files changed
+78
-10
No files matched your search
@@ -1,7 +1,9 @@
|
||||
import type { AgentRunEvent } from "@umt/contracts";
|
||||
import { createElement } from "react";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { runGroup } from "~/api/agent.ts";
|
||||
import { followBehavior } from "~/components/agentui/message-scroller.tsx";
|
||||
import {
|
||||
agentListHref,
|
||||
agentRunHref,
|
||||
@@ -16,6 +18,7 @@ import {
|
||||
} from "./agent-nav.ts";
|
||||
import { CompactPager } from "./agent-session-list.tsx";
|
||||
import { isAgentPage, outletKey } from "./agent-store.ts";
|
||||
import { cachedRunEvents, cacheRunEvents } from "./use-agent-stream.ts";
|
||||
|
||||
// 智能体页面切换的状态逻辑:整页重挂载 key、分栏与 URL、草稿、滚动策略、快捷键在智能体页面的行为。
|
||||
|
||||
@@ -119,3 +122,31 @@ describe("输入草稿", () => {
|
||||
expect(readDraft(undefined)).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("消息区滚动策略", () => {
|
||||
it("流式的小段增长平滑跟随", () => {
|
||||
expect(followBehavior({ gap: 48, viewport: 600, reduce: false })).toBe("smooth");
|
||||
});
|
||||
it("一次多出一屏以上(打开 / 切回会话铺开历史)直接跳到底", () => {
|
||||
expect(followBehavior({ gap: 1400, viewport: 600, reduce: false })).toBe("auto");
|
||||
});
|
||||
it("减少动态效果时一律直接跳", () => {
|
||||
expect(followBehavior({ gap: 48, viewport: 600, reduce: true })).toBe("auto");
|
||||
});
|
||||
});
|
||||
|
||||
describe("切回看过的会话:事件缓存", () => {
|
||||
const ev = (seq: number) => ({ seq, at: "2026-10-06T00:00:00Z", type: "text_delta", delta: "x" }) as AgentRunEvent;
|
||||
it("记住最近读到的事件,切回时直接可用", () => {
|
||||
cacheRunEvents("live:a", [ev(0), ev(1)]);
|
||||
expect(cachedRunEvents("live:a").map((e) => e.seq)).toEqual([0, 1]);
|
||||
expect(cachedRunEvents("mock:a")).toEqual([]);
|
||||
});
|
||||
it("空列表不覆盖已有缓存;超过 30 条会话丢掉最早看的", () => {
|
||||
cacheRunEvents("live:a", []);
|
||||
expect(cachedRunEvents("live:a")).toHaveLength(2);
|
||||
for (let i = 0; i < 30; i++) cacheRunEvents(`live:n${i}`, [ev(i)]);
|
||||
expect(cachedRunEvents("live:a")).toEqual([]);
|
||||
expect(cachedRunEvents("live:n29")).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user