diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 27ba4e18671..4a2af78ebc8 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1052,7 +1052,7 @@ export namespace Config { }) .optional(), plugin: z.string().array().optional(), - snapshot: z.boolean().optional(), + snapshot: z.union([z.boolean(), z.number().int().nonnegative()]).optional(), share: z .enum(["manual", "auto", "disabled"]) .optional() diff --git a/packages/opencode/src/snapshot/index.ts b/packages/opencode/src/snapshot/index.ts index 72252b7b4c5..5f43aa198c1 100644 --- a/packages/opencode/src/snapshot/index.ts +++ b/packages/opencode/src/snapshot/index.ts @@ -13,7 +13,7 @@ import { Process } from "@/util/process" export namespace Snapshot { const log = Log.create({ service: "snapshot" }) const hour = 60 * 60 * 1000 - const prune = "7.days" + const defaultRetentionDays = 7 function args(git: string, cmd: string[]) { return ["--git-dir", git, "--work-tree", Instance.worktree, ...cmd] @@ -31,14 +31,15 @@ export namespace Snapshot { export async function cleanup() { if (Instance.project.vcs !== "git") return const cfg = await Config.get() - if (cfg.snapshot === false) return + if (cfg.snapshot === false || cfg.snapshot === 0) return + const retentionDays = cfg.snapshot === true ? defaultRetentionDays : cfg.snapshot const git = gitdir() const exists = await fs .stat(git) .then(() => true) .catch(() => false) if (!exists) return - const result = await Process.run(["git", ...args(git, ["gc", `--prune=${prune}`])], { + const result = await Process.run(["git", ...args(git, ["gc", `--prune=${retentionDays}.days`])], { cwd: Instance.directory, nothrow: true, }) @@ -50,13 +51,13 @@ export namespace Snapshot { }) return } - log.info("cleanup", { prune }) + log.info("cleanup", { retentionDays }) } export async function track() { if (Instance.project.vcs !== "git") return const cfg = await Config.get() - if (cfg.snapshot === false) return + if (cfg.snapshot === false || cfg.snapshot === 0) return const git = gitdir() if (await fs.mkdir(git, { recursive: true })) { await Process.run(["git", "init"], { diff --git a/packages/opencode/test/snapshot/snapshot.test.ts b/packages/opencode/test/snapshot/snapshot.test.ts index 1804ab5c2a2..ece872fb372 100644 --- a/packages/opencode/test/snapshot/snapshot.test.ts +++ b/packages/opencode/test/snapshot/snapshot.test.ts @@ -1178,3 +1178,16 @@ test("diffFull with whitespace changes", async () => { }, }) }) + +test("snapshot config with boolean true uses default 7-day retention", async () => { + const cfg = { snapshot: true as true | number } + const retentionDays = cfg.snapshot === true ? 7 : cfg.snapshot + expect(retentionDays).toBe(7) +}) + +test("snapshot config with positive integer uses specified retention", async () => { + const cfg = { snapshot: 3 as true | number } + const retentionDays = cfg.snapshot === true ? 7 : cfg.snapshot + expect(retentionDays).toBe(3) +}) + diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 2629015eb34..ba0a2557500 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1343,7 +1343,7 @@ export type Config = { ignore?: Array } plugin?: Array - snapshot?: boolean + snapshot?: boolean | number /** * Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing */