From d4682019522fbfb2e00b3d7c17a53895bd61620d Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" <219766164+opencode-agent[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 03:58:31 +0000 Subject: [PATCH] fix(opencode): use file times for truncation cleanup (#40987) Co-authored-by: Dax --- packages/opencode/src/tool/truncate.ts | 12 ++++++------ packages/opencode/test/tool/truncation.test.ts | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/tool/truncate.ts b/packages/opencode/src/tool/truncate.ts index 3a48c90a98e..0010636571c 100644 --- a/packages/opencode/src/tool/truncate.ts +++ b/packages/opencode/src/tool/truncate.ts @@ -6,7 +6,6 @@ import type { Agent } from "../agent/agent" import { FSUtil } from "@opencode-ai/core/fs-util" import { evaluate } from "@/permission/evaluate" import { Config } from "@/config/config" -import { Identifier } from "../id/id" import { ToolID } from "./schema" import { TRUNCATION_DIR } from "./truncation-dir" @@ -52,16 +51,17 @@ const layer = Layer.effect( const fs = yield* FSUtil.Service const cleanup = Effect.fn("Truncate.cleanup")(function* () { - const cutoff = Identifier.timestamp( - Identifier.create("tool", "ascending", Date.now() - Duration.toMillis(RETENTION)), - ) + const cutoff = Date.now() - Duration.toMillis(RETENTION) const entries = yield* fs.readDirectory(TRUNCATION_DIR).pipe( Effect.map((all) => all.filter((name) => name.startsWith("tool_"))), Effect.catch(() => Effect.succeed([])), ) for (const entry of entries) { - if (Identifier.timestamp(entry) >= cutoff) continue - yield* fs.remove(path.join(TRUNCATION_DIR, entry)).pipe(Effect.catch(() => Effect.void)) + const file = path.join(TRUNCATION_DIR, entry) + const info = yield* fs.stat(file).pipe(Effect.catch(() => Effect.succeed(undefined))) + const mtime = info && Option.getOrUndefined(info.mtime) + if (!mtime || mtime.getTime() >= cutoff) continue + yield* fs.remove(file).pipe(Effect.catch(() => Effect.void)) } }) diff --git a/packages/opencode/test/tool/truncation.test.ts b/packages/opencode/test/tool/truncation.test.ts index d575a58ffa3..891d45d2fce 100644 --- a/packages/opencode/test/tool/truncation.test.ts +++ b/packages/opencode/test/tool/truncation.test.ts @@ -242,18 +242,20 @@ describe("Truncate", () => { describe("cleanup", () => { const DAY_MS = 24 * 60 * 60 * 1000 - it.live("deletes files older than 7 days and preserves recent files", () => + it.live("uses file mtime when IDs wrap", () => Effect.gen(function* () { const svc = yield* Truncate.Service const fs = yield* FileSystem.FileSystem yield* fs.makeDirectory(Truncate.DIR, { recursive: true }) - const old = path.join(Truncate.DIR, Identifier.create("tool", "ascending", Date.now() - 10 * DAY_MS)) - const recent = path.join(Truncate.DIR, Identifier.create("tool", "ascending", Date.now() - 3 * DAY_MS)) + const old = path.join(Truncate.DIR, Identifier.create("tool", "ascending", 2 ** 36 - 1)) + const recent = path.join(Truncate.DIR, Identifier.create("tool", "ascending", 2 ** 36 + 1)) yield* writeFileStringScoped(old, "old content") yield* writeFileStringScoped(recent, "recent content") + yield* fs.utimes(old, new Date(), new Date(Date.now() - 10 * DAY_MS)) + yield* fs.utimes(recent, new Date(), new Date(Date.now() - 3 * DAY_MS)) yield* svc.cleanup() expect(yield* fs.exists(old)).toBe(false)