Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/controller/useAgentGUIConversationRouting.spec.tsx
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

285 lines
9.4 KiB
TypeScript

import { renderHook } from "@testing-library/react";
import {
createAgentSessionEngine,
selectEngineSessionReconcile
} from "@tutti-os/agent-activity-core";
import { describe, expect, it, vi } from "vitest";
import { createTestEngineCommandPort } from "../../../shared/testing/createTestAgentSessionEngine";
import { useAgentGUIConversationRouting } from "./useAgentGUIConversationRouting";
describe("useAgentGUIConversationRouting", () => {
it("keeps an explicitly selected active session outside bounded rail state", () => {
const sessionEngine = createAgentSessionEngine({
clock: { nowUnixMs: () => 1 },
commandPort: createTestEngineCommandPort({
execute: async () => undefined
}),
identity: { origin: "test", workspaceId: "workspace-1" },
scheduler: { schedule: () => ({ cancel() {} }) }
});
const selectConversation = vi.fn();
const setIntent = vi.fn();
renderHook(() =>
useAgentGUIConversationRouting({
activeConversationIdRef: { current: "historical-session" },
conversationListQuery: {},
conversations: [],
conversationsRef: { current: [] },
handledOpenSessionSequenceRef: { current: null },
hasLoadedConversations: true,
intent: { tag: "active", id: "historical-session" },
openSessionRequest: null,
pendingOpenSessionRequestRef: { current: null },
selectConversation,
sessionEngine,
setIntent,
transientConversation: null,
workspaceId: "workspace-1"
})
);
expect(setIntent).not.toHaveBeenCalled();
expect(selectConversation).not.toHaveBeenCalled();
});
it("reconciles a persisted selection outside the bounded list after restart", () => {
const sessionEngine = createAgentSessionEngine({
clock: { nowUnixMs: () => 1 },
commandPort: createTestEngineCommandPort({
execute: async () => undefined
}),
identity: { origin: "test", workspaceId: "workspace-1" },
scheduler: { schedule: () => ({ cancel() {} }) }
});
const selectConversation = vi.fn();
const setIntent = vi.fn();
renderHook(() =>
useAgentGUIConversationRouting({
activeConversationIdRef: { current: "persisted-session" },
conversationListQuery: {},
conversations: [],
conversationsRef: { current: [] },
handledOpenSessionSequenceRef: { current: null },
hasLoadedConversations: true,
intent: { tag: "requested", id: "persisted-session" },
openSessionRequest: null,
pendingOpenSessionRequestRef: { current: null },
selectConversation,
sessionEngine,
setIntent,
transientConversation: null,
workspaceId: "workspace-1"
})
);
expect(selectConversation).toHaveBeenCalledWith("persisted-session", {
reloadConversations: false
});
expect(
selectEngineSessionReconcile(
sessionEngine.getSnapshot(),
"persisted-session"
)
).not.toBeNull();
expect(setIntent).not.toHaveBeenCalled();
});
it.each(["active", "requested"] as const)(
"does not restore a failed new activation from a stale %s intent",
(intentTag) => {
const sessionEngine = createAgentSessionEngine({
clock: { nowUnixMs: () => 1 },
commandPort: createTestEngineCommandPort({
execute: () => new Promise(() => {})
}),
identity: { origin: "test", workspaceId: "workspace-1" },
scheduler: { schedule: () => ({ cancel() {} }) }
});
sessionEngine.dispatch({
agentSessionId: "failed-session",
agentTargetId: "target-1",
clientSubmitId: "submit-1",
content: [{ type: "text", text: "hello" }],
cwd: "/workspace",
expiresAtUnixMs: 45_001,
mode: "new",
requestedAtUnixMs: 1,
requestId: "activation-1",
type: "activation/requested",
workspaceId: "workspace-1"
});
sessionEngine.dispatch({
commandId: "activate:activation-1",
commandType: "session/activate",
correlationId: "activation-1",
errorMessage: "Cursor failed to start.",
outcome: "failed",
type: "engine/commandResult"
});
const selectConversation = vi.fn();
const setIntent = vi.fn();
renderHook(() =>
useAgentGUIConversationRouting({
// Mirrors the earlier failure-settlement effect, which clears the
// active ref before routing runs with the previous render's intent.
activeConversationIdRef: { current: null },
conversationListQuery: {},
conversations: [],
conversationsRef: { current: [] },
handledOpenSessionSequenceRef: { current: null },
hasLoadedConversations: true,
intent: { tag: intentTag, id: "failed-session" },
openSessionRequest: null,
pendingOpenSessionRequestRef: { current: null },
selectConversation,
sessionEngine,
setIntent,
transientConversation: null,
workspaceId: "workspace-1"
})
);
expect(setIntent).toHaveBeenCalledOnce();
expect(setIntent).toHaveBeenCalledWith({ tag: "home" });
expect(selectConversation).not.toHaveBeenCalled();
expect(
selectEngineSessionReconcile(
sessionEngine.getSnapshot(),
"failed-session"
)
).toBeNull();
}
);
it("keeps a failed activation open when canonical session state exists", () => {
const sessionEngine = createAgentSessionEngine({
clock: { nowUnixMs: () => 1 },
commandPort: createTestEngineCommandPort({
execute: () => new Promise(() => {})
}),
identity: { origin: "test", workspaceId: "workspace-1" },
scheduler: { schedule: () => ({ cancel() {} }) }
});
sessionEngine.dispatch({
agentSessionId: "failed-session",
agentTargetId: "target-1",
clientSubmitId: "submit-1",
content: [{ type: "text", text: "hello" }],
cwd: "/workspace",
expiresAtUnixMs: 45_001,
mode: "new",
requestedAtUnixMs: 1,
requestId: "activation-1",
type: "activation/requested",
workspaceId: "workspace-1"
});
sessionEngine.dispatch({
commandId: "activate:activation-1",
commandType: "session/activate",
correlationId: "activation-1",
errorMessage: "Initial goal failed.",
outcome: "failed",
type: "engine/commandResult"
});
sessionEngine.dispatch({
sessions: [
{
activeTurnId: null,
agentSessionId: "failed-session",
createdAtUnixMs: 2,
cwd: "/workspace",
latestTurnInteractions: [],
pendingInteractions: [],
provider: "codex",
title: "Historical session",
workspaceId: "workspace-1"
}
],
type: "session/snapshotReceived"
});
const setIntent = vi.fn();
renderHook(() =>
useAgentGUIConversationRouting({
activeConversationIdRef: { current: "failed-session" },
conversationListQuery: {},
conversations: [],
conversationsRef: { current: [] },
handledOpenSessionSequenceRef: { current: null },
hasLoadedConversations: true,
intent: { id: "failed-session", source: "activation", tag: "active" },
openSessionRequest: null,
pendingOpenSessionRequestRef: { current: null },
selectConversation: vi.fn(),
sessionEngine,
setIntent,
transientConversation: null,
workspaceId: "workspace-1"
})
);
expect(setIntent).not.toHaveBeenCalledWith({ tag: "home" });
});
it("does not let a failed activation override an explicit history selection", () => {
const sessionEngine = createAgentSessionEngine({
clock: { nowUnixMs: () => 1 },
commandPort: createTestEngineCommandPort({
execute: () => new Promise(() => {})
}),
identity: { origin: "test", workspaceId: "workspace-1" },
scheduler: { schedule: () => ({ cancel() {} }) }
});
sessionEngine.dispatch({
agentSessionId: "historical-session",
agentTargetId: "target-1",
clientSubmitId: "submit-1",
content: [{ type: "text", text: "hello" }],
cwd: "/workspace",
expiresAtUnixMs: 45_001,
mode: "new",
requestedAtUnixMs: 1,
requestId: "activation-1",
type: "activation/requested",
workspaceId: "workspace-1"
});
sessionEngine.dispatch({
commandId: "activate:activation-1",
commandType: "session/activate",
correlationId: "activation-1",
errorMessage: "Initial goal failed.",
outcome: "failed",
type: "engine/commandResult"
});
const setIntent = vi.fn();
renderHook(() =>
useAgentGUIConversationRouting({
activeConversationIdRef: { current: "historical-session" },
conversationListQuery: {},
conversations: [],
conversationsRef: { current: [] },
handledOpenSessionSequenceRef: { current: null },
hasLoadedConversations: true,
intent: {
id: "historical-session",
source: "user-selection",
tag: "active"
},
openSessionRequest: null,
pendingOpenSessionRequestRef: { current: null },
selectConversation: vi.fn(),
sessionEngine,
setIntent,
transientConversation: null,
workspaceId: "workspace-1"
})
);
expect(setIntent).not.toHaveBeenCalledWith({ tag: "home" });
});
});