fix(agent): 抽屉开着时路由变化,新对话的上下文跟着页面换
浏览器前进后退或会话里的链接换了页面,抽屉里新对话仍挂着上一页的对象。 按路由推断的上下文随页面更新;页面按钮带进来的上下文、正在看的会话不动。 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
a87c2c19c4
commit
bbd7459935
3 files changed
+57
-1
No files matched your search
@@ -28,6 +28,7 @@ import {
|
|||||||
setAgentDrawerOpen,
|
setAgentDrawerOpen,
|
||||||
shortGoalTitle,
|
shortGoalTitle,
|
||||||
showAgentRunInDrawer,
|
showAgentRunInDrawer,
|
||||||
|
syncAgentContextToPath,
|
||||||
takeReturnFocus,
|
takeReturnFocus,
|
||||||
toggleAgentDrawer,
|
toggleAgentDrawer,
|
||||||
useAgentDrawer,
|
useAgentDrawer,
|
||||||
@@ -104,6 +105,7 @@ export function AgentDrawer() {
|
|||||||
const content = useRef<HTMLDivElement>(null);
|
const content = useRef<HTMLDivElement>(null);
|
||||||
// 记下最近的非智能体页面:会话页「在侧边打开」回到这里
|
// 记下最近的非智能体页面:会话页「在侧边打开」回到这里
|
||||||
useEffect(() => noteAgentReturnPath(pathname, search), [pathname, search]);
|
useEffect(() => noteAgentReturnPath(pathname, search), [pathname, search]);
|
||||||
|
useEffect(() => syncAgentContextToPath(pathname), [pathname]);
|
||||||
const name = useContextName(context);
|
const name = useContextName(context);
|
||||||
const mock = agentMockEnabled();
|
const mock = agentMockEnabled();
|
||||||
// 目标前缀带名称和 ID:名称给人看,ID 给模型用
|
// 目标前缀带名称和 ID:名称给人看,ID 给模型用
|
||||||
|
|||||||
@@ -17,7 +17,19 @@ import {
|
|||||||
writeDraft,
|
writeDraft,
|
||||||
} from "./agent-nav.ts";
|
} from "./agent-nav.ts";
|
||||||
import { CompactPager } from "./agent-session-list.tsx";
|
import { CompactPager } from "./agent-session-list.tsx";
|
||||||
import { agentReturnPath, isAgentPage, noteAgentReturnPath, outletKey, toggleAction } from "./agent-store.ts";
|
import {
|
||||||
|
agentReturnPath,
|
||||||
|
clearAgentContext,
|
||||||
|
isAgentPage,
|
||||||
|
noteAgentReturnPath,
|
||||||
|
openAgentDrawer,
|
||||||
|
outletKey,
|
||||||
|
setAgentDrawerOpen,
|
||||||
|
showAgentRunInDrawer,
|
||||||
|
syncAgentContextToPath,
|
||||||
|
toggleAction,
|
||||||
|
useAgentDrawer,
|
||||||
|
} from "./agent-store.ts";
|
||||||
import { cachedRunEvents, cacheRunEvents } from "./use-agent-stream.ts";
|
import { cachedRunEvents, cacheRunEvents } from "./use-agent-stream.ts";
|
||||||
|
|
||||||
// 智能体页面切换的状态逻辑:整页重挂载 key、分栏与 URL、草稿、滚动策略、快捷键在智能体页面的行为。
|
// 智能体页面切换的状态逻辑:整页重挂载 key、分栏与 URL、草稿、滚动策略、快捷键在智能体页面的行为。
|
||||||
@@ -176,3 +188,33 @@ describe("会话页「在侧边打开」回到之前的页面", () => {
|
|||||||
expect(agentReturnPath()).toBe("/console/sites");
|
expect(agentReturnPath()).toBe("/console/sites");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("抽屉开着时路由变化", () => {
|
||||||
|
// useAgentDrawer 是 useSyncExternalStore,测试里直接读快照
|
||||||
|
const snapshot = () => {
|
||||||
|
let out: ReturnType<typeof useAgentDrawer> | null = null;
|
||||||
|
const Probe = () => {
|
||||||
|
out = useAgentDrawer();
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
renderToStaticMarkup(createElement(Probe));
|
||||||
|
return out as unknown as ReturnType<typeof useAgentDrawer>;
|
||||||
|
};
|
||||||
|
it("新对话的路由上下文跟着页面换", () => {
|
||||||
|
openAgentDrawer({ label: "作品 aaaa", entityId: "aaaa", fromPath: true });
|
||||||
|
syncAgentContextToPath("/console/sites/hdh");
|
||||||
|
expect(snapshot().context).toMatchObject({ siteId: "hdh", fromPath: true });
|
||||||
|
syncAgentContextToPath("/console/home");
|
||||||
|
expect(snapshot().context).toBeNull();
|
||||||
|
});
|
||||||
|
it("页面按钮带的上下文、正在看的会话、抽屉关着时不动", () => {
|
||||||
|
openAgentDrawer({ label: "作品:沙丘", entityId: "e1" });
|
||||||
|
syncAgentContextToPath("/console/sites/hdh");
|
||||||
|
expect(snapshot().context).toMatchObject({ entityId: "e1" });
|
||||||
|
clearAgentContext();
|
||||||
|
showAgentRunInDrawer("r1");
|
||||||
|
syncAgentContextToPath("/console/sites/hdh");
|
||||||
|
expect(snapshot().context).toBeNull();
|
||||||
|
setAgentDrawerOpen(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -84,6 +84,18 @@ export function newAgentConversation() {
|
|||||||
emit();
|
emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽屉开着时路由变了(浏览器前进后退、会话里的链接):还在新对话、上下文是按路由推断的,就换成新页面的对象;
|
||||||
|
* 页面按钮带进来的上下文、已经在看的会话不动。
|
||||||
|
*/
|
||||||
|
export function syncAgentContextToPath(pathname: string) {
|
||||||
|
if (!state.open || state.runId || (state.context && !state.context.fromPath)) return;
|
||||||
|
const next = contextFromPath(pathname);
|
||||||
|
if (JSON.stringify(next) === JSON.stringify(state.context)) return;
|
||||||
|
state = { ...state, context: next };
|
||||||
|
emit();
|
||||||
|
}
|
||||||
|
|
||||||
/** 去掉上下文(输入框上的名称标签 ×) */
|
/** 去掉上下文(输入框上的名称标签 ×) */
|
||||||
export function clearAgentContext() {
|
export function clearAgentContext() {
|
||||||
state = { ...state, context: null };
|
state = { ...state, context: null };
|
||||||
|
|||||||
Reference in new issue
Block a user