From 8fd4568071206a4f31de064205f7808e95606c85 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 18 Feb 2026 10:55:25 -0500 Subject: [PATCH 1/3] refactor: migrate src/skill/discovery.ts from Bun.file()/Bun.write() to Filesystem module Replace Bun-specific file operations with Filesystem module: - Add Filesystem import from ../util/filesystem - Replace Bun.file().exists() with Filesystem.exists() - Replace Bun.write() with Filesystem.write() All 17 skill tests pass. --- packages/opencode/src/skill/discovery.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/skill/discovery.ts b/packages/opencode/src/skill/discovery.ts index a4bf97d7a1..3e31990d64 100644 --- a/packages/opencode/src/skill/discovery.ts +++ b/packages/opencode/src/skill/discovery.ts @@ -2,6 +2,7 @@ import path from "path" import { mkdir } from "fs/promises" import { Log } from "../util/log" import { Global } from "../global" +import { Filesystem } from "../util/filesystem" export namespace Discovery { const log = Log.create({ service: "skill-discovery" }) @@ -19,14 +20,14 @@ export namespace Discovery { } async function get(url: string, dest: string): Promise { - if (await Bun.file(dest).exists()) return true + if (await Filesystem.exists(dest)) return true return fetch(url) .then(async (response) => { if (!response.ok) { log.error("failed to download", { url, status: response.status }) return false } - await Bun.write(dest, await response.text()) + await Filesystem.write(dest, await response.text()) return true }) .catch((err) => { @@ -88,7 +89,7 @@ export namespace Discovery { ) const md = path.join(root, "SKILL.md") - if (await Bun.file(md).exists()) result.push(root) + if (await Filesystem.exists(md)) result.push(root) }), ) From 3871578db6037bec987e6bf4b0e4bb8010335338 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 18 Feb 2026 18:05:42 -0500 Subject: [PATCH 2/3] refactor: use writeStream for downloading skills to avoid buffering --- packages/opencode/src/skill/discovery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/skill/discovery.ts b/packages/opencode/src/skill/discovery.ts index 3e31990d64..846002cdae 100644 --- a/packages/opencode/src/skill/discovery.ts +++ b/packages/opencode/src/skill/discovery.ts @@ -27,7 +27,7 @@ export namespace Discovery { log.error("failed to download", { url, status: response.status }) return false } - await Filesystem.write(dest, await response.text()) + if (response.body) await Filesystem.writeStream(dest, response.body) return true }) .catch((err) => { From 2a6f89d70592ec6750acbf818505937bd0108f74 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 18 Feb 2026 18:26:57 -0500 Subject: [PATCH 3/3] core: use Filesystem utility for consistent file operations with better error handling --- packages/opencode/src/session/prompt.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index d1f4072586..3d6c2c6099 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -27,6 +27,7 @@ import { MCP } from "../mcp" import { LSP } from "../lsp" import { ReadTool } from "../tool/read" import { FileTime } from "../file/time" +import { Filesystem } from "../util/filesystem" import { Flag } from "../flag/flag" import { ulid } from "ulid" import { spawn } from "child_process" @@ -1082,11 +1083,9 @@ export namespace SessionPrompt { // have to normalize, symbol search returns absolute paths // Decode the pathname since URL constructor doesn't automatically decode it const filepath = fileURLToPath(part.url) - const stat = await Bun.file(filepath) - .stat() - .catch(() => undefined) + const s = Filesystem.stat(filepath) - if (stat?.isDirectory()) { + if (s?.isDirectory()) { part.mime = "application/x-directory" } @@ -1233,14 +1232,13 @@ export namespace SessionPrompt { ] } - const file = Bun.file(filepath) FileTime.read(input.sessionID, filepath) return [ { messageID: info.id, sessionID: input.sessionID, type: "text", - text: `Called the Read tool with the following input: {\"filePath\":\"${filepath}\"}`, + text: `Called the Read tool with the following input: {"filePath":"${filepath}"}`, synthetic: true, }, { @@ -1248,7 +1246,8 @@ export namespace SessionPrompt { messageID: info.id, sessionID: input.sessionID, type: "file", - url: `data:${part.mime};base64,` + Buffer.from(await file.bytes()).toString("base64"), + url: + `data:${part.mime};base64,` + Buffer.from(await Filesystem.readBytes(filepath)).toString("base64"), mime: part.mime, filename: part.filename!, source: part.source, @@ -1354,7 +1353,7 @@ export namespace SessionPrompt { // Switching from plan mode to build mode if (input.agent.name !== "plan" && assistantMessage?.info.agent === "plan") { const plan = Session.plan(input.session) - const exists = await Bun.file(plan).exists() + const exists = await Filesystem.exists(plan) if (exists) { const part = await Session.updatePart({ id: Identifier.ascending("part"), @@ -1373,7 +1372,7 @@ export namespace SessionPrompt { // Entering plan mode if (input.agent.name === "plan" && assistantMessage?.info.agent !== "plan") { const plan = Session.plan(input.session) - const exists = await Bun.file(plan).exists() + const exists = await Filesystem.exists(plan) if (!exists) await fs.mkdir(path.dirname(plan), { recursive: true }) const part = await Session.updatePart({ id: Identifier.ascending("part"),