Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion client/src/lib/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Update this file with every code change / git commit.
*/

export const APP_VERSION = "0.27.17";
export const APP_VERSION = "0.27.18";

export interface ReleaseNote {
version: string;
Expand All @@ -18,6 +18,13 @@ export interface ReleaseNote {
}

export const RELEASE_NOTES: ReleaseNote[] = [
{
version: "0.27.18",
date: "2026-03-21",
changes: [
"Auto-purge hourly canvas auto-saves older than 3 days — named and manually-saved canvases are never removed",
],
},
{
version: "0.27.17",
date: "2026-03-20",
Expand Down
17 changes: 10 additions & 7 deletions client/src/pages/FlowWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,8 @@ function FlowWorkspaceInner() {

// ── Auto-save every 5 minutes ──
// Saves canvas to a "Canvas Auto-saves" system folder in the Context Store.
// Hourly saves are kept permanently; 5-min saves are purged after 1 hour.
// 5-min saves are purged after 1 hour; hourly saves are purged after 3 days.
// Named/manually-saved canvases are never touched — only auto-save prefixed docs are purged.

const autoSaveTimerRef = useRef<ReturnType<typeof setInterval>>();
const lastHourlySaveRef = useRef(0);
Expand Down Expand Up @@ -1080,19 +1081,21 @@ function FlowWorkspaceInner() {
});
lastHourlySaveRef.current = now;

// Purge 5-min saves older than 1 hour from the folder
// Purge 5-min saves older than 1 hour and hourly saves older than 3 days
try {
const docsRes = await apiRequest("GET", "/api/documents");
const raw = await docsRes.json();
const allDocs = Array.isArray(raw) ? raw : (raw.documents ?? []);
const oneHourAgo = now - 3600_000;
const old5Min = allDocs.filter(
const threeDaysAgo = now - 3 * 24 * 3600_000;
const staleAutoSaves = allDocs.filter(
(d: { title: string; folderId: number | null; updatedAt: string }) =>
d.folderId === folderId &&
d.title?.startsWith("[5min]") &&
new Date(d.updatedAt).getTime() < oneHourAgo,
d.folderId === folderId && (
(d.title?.startsWith("[5min]") && new Date(d.updatedAt).getTime() < oneHourAgo) ||
(d.title?.startsWith("[Hourly]") && new Date(d.updatedAt).getTime() < threeDaysAgo)
),
);
for (const doc of old5Min) {
for (const doc of staleAutoSaves) {
await apiRequest("DELETE", `/api/documents/${doc.id}`).catch(() => {});
}
} catch {
Expand Down
Loading