void setSessionWithInstrumentation("custom", sid)}
onConversationId={(cid) => void vm.setCellConversation(id, cid)}
/>
+ ) : agentId && cellMode === "custom" ? (
+
-
- {conversationId
- ? "Une reprise est possible si le profil et le backend conservent cette conversation."
- : "Aucune conversation reprenable n'est enregistrée pour cette cellule; la bascule repartira à neuf si le backend ne peut pas reprendre."}
-
+ {conversationId && (
+
+ Une reprise est possible si le profil et le backend conservent cette conversation.
+
+ )}
{
+ const chat = applyOperation(base(), {
+ type: "setCellPreferredView",
+ target: "a",
+ preferredView: "chat",
+ });
+ expect(leaves(chat)[0].preferredView).toBe("chat");
+
+ const tui = applyOperation(chat, {
+ type: "setCellPreferredView",
+ target: "a",
+ preferredView: "tui",
+ });
+ expect(leaves(tui)[0].preferredView).toBeUndefined();
+ expect("preferredView" in leaves(tui)[0]).toBe(false);
+ });
+
// --- setAgentRunning -------------------------------------------------------
it("setAgentRunning true sets the flag", () => {
const after = applyOperation(base(), {
diff --git a/frontend/src/features/layout/layout.ts b/frontend/src/features/layout/layout.ts
index d99dc363..81b10b41 100644
--- a/frontend/src/features/layout/layout.ts
+++ b/frontend/src/features/layout/layout.ts
@@ -265,6 +265,22 @@ export function applyOperation(
if (!found) throw notFound(op.target);
return { root };
}
+ case "setCellPreferredView": {
+ let found = false;
+ const root = mapNode(tree.root, (n) => {
+ if (n.type === "leaf" && n.node.id === op.target) {
+ found = true;
+ const { preferredView: _preferredView, ...rest } = n.node;
+ const updated = op.preferredView === "chat"
+ ? { ...rest, preferredView: "chat" as const }
+ : rest;
+ return { type: "leaf", node: updated };
+ }
+ return n;
+ });
+ if (!found) throw notFound(op.target);
+ return { root };
+ }
case "setAgentRunning": {
let found = false;
const root = mapNode(tree.root, (n) => {
diff --git a/frontend/src/features/layout/useLayout.ts b/frontend/src/features/layout/useLayout.ts
index dec6004f..f50354db 100644
--- a/frontend/src/features/layout/useLayout.ts
+++ b/frontend/src/features/layout/useLayout.ts
@@ -15,6 +15,7 @@ import type {
GatewayError,
LayoutOperation,
LayoutTree,
+ PreferredView,
} from "@/domain";
import { useGateways } from "@/app/di";
import {
@@ -67,6 +68,8 @@ export interface LayoutViewModel {
* to persist the id assigned at first launch so the next open resumes it.
*/
setCellConversation: (target: string, conversationId: string | null) => Promise;
+ /** Persists the preferred TUI or structured-chat surface for one agent cell. */
+ setCellPreferredView: (target: string, preferredView: PreferredView) => Promise;
/**
* Persists a `customPluginLayout` node's opaque state through `mutate_layout`.
*/
@@ -269,6 +272,12 @@ export function useLayout(
[mutate],
);
+ const setCellPreferredView = useCallback(
+ (target: string, preferredView: PreferredView) =>
+ mutate({ type: "setCellPreferredView", target, preferredView }),
+ [mutate],
+ );
+
const setPluginLayoutState = useCallback(
async (nodeId: string, state: unknown) => {
await mutate({ type: "setPluginLayoutState", target: nodeId, state });
@@ -294,6 +303,7 @@ export function useLayout(
setCellAgent,
attachLiveAgentToCell,
setCellConversation,
+ setCellPreferredView,
setPluginLayoutState,
replacePluginLayoutWithTerminal,
};