feat(FN-3447): add planning session rewind capability with modal back actio

This merge delivers four major features: a planning session rewind system (FN-3447, steps 1–4) with a new backend route for rolling back sessions, modal back-action wiring, and updated typing; workspace verification gates (FN-3385) for agent prompt editing; an agents view org chart spacing rework (F

Fusion-Task-Id: FN-3447
This commit is contained in:
Fusion
2026-05-04 19:56:48 -07:00
committed by gsxdsm
parent 79bf77bd5e
commit cb3ab98e70
9 changed files with 261 additions and 10 deletions

View File

@@ -1923,6 +1923,52 @@ export async function retrySession(
await continueAgentConversation(session, replayMessage);
}
export interface PlanningRewindResult {
currentQuestion: PlanningQuestion;
history: PlanningHistoryEntry[];
}
export async function rewindSession(
sessionId: string,
rootDir?: string,
promptOverrides?: PromptOverrideMap,
): Promise<PlanningRewindResult> {
const session = getSession(sessionId);
if (!session) {
throw new SessionNotFoundError(`Planning session ${sessionId} not found or expired`);
}
if (session.history.length === 0) {
throw new InvalidSessionStateError("Planning session has no previous question to rewind to");
}
const rewindEntry = session.history.pop();
if (!rewindEntry) {
throw new InvalidSessionStateError("Planning session has no previous question to rewind to");
}
disposeSessionAgentForRetry(session);
session.currentQuestion = rewindEntry.question;
session.summary = undefined;
session.error = undefined;
session.lastGeneratedThinking = session.history[session.history.length - 1]?.thinkingOutput ?? "";
session.thinkingOutput = "";
session.updatedAt = new Date();
if (!session.agent && rootDir) {
await ensureSessionAgent(session, rootDir, session.history, promptOverrides);
}
persistSession(session, "awaiting_input");
planningStreamManager.broadcast(session.id, { type: "question", data: rewindEntry.question });
return {
currentQuestion: rewindEntry.question,
history: [...session.history],
};
}
export function stopGeneration(sessionId: string): boolean {
const session = sessions.get(sessionId);
const activeGeneration = activeGenerations.get(sessionId);