feat(terminals): reprise de conversation par cellule + fix ordre d'écriture
Permet de recharger la conversation CLI précédente de chaque cellule à la
réouverture du projet, de façon universelle (indépendant du modèle/CLI).
- profil AgentRuntime: bloc déclaratif optionnel `session { assignFlag, resumeFlag }`
- LeafCell: `conversationId` (persistant, distinct du SessionId PTY) + `agentWasRunning`
- runtime: SessionPlan (None/Assign/Resume) + composition pure des args
- LaunchAgent: décide Assign vs Resume, génère l'UUID, remonte l'id assigné
(persistance par l'appelant via setCellConversation — découplage SRP)
- close: SnapshotRunningAgents fige `agentWasRunning` avant le kill-all
(statut clot/en cours universel, sans parsing CLI)
- SessionInspector: port optionnel best-effort + adapter ClaudeTranscriptInspector
- popup de reprise par cellule (statut + sujet/tokens si dispo), intercalée
avant le Resume auto, jamais sur le chemin reattach
fix(terminals): sérialise les écritures PTY (file FIFO par handle) — corrige
les caractères mélangés/accents dus au réordonnancement des invoke Tauri concurrents
fix(layout): l'opération `move` préservait mal les champs du leaf (perdait `agent`)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -17,6 +17,7 @@ import { Channel, invoke } from "@tauri-apps/api/core";
|
||||
import type { Agent } from "@/domain";
|
||||
import type {
|
||||
AgentGateway,
|
||||
ConversationDetails,
|
||||
CreateAgentInput,
|
||||
OpenTerminalOptions,
|
||||
ReattachResult,
|
||||
@ -30,6 +31,8 @@ interface LaunchAgentResponse {
|
||||
cwd: string;
|
||||
rows: number;
|
||||
cols: number;
|
||||
/** Conversation id minted by this launch (omitted when nothing was assigned). */
|
||||
assignedConversationId?: string;
|
||||
}
|
||||
|
||||
export class TauriAgentGateway implements AgentGateway {
|
||||
@ -85,11 +88,19 @@ export class TauriAgentGateway implements AgentGateway {
|
||||
agentId,
|
||||
rows: options.rows,
|
||||
cols: options.cols,
|
||||
// Resume id: the leaf's persisted conversation id, when any (T4b). The
|
||||
// backend resumes it; absent ⇒ a fresh cell that may get a new id.
|
||||
conversationId: options.conversationId ?? null,
|
||||
},
|
||||
onOutput: channel,
|
||||
});
|
||||
|
||||
return makeTerminalHandle(res.sessionId, channel);
|
||||
const handle = makeTerminalHandle(res.sessionId, channel);
|
||||
// Surface the id assigned by this launch so the caller persists it on the
|
||||
// leaf (`setCellConversation`) and resumes next time.
|
||||
return res.assignedConversationId
|
||||
? { ...handle, assignedConversationId: res.assignedConversationId }
|
||||
: handle;
|
||||
}
|
||||
|
||||
async reattach(
|
||||
@ -111,4 +122,16 @@ export class TauriAgentGateway implements AgentGateway {
|
||||
scrollback: Uint8Array.from(res.scrollback),
|
||||
};
|
||||
}
|
||||
|
||||
inspectConversation(
|
||||
projectId: string,
|
||||
agentId: string,
|
||||
conversationId: string,
|
||||
): Promise<ConversationDetails> {
|
||||
// `inspect_conversation` takes a single `request` DTO; absent fields are
|
||||
// omitted from the response (best-effort), so an empty object is valid.
|
||||
return invoke<ConversationDetails>("inspect_conversation", {
|
||||
request: { projectId, agentId, conversationId },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user