feat(mcp,orchestrator,frontend): tool idea_restart_self, redemarrage autonome d'un agent — #288 (tool core self-only via requester MCP handshake, retour immediat {restartId, status: scheduled} puis orchestration detachee: snapshot reprise, stop PTY/structured, liberation Busy/mailbox, relance LaunchAgent meme conversation_id fresh_start=false, injection interne invisible; events domain/wire agentRestartRequested/PhaseChanged/Completed/Failed phases stopping/releasingInput/launching/resuming; CLI custom: separateurs exacts redemarrage de l'agent + etat termine/echoue, deduplication (restartId, event), verrouillage composer; TUI native: overlay AgentRestartOverlay sans injection xterm, progress/annonces projetes jusqu'a idle; QA verte: mcp_server restart_self 1/1, restart-self 3/3, backend self_restart_contract + events wire 2/2, frontend 3 suites 92/92, npm build, cargo check --workspace, fmt --check, diff --check; reserves hors perimetre: web-server 103/110 fixture PTY preexistante, 34 echecs npm test globaux listProjectSettings/web hors #288; scripts/ hors perimetre)
This commit is contained in:
@ -5,6 +5,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { DIProvider } from "@/app/di";
|
||||
import type { AgentProfile, ReplyChunk } from "@/domain";
|
||||
import { MockSystemGateway, MockWorkStateGateway } from "@/adapters/mock";
|
||||
import { AnnouncementsProvider } from "@/features/announcements";
|
||||
import { PluginRuntimeProvider } from "@/features/plugins";
|
||||
import {
|
||||
__resetProjectCliInteractionActivityForTests,
|
||||
@ -145,6 +146,91 @@ describe("CustomAgentChatView", () => {
|
||||
__resetProjectCliInteractionActivityForTests();
|
||||
});
|
||||
|
||||
it("projects self-restart lifecycle separators in the custom CLI only once", async () => {
|
||||
const system = new MockSystemGateway();
|
||||
const agent = {
|
||||
launchAgentChat: vi.fn(async () => ({ sessionId: "chat-session-restart" })),
|
||||
reattachAgentChat: vi.fn(async (sessionId: string) => ({
|
||||
sessionId,
|
||||
scrollback: [],
|
||||
})),
|
||||
sendAgentChat: vi.fn(async () => {}),
|
||||
cancelAgentChat: vi.fn(async () => {}),
|
||||
closeAgentChat: vi.fn(async () => {}),
|
||||
};
|
||||
|
||||
render(
|
||||
<DIProvider gateways={{ agent, system } as unknown as Gateways}>
|
||||
<AnnouncementsProvider projectId="project-1">
|
||||
<CustomAgentChatView
|
||||
projectId="project-1"
|
||||
agentId="agent-1"
|
||||
agentName="Worker"
|
||||
profile={profile}
|
||||
cwd="/repo"
|
||||
nodeId="node-1"
|
||||
sessionId={null}
|
||||
conversationId="conversation-1"
|
||||
onSessionId={vi.fn()}
|
||||
onConversationId={vi.fn()}
|
||||
/>
|
||||
</AnnouncementsProvider>
|
||||
</DIProvider>,
|
||||
);
|
||||
await waitFor(() => expect(agent.launchAgentChat).toHaveBeenCalled());
|
||||
|
||||
act(() => {
|
||||
system.emit({
|
||||
type: "agentRestartRequested",
|
||||
agentId: "agent-1",
|
||||
restartId: "restart-1",
|
||||
reason: null,
|
||||
});
|
||||
system.emit({
|
||||
type: "agentRestartCompleted",
|
||||
agentId: "agent-1",
|
||||
restartId: "restart-1",
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText("------- redemarrage de l'agent -------"),
|
||||
).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText("------- redemarrage de l'agent termine -------"),
|
||||
).not.toBeNull();
|
||||
expect(screen.getAllByTestId("agent-restart-separator")).toHaveLength(2);
|
||||
|
||||
act(() => {
|
||||
system.emit({
|
||||
type: "agentRestartCompleted",
|
||||
agentId: "agent-1",
|
||||
restartId: "restart-1",
|
||||
});
|
||||
});
|
||||
expect(screen.getAllByTestId("agent-restart-separator")).toHaveLength(2);
|
||||
|
||||
act(() => {
|
||||
system.emit({
|
||||
type: "agentRestartRequested",
|
||||
agentId: "agent-1",
|
||||
restartId: "restart-2",
|
||||
reason: "new capability",
|
||||
});
|
||||
system.emit({
|
||||
type: "agentRestartFailed",
|
||||
agentId: "agent-1",
|
||||
restartId: "restart-2",
|
||||
phase: "launching",
|
||||
message: "runtime unavailable",
|
||||
});
|
||||
});
|
||||
expect(
|
||||
screen.getByText("------- redemarrage de l'agent echoue -------"),
|
||||
).not.toBeNull();
|
||||
expect(screen.getByText("runtime unavailable")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("shows the technical open failure on mobile with retry and native TUI fallback", async () => {
|
||||
const openNativeTui = vi.fn();
|
||||
const agent = {
|
||||
|
||||
Reference in New Issue
Block a user