feat(backend,application,frontend,domain,web-server,app-tauri): bouton Redémarrer l'agent dans la barre supérieure des cellules — #317 (QA verte)
La cellule expose un bouton Redémarrer l'agent valable pour les trois modes de présentation (headless, TUI native, CLI custom), sans jamais prendre la présentation pour vérité runtime. - Application: use case RestartCellAgentRuntime validant le binding exact cellule/runtime via les snapshots live (RestartRuntimeNotFound, ConflictAgentVisibleElsewhere, AgentNotBoundToCell) puis déléguant au scheduler self-restart existant (schedule_cell); CellAgentPresentation purement informationnelle. - Backend/app-tauri/web-server: commande restart_cell_agent sur contrat DTO identique Tauri/HTTP, stop borné par timeout typé (RestartStopTimeout), relance préservant routage TUI natif, géométrie de cellule (node/rows/cols) et conversation; évenements domaine enrichis. - Frontend: bouton dans la barre de cellule avec confirmation, overlay d'état Redémarrage…/échec (libellés par code d'erreur, Fermer/ Réessayer), gardes d'identité de cellule et de restarts externes, gateway/mock/http adapters et ports alignés. - Tests: dto_agents, workstate_actions, contrats web-server, LayoutGrid.cellControlsLayering, adapters agent/mock/http. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -6,7 +6,7 @@ import { describe, it, expect } from "vitest";
|
||||
|
||||
import type { DomainEvent } from "@/domain";
|
||||
import type { Gateways } from "@/ports";
|
||||
import { createMockGateways, MockSystemGateway } from "./index";
|
||||
import { createMockGateways, MockAgentGateway, MockSystemGateway } from "./index";
|
||||
|
||||
// Typechecking this assignment proves every mock implements its port.
|
||||
const gateways: Gateways = createMockGateways();
|
||||
@ -90,6 +90,42 @@ describe("MockSystemGateway", () => {
|
||||
});
|
||||
|
||||
describe("other mock gateways", () => {
|
||||
it("schedules a restart only for the agent runtime bound to the exact cell", async () => {
|
||||
const agentGateway = new MockAgentGateway();
|
||||
const agent = await agentGateway.createAgent("p1", {
|
||||
name: "Worker",
|
||||
profileId: "profile-1",
|
||||
});
|
||||
await agentGateway.launchAgent(
|
||||
"p1",
|
||||
agent.id,
|
||||
{ cwd: "/p1", rows: 24, cols: 80, nodeId: "node-1" },
|
||||
() => {},
|
||||
);
|
||||
|
||||
await expect(
|
||||
agentGateway.restartCellAgentRuntime({
|
||||
projectId: "p1",
|
||||
nodeId: "node-1",
|
||||
agentId: agent.id,
|
||||
presentation: "tui",
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
status: "scheduled",
|
||||
agentId: agent.id,
|
||||
nodeId: "node-1",
|
||||
presentation: "tui",
|
||||
});
|
||||
await expect(
|
||||
agentGateway.restartCellAgentRuntime({
|
||||
projectId: "p1",
|
||||
nodeId: "stale-node",
|
||||
agentId: agent.id,
|
||||
presentation: "tui",
|
||||
}),
|
||||
).rejects.toMatchObject({ code: "AGENT_NOT_BOUND_TO_CELL" });
|
||||
});
|
||||
|
||||
it("project.createProject returns a project and listProjects reflects it", async () => {
|
||||
expect(await gateways.project.listProjects()).toEqual([]);
|
||||
const created = await gateways.project.createProject("n", "/root");
|
||||
|
||||
Reference in New Issue
Block a user