Files
AgentCompany/src/main/ipc-recovery-handlers.ts
T
ZacharyZhang-NY 64183428ec feat(02-03): crash recovery detection and user notification
- 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)
2026-03-22 03:57:58 -04:00

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);
});
}