- Enhance interruptStaleRuns to return count and mark tasks as blocked - Add lastInterruptedCount property for bootstrap recovery check - Add getInterruptedRunsForRecovery query method - Add retryInterruptedTask, dismissInterruptedTask, markInterruptedTaskFailed actions - Add recovery-needed IPC event emission in bootstrap between heartbeat and resume - Create ipc-recovery-handlers.ts with retry/dismiss/fail IPC handlers - Register recovery handlers in domain handler chain - Expose recoveryRetry, recoveryDismiss, recoveryFail in preload API - Add recovery method types to DesktopApi contract - Create RecoveryBanner component with retry/cancel per interrupted task - Integrate RecoveryBanner at top of Dashboard view - Add crash recovery unit tests (9 tests)
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { z } from "zod";
|
|
import { ok, fail, type RegisterDomainHandlersDependencies } from "./ipc-domain-common";
|
|
|
|
const recoveryRetrySchema = z.object({
|
|
taskId: z.string(),
|
|
agentId: z.string(),
|
|
companyId: z.string(),
|
|
});
|
|
|
|
const recoveryTaskSchema = z.object({
|
|
taskId: z.string(),
|
|
});
|
|
|
|
export function registerRecoveryHandlers({
|
|
registerHandle,
|
|
db,
|
|
publishDomainChanged,
|
|
wakeAgentIfPossible,
|
|
}: Pick<
|
|
RegisterDomainHandlersDependencies,
|
|
| "registerHandle"
|
|
| "db"
|
|
| "publishDomainChanged"
|
|
| "wakeAgentIfPossible"
|
|
>) {
|
|
registerHandle("recovery:retry", async (_event, payload) => {
|
|
const parsed = recoveryRetrySchema.parse(payload);
|
|
db.retryInterruptedTask(parsed.taskId, parsed.agentId, parsed.companyId);
|
|
try {
|
|
wakeAgentIfPossible(parsed.agentId, parsed.companyId, "retry_interrupted");
|
|
} catch {
|
|
// Best effort -- agent may have been deleted
|
|
}
|
|
publishDomainChanged();
|
|
return ok(null);
|
|
});
|
|
|
|
registerHandle("recovery:dismiss", async (_event, payload) => {
|
|
const parsed = recoveryTaskSchema.parse(payload);
|
|
db.dismissInterruptedTask(parsed.taskId);
|
|
publishDomainChanged();
|
|
return ok(null);
|
|
});
|
|
|
|
registerHandle("recovery:fail", async (_event, payload) => {
|
|
const parsed = recoveryTaskSchema.parse(payload);
|
|
db.markInterruptedTaskFailed(parsed.taskId);
|
|
publishDomainChanged();
|
|
return ok(null);
|
|
});
|
|
}
|