diff --git a/bun.lock b/bun.lock index a78c9245ce4..a9821225cf6 100644 --- a/bun.lock +++ b/bun.lock @@ -401,6 +401,7 @@ "opentui-spinner": "0.0.6", "partial-json": "0.1.7", "remeda": "catalog:", + "rotating-file-stream": "3.2.9", "simple-git": "3.31.1", "solid-js": "catalog:", "strip-ansi": "7.1.2", @@ -3797,6 +3798,8 @@ "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], + "rotating-file-stream": ["rotating-file-stream@3.2.9", "", {}, "sha512-i9i0KkHh12ryl4xtELg+0gyoFre2PJ9RcQQLzquWsiqygyYsrZLckrqqYrthhnJZGZb4g+KUHtcoWYVq34gaug=="], + "roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="], "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 5d184292e35..91a053b04c7 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -126,6 +126,7 @@ "opentui-spinner": "0.0.6", "partial-json": "0.1.7", "remeda": "catalog:", + "rotating-file-stream": "3.2.9", "simple-git": "3.31.1", "solid-js": "catalog:", "strip-ansi": "7.1.2", diff --git a/packages/opencode/src/util/log.ts b/packages/opencode/src/util/log.ts index 2ca4c0a3de3..e080648bc4d 100644 --- a/packages/opencode/src/util/log.ts +++ b/packages/opencode/src/util/log.ts @@ -1,9 +1,9 @@ import path from "path" import fs from "fs/promises" -import { createWriteStream } from "fs" import { Global } from "../global" import z from "zod" import { Glob } from "./glob" +import { createStream } from "rotating-file-stream" // kilocode_change export namespace Log { export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" }) @@ -66,15 +66,25 @@ export namespace Log { options.dev ? "dev.log" : new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log", ) await fs.truncate(logpath).catch(() => {}) - const stream = createWriteStream(logpath, { flags: "a" }) - write = async (msg: any) => { - return new Promise((resolve, reject) => { - stream.write(msg, (err) => { - if (err) reject(err) - else resolve(msg.length) - }) - }) + // kilocode_change start - use rotating-file-stream to cap log files at 50 MB + const dir = path.dirname(logpath) + const stream = createStream(path.basename(logpath), { + size: "50M", + maxFiles: 10, + history: path.join(dir, ".log-history"), + path: dir, + }) + stream.on("error", (err: Error) => { + process.stderr.write("log stream error: " + err.message + "\n") + }) + stream.on("warning", (err: Error) => { + process.stderr.write("log stream warning: " + err.message + "\n") + }) + write = (msg: any) => { + stream.write(msg) + return msg.length } + // kilocode_change end } async function cleanup(dir: string) {