fix(opencode): use file times for truncation cleanup (#40987)

Co-authored-by: Dax <mail@thdxr.com>
This commit is contained in:
opencode-agent[bot] 2026-08-07 03:58:31 +00:00 committed by GitHub
parent 31c5c4e924
commit d468201952
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 9 deletions

View file

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

View file

@ -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)