feat(FN-1152): add retry flows for failed AI planning sessions

- Keep errored AI sessions retryable in the session store and add backend retry handlers for planning, subtask breakdown, and mission interview flows
- Add retry API routes and dashboard API client helpers for planning, subtask, and mission interview session retries
- Update PlanningModeModal, SubtaskBreakdownModal, MissionInterviewModal, and background session handling to show error states with retry/cancel UX
- Expand unit and integration tests across store, services, routes, and modal components to cover retry success and failure paths
This commit is contained in:
gsxdsm
2026-04-08 15:10:46 -07:00
parent 5f53949e2a
commit e80fb448d4
20 changed files with 1368 additions and 234 deletions

View File

@@ -1253,6 +1253,19 @@ export function respondToPlanning(
});
}
/** Retry a failed planning session turn */
export function retryPlanningSession(
sessionId: string,
projectId?: string,
): Promise<{ success: boolean; sessionId: string }> {
return api<{ success: boolean; sessionId: string }>(
withProjectId(`/planning/${encodeURIComponent(sessionId)}/retry`, projectId),
{
method: "POST",
},
);
}
/** Cancel an active planning session */
export function cancelPlanning(sessionId: string, projectId?: string): Promise<void> {
return api<void>(withProjectId("/planning/cancel", projectId), {
@@ -1803,6 +1816,18 @@ export function startSubtaskBreakdown(description: string, projectId?: string):
});
}
export function retrySubtaskSession(
sessionId: string,
projectId?: string,
): Promise<{ success: boolean; sessionId: string }> {
return api<{ success: boolean; sessionId: string }>(
withProjectId(`/subtasks/${encodeURIComponent(sessionId)}/retry`, projectId),
{
method: "POST",
},
);
}
export function getSubtaskStreamUrl(sessionId: string, projectId?: string): string {
return buildApiUrl(withProjectId(`/subtasks/${encodeURIComponent(sessionId)}/stream`, projectId));
}
@@ -3235,6 +3260,19 @@ export function respondToMissionInterview(
});
}
/** Retry a failed mission interview turn */
export function retryMissionInterviewSession(
sessionId: string,
projectId?: string,
): Promise<{ success: boolean; sessionId: string }> {
return api<{ success: boolean; sessionId: string }>(
withProjectId(`/missions/interview/${encodeURIComponent(sessionId)}/retry`, projectId),
{
method: "POST",
},
);
}
/** Cancel an active mission interview session */
export function cancelMissionInterview(sessionId: string, projectId?: string): Promise<void> {
return api<void>(withProjectId("/missions/interview/cancel", projectId), {