mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
Auto-save annotation drafts to survive server crashes (#217)
* feat: auto-save annotation drafts to survive server crashes Adds server-side draft persistence so annotations are not lost when the server process dies. Drafts are saved to ~/.plannotator/drafts/ keyed by a SHA-256 content hash, debounced at 500ms. On reload, a dialog prompts the user to restore or dismiss. Drafts are auto-deleted on approve/deny/feedback. Closes #212 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: remove duplicate imports and update CLAUDE.md for draft feature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: wrap handleRestoreDraft in useCallback and update shared-handlers comment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,8 @@
|
||||
import { isRemoteSession, getServerPort } from "./remote";
|
||||
import { type DiffType, type GitContext, runGitDiff } from "./git";
|
||||
import { getRepoInfo } from "./repo";
|
||||
import { handleImage, handleUpload, handleAgents, handleServerReady, type OpencodeClient } from "./shared-handlers";
|
||||
import { handleImage, handleUpload, handleAgents, handleServerReady, handleDraftSave, handleDraftLoad, handleDraftDelete, type OpencodeClient } from "./shared-handlers";
|
||||
import { contentHash, deleteDraft } from "./draft";
|
||||
|
||||
// Re-export utilities
|
||||
export { isRemoteSession, getServerPort } from "./remote";
|
||||
@@ -82,6 +83,8 @@ export async function startReviewServer(
|
||||
): Promise<ReviewServerResult> {
|
||||
const { htmlContent, origin, gitContext, sharingEnabled = true, shareBaseUrl, onReady } = options;
|
||||
|
||||
const draftKey = contentHash(options.rawPatch);
|
||||
|
||||
// Mutable state for diff switching
|
||||
let currentPatch = options.rawPatch;
|
||||
let currentGitRef = options.gitRef;
|
||||
@@ -185,6 +188,13 @@ export async function startReviewServer(
|
||||
return handleAgents(options.opencodeClient);
|
||||
}
|
||||
|
||||
// API: Annotation draft persistence
|
||||
if (url.pathname === "/api/draft") {
|
||||
if (req.method === "POST") return handleDraftSave(req, draftKey);
|
||||
if (req.method === "DELETE") return handleDraftDelete(draftKey);
|
||||
return handleDraftLoad(draftKey);
|
||||
}
|
||||
|
||||
// API: Submit review feedback
|
||||
if (url.pathname === "/api/feedback" && req.method === "POST") {
|
||||
try {
|
||||
@@ -194,6 +204,7 @@ export async function startReviewServer(
|
||||
agentSwitch?: string;
|
||||
};
|
||||
|
||||
deleteDraft(draftKey);
|
||||
resolveDecision({
|
||||
feedback: body.feedback || "",
|
||||
annotations: body.annotations || [],
|
||||
|
||||
Reference in New Issue
Block a user