summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/cli/cmd/tui/worker.ts3
-rw-r--r--packages/opencode/src/cli/heap.ts59
-rw-r--r--packages/opencode/src/flag/flag.ts1
-rw-r--r--packages/opencode/src/index.ts3
4 files changed, 66 insertions, 0 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/worker.ts b/packages/opencode/src/cli/cmd/tui/worker.ts
index a83645d89..643676e34 100644
--- a/packages/opencode/src/cli/cmd/tui/worker.ts
+++ b/packages/opencode/src/cli/cmd/tui/worker.ts
@@ -13,6 +13,7 @@ import { Flag } from "@/flag/flag"
import { setTimeout as sleep } from "node:timers/promises"
import { writeHeapSnapshot } from "node:v8"
import { WorkspaceID } from "@/control-plane/schema"
+import { Heap } from "@/cli/heap"
await Log.init({
print: process.argv.includes("--print-logs"),
@@ -23,6 +24,8 @@ await Log.init({
})(),
})
+Heap.start()
+
process.on("unhandledRejection", (e) => {
Log.Default.error("rejection", {
e: e instanceof Error ? e.message : e,
diff --git a/packages/opencode/src/cli/heap.ts b/packages/opencode/src/cli/heap.ts
new file mode 100644
index 000000000..bb5a3d093
--- /dev/null
+++ b/packages/opencode/src/cli/heap.ts
@@ -0,0 +1,59 @@
+import path from "path"
+import { writeHeapSnapshot } from "node:v8"
+import { Flag } from "@/flag/flag"
+import { Global } from "@/global"
+import { Log } from "@/util/log"
+
+const log = Log.create({ service: "heap" })
+const MINUTE = 60_000
+const LIMIT = 2 * 1024 * 1024 * 1024
+
+export namespace Heap {
+ let timer: Timer | undefined
+ let lock = false
+ let armed = true
+
+ export function start() {
+ if (!Flag.OPENCODE_AUTO_HEAP_SNAPSHOT) return
+ if (timer) return
+
+ const run = async () => {
+ if (lock) return
+
+ const stat = process.memoryUsage()
+ if (stat.rss <= LIMIT) {
+ armed = true
+ return
+ }
+ if (!armed) return
+
+ lock = true
+ armed = false
+ const file = path.join(
+ Global.Path.log,
+ `heap-${process.pid}-${new Date().toISOString().replace(/[:.]/g, "")}.heapsnapshot`,
+ )
+ log.warn("heap usage exceeded limit", {
+ rss: stat.rss,
+ heap: stat.heapUsed,
+ file,
+ })
+
+ await Promise.resolve()
+ .then(() => writeHeapSnapshot(file))
+ .catch((err) => {
+ log.error("failed to write heap snapshot", {
+ error: err instanceof Error ? err.message : String(err),
+ file,
+ })
+ })
+
+ lock = false
+ }
+
+ timer = setInterval(() => {
+ void run()
+ }, MINUTE)
+ timer.unref?.()
+ }
+}
diff --git a/packages/opencode/src/flag/flag.ts b/packages/opencode/src/flag/flag.ts
index 27190f2eb..1ac52dd17 100644
--- a/packages/opencode/src/flag/flag.ts
+++ b/packages/opencode/src/flag/flag.ts
@@ -12,6 +12,7 @@ function falsy(key: string) {
export namespace Flag {
export const OPENCODE_AUTO_SHARE = truthy("OPENCODE_AUTO_SHARE")
+ export const OPENCODE_AUTO_HEAP_SNAPSHOT = truthy("OPENCODE_AUTO_HEAP_SNAPSHOT")
export const OPENCODE_GIT_BASH_PATH = process.env["OPENCODE_GIT_BASH_PATH"]
export const OPENCODE_CONFIG = process.env["OPENCODE_CONFIG"]
export declare const OPENCODE_PURE: boolean
diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts
index bb14e0588..1fa027abf 100644
--- a/packages/opencode/src/index.ts
+++ b/packages/opencode/src/index.ts
@@ -35,6 +35,7 @@ import { JsonMigration } from "./storage/json-migration"
import { Database } from "./storage/db"
import { errorMessage } from "./util/error"
import { PluginCommand } from "./cli/cmd/plug"
+import { Heap } from "./cli/heap"
process.on("unhandledRejection", (e) => {
Log.Default.error("rejection", {
@@ -96,6 +97,8 @@ const cli = yargs(args)
})(),
})
+ Heap.start()
+
process.env.AGENT = "1"
process.env.OPENCODE = "1"
process.env.OPENCODE_PID = String(process.pid)