refactor(opencode): use AppFileSystem path helpers (#22637)

This commit is contained in:
Kit Langton
2026-04-15 19:36:30 -04:00
committed by GitHub
parent 672ee28635
commit 4dd0d1f67e
5 changed files with 14 additions and 17 deletions
+2 -3
View File
@@ -10,7 +10,6 @@ import { Flag } from "@/flag/flag"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { isRecord } from "@/util/record" import { isRecord } from "@/util/record"
import { Global } from "@/global" import { Global } from "@/global"
import { Filesystem } from "@/util/filesystem"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { AppFileSystem } from "@opencode-ai/shared/filesystem"
@@ -42,8 +41,8 @@ export namespace TuiConfig {
export class Service extends Context.Service<Service, Interface>()("@opencode/TuiConfig") {} export class Service extends Context.Service<Service, Interface>()("@opencode/TuiConfig") {}
function pluginScope(file: string, ctx: { directory: string; worktree: string }): Config.PluginScope { function pluginScope(file: string, ctx: { directory: string; worktree: string }): Config.PluginScope {
if (Filesystem.contains(ctx.directory, file)) return "local" if (AppFileSystem.contains(ctx.directory, file)) return "local"
if (ctx.worktree !== "/" && Filesystem.contains(ctx.worktree, file)) return "local" if (ctx.worktree !== "/" && AppFileSystem.contains(ctx.worktree, file)) return "local"
return "global" return "global"
} }
+4 -5
View File
@@ -3,7 +3,6 @@ import { InstanceState } from "@/effect/instance-state"
import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { AppFileSystem } from "@opencode-ai/shared/filesystem"
import { Flag } from "@/flag/flag" import { Flag } from "@/flag/flag"
import type { SessionID } from "@/session/schema" import type { SessionID } from "@/session/schema"
import { Filesystem } from "@/util/filesystem"
import { Log } from "../util/log" import { Log } from "../util/log"
export namespace FileTime { export namespace FileTime {
@@ -62,7 +61,7 @@ export namespace FileTime {
) )
const getLock = Effect.fn("FileTime.lock")(function* (filepath: string) { const getLock = Effect.fn("FileTime.lock")(function* (filepath: string) {
filepath = Filesystem.normalizePath(filepath) filepath = AppFileSystem.normalizePath(filepath)
const locks = (yield* InstanceState.get(state)).locks const locks = (yield* InstanceState.get(state)).locks
const lock = locks.get(filepath) const lock = locks.get(filepath)
if (lock) return lock if (lock) return lock
@@ -73,21 +72,21 @@ export namespace FileTime {
}) })
const read = Effect.fn("FileTime.read")(function* (sessionID: SessionID, file: string) { const read = Effect.fn("FileTime.read")(function* (sessionID: SessionID, file: string) {
file = Filesystem.normalizePath(file) file = AppFileSystem.normalizePath(file)
const reads = (yield* InstanceState.get(state)).reads const reads = (yield* InstanceState.get(state)).reads
log.info("read", { sessionID, file }) log.info("read", { sessionID, file })
session(reads, sessionID).set(file, yield* stamp(file)) session(reads, sessionID).set(file, yield* stamp(file))
}) })
const get = Effect.fn("FileTime.get")(function* (sessionID: SessionID, file: string) { const get = Effect.fn("FileTime.get")(function* (sessionID: SessionID, file: string) {
file = Filesystem.normalizePath(file) file = AppFileSystem.normalizePath(file)
const reads = (yield* InstanceState.get(state)).reads const reads = (yield* InstanceState.get(state)).reads
return reads.get(sessionID)?.get(file)?.read return reads.get(sessionID)?.get(file)?.read
}) })
const assert = Effect.fn("FileTime.assert")(function* (sessionID: SessionID, filepath: string) { const assert = Effect.fn("FileTime.assert")(function* (sessionID: SessionID, filepath: string) {
if (disableCheck) return if (disableCheck) return
filepath = Filesystem.normalizePath(filepath) filepath = AppFileSystem.normalizePath(filepath)
const reads = (yield* InstanceState.get(state)).reads const reads = (yield* InstanceState.get(state)).reads
const time = reads.get(sessionID)?.get(filepath) const time = reads.get(sessionID)?.get(filepath)
+5 -5
View File
@@ -1,7 +1,7 @@
import { GlobalBus } from "@/bus/global" import { GlobalBus } from "@/bus/global"
import { disposeInstance } from "@/effect/instance-registry" import { disposeInstance } from "@/effect/instance-registry"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { Filesystem } from "@/util/filesystem" import { AppFileSystem } from "@opencode-ai/shared/filesystem"
import { iife } from "@/util/iife" import { iife } from "@/util/iife"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { LocalContext } from "../util/local-context" import { LocalContext } from "../util/local-context"
@@ -56,7 +56,7 @@ function track(directory: string, next: Promise<InstanceContext>) {
export const Instance = { export const Instance = {
async provide<R>(input: { directory: string; init?: () => Promise<any>; fn: () => R }): Promise<R> { async provide<R>(input: { directory: string; init?: () => Promise<any>; fn: () => R }): Promise<R> {
const directory = Filesystem.resolve(input.directory) const directory = AppFileSystem.resolve(input.directory)
let existing = cache.get(directory) let existing = cache.get(directory)
if (!existing) { if (!existing) {
Log.Default.info("creating instance", { directory }) Log.Default.info("creating instance", { directory })
@@ -93,11 +93,11 @@ export const Instance = {
*/ */
containsPath(filepath: string, ctx?: InstanceContext) { containsPath(filepath: string, ctx?: InstanceContext) {
const instance = ctx ?? Instance const instance = ctx ?? Instance
if (Filesystem.contains(instance.directory, filepath)) return true if (AppFileSystem.contains(instance.directory, filepath)) return true
// Non-git projects set worktree to "/" which would match ANY absolute path. // Non-git projects set worktree to "/" which would match ANY absolute path.
// Skip worktree check in this case to preserve external_directory permissions. // Skip worktree check in this case to preserve external_directory permissions.
if (Instance.worktree === "/") return false if (Instance.worktree === "/") return false
return Filesystem.contains(instance.worktree, filepath) return AppFileSystem.contains(instance.worktree, filepath)
}, },
/** /**
* Captures the current instance ALS context and returns a wrapper that * Captures the current instance ALS context and returns a wrapper that
@@ -117,7 +117,7 @@ export const Instance = {
return context.provide(ctx, fn) return context.provide(ctx, fn)
}, },
async reload(input: { directory: string; init?: () => Promise<any>; project?: Project.Info; worktree?: string }) { async reload(input: { directory: string; init?: () => Promise<any>; project?: Project.Info; worktree?: string }) {
const directory = Filesystem.resolve(input.directory) const directory = AppFileSystem.resolve(input.directory)
Log.Default.info("reloading instance", { directory }) Log.Default.info("reloading instance", { directory })
await disposeInstance(directory) await disposeInstance(directory)
cache.delete(directory) cache.delete(directory)
@@ -4,7 +4,6 @@ import { getAdaptor } from "@/control-plane/adaptors"
import { WorkspaceID } from "@/control-plane/schema" import { WorkspaceID } from "@/control-plane/schema"
import { Workspace } from "@/control-plane/workspace" import { Workspace } from "@/control-plane/workspace"
import { ServerProxy } from "../proxy" import { ServerProxy } from "../proxy"
import { Filesystem } from "@/util/filesystem"
import { Instance } from "@/project/instance" import { Instance } from "@/project/instance"
import { InstanceBootstrap } from "@/project/bootstrap" import { InstanceBootstrap } from "@/project/bootstrap"
import { Session } from "@/session" import { Session } from "@/session"
@@ -12,6 +11,7 @@ import { SessionID } from "@/session/schema"
import { WorkspaceContext } from "@/control-plane/workspace-context" import { WorkspaceContext } from "@/control-plane/workspace-context"
import { AppRuntime } from "@/effect/app-runtime" import { AppRuntime } from "@/effect/app-runtime"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
type Rule = { method?: string; path: string; exact?: boolean; action: "local" | "forward" } type Rule = { method?: string; path: string; exact?: boolean; action: "local" | "forward" }
@@ -53,7 +53,7 @@ export function WorkspaceRouterMiddleware(upgrade: UpgradeWebSocket): Middleware
return async (c, next) => { return async (c, next) => {
const raw = c.req.query("directory") || c.req.header("x-opencode-directory") || process.cwd() const raw = c.req.query("directory") || c.req.header("x-opencode-directory") || process.cwd()
const directory = Filesystem.resolve( const directory = AppFileSystem.resolve(
(() => { (() => {
try { try {
return decodeURIComponent(raw) return decodeURIComponent(raw)
+1 -2
View File
@@ -15,7 +15,6 @@ import { FileWatcher } from "../file/watcher"
import { Bus } from "../bus" import { Bus } from "../bus"
import { Format } from "../format" import { Format } from "../format"
import { FileTime } from "../file/time" import { FileTime } from "../file/time"
import { Filesystem } from "../util/filesystem"
import { Instance } from "../project/instance" import { Instance } from "../project/instance"
import { Snapshot } from "@/snapshot" import { Snapshot } from "@/snapshot"
import { assertExternalDirectoryEffect } from "./external-directory" import { assertExternalDirectoryEffect } from "./external-directory"
@@ -169,7 +168,7 @@ export const EditTool = Tool.define(
let output = "Edit applied successfully." let output = "Edit applied successfully."
yield* lsp.touchFile(filePath, true) yield* lsp.touchFile(filePath, true)
const diagnostics = yield* lsp.diagnostics() const diagnostics = yield* lsp.diagnostics()
const normalizedFilePath = Filesystem.normalizePath(filePath) const normalizedFilePath = AppFileSystem.normalizePath(filePath)
const block = LSP.Diagnostic.report(filePath, diagnostics[normalizedFilePath] ?? []) const block = LSP.Diagnostic.report(filePath, diagnostics[normalizedFilePath] ?? [])
if (block) output += `\n\nLSP errors detected in this file, please fix:\n${block}` if (block) output += `\n\nLSP errors detected in this file, please fix:\n${block}`