summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrendan Allan <[email protected]>2026-04-11 10:43:40 +0800
committerGitHub <[email protected]>2026-04-11 10:43:40 +0800
commitb6af4d0dc6fb37ffb2b4fb621e53593b12aa32a1 (patch)
tree39831e64f23f3e1cff9d17a21c302a2d866db512
parent577139c62606630fee8e82ec2021f71e66d54b1f (diff)
downloadopencode-b6af4d0dc6fb37ffb2b4fb621e53593b12aa32a1.tar.gz
opencode-b6af4d0dc6fb37ffb2b4fb621e53593b12aa32a1.zip
refactor(config): pass instance context to containsPath (#21882)
-rw-r--r--packages/opencode/src/config/config.ts37
-rw-r--r--packages/opencode/src/project/instance.ts7
2 files changed, 25 insertions, 19 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index ff79b739f..eabf971f4 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -41,6 +41,7 @@ import { Duration, Effect, Layer, Option, ServiceMap } from "effect"
import { Flock } from "@/util/flock"
import { isPathPluginSpec, parsePluginSpecifier, resolvePathPluginTarget } from "@/plugin/shared"
import { Npm } from "@/npm"
+import { InstanceRef } from "@/effect/instance-ref"
export namespace Config {
const ModelId = z.string().meta({ $ref: "https://models.dev/model-schema.json#/$defs/Model" })
@@ -1327,27 +1328,31 @@ export namespace Config {
const consoleManagedProviders = new Set<string>()
let activeOrgName: string | undefined
- const scope = (source: string): PluginScope => {
+ const scope = Effect.fnUntraced(function* (source: string) {
if (source.startsWith("http://") || source.startsWith("https://")) return "global"
if (source === "OPENCODE_CONFIG_CONTENT") return "local"
- if (Instance.containsPath(source)) return "local"
+ if (yield* InstanceRef.use((ctx) => Effect.succeed(Instance.containsPath(source, ctx)))) return "local"
return "global"
- }
+ })
- const track = (source: string, list: PluginSpec[] | undefined, kind?: PluginScope) => {
+ const track = Effect.fnUntraced(function* (
+ source: string,
+ list: PluginSpec[] | undefined,
+ kind?: PluginScope,
+ ) {
if (!list?.length) return
- const hit = kind ?? scope(source)
+ const hit = kind ?? (yield* scope(source))
const plugins = deduplicatePluginOrigins([
...(result.plugin_origins ?? []),
...list.map((spec) => ({ spec, source, scope: hit })),
])
result.plugin = plugins.map((item) => item.spec)
result.plugin_origins = plugins
- }
+ })
const merge = (source: string, next: Info, kind?: PluginScope) => {
result = mergeConfigConcatArrays(result, next)
- track(source, next.plugin, kind)
+ return track(source, next.plugin, kind)
}
for (const [key, value] of Object.entries(auth)) {
@@ -1367,16 +1372,16 @@ export namespace Config {
dir: path.dirname(source),
source,
})
- merge(source, next, "global")
+ yield* merge(source, next, "global")
log.debug("loaded remote config from well-known", { url })
}
}
const global = yield* getGlobal()
- merge(Global.Path.config, global, "global")
+ yield* merge(Global.Path.config, global, "global")
if (Flag.OPENCODE_CONFIG) {
- merge(Flag.OPENCODE_CONFIG, yield* loadFile(Flag.OPENCODE_CONFIG))
+ yield* merge(Flag.OPENCODE_CONFIG, yield* loadFile(Flag.OPENCODE_CONFIG))
log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG })
}
@@ -1384,7 +1389,7 @@ export namespace Config {
for (const file of yield* Effect.promise(() =>
ConfigPaths.projectFiles("opencode", ctx.directory, ctx.worktree),
)) {
- merge(file, yield* loadFile(file), "local")
+ yield* merge(file, yield* loadFile(file), "local")
}
}
@@ -1405,7 +1410,7 @@ export namespace Config {
for (const file of ["opencode.json", "opencode.jsonc"]) {
const source = path.join(dir, file)
log.debug(`loading config from ${source}`)
- merge(source, yield* loadFile(source))
+ yield* merge(source, yield* loadFile(source))
result.agent ??= {}
result.mode ??= {}
result.plugin ??= []
@@ -1424,7 +1429,7 @@ export namespace Config {
result.agent = mergeDeep(result.agent, yield* Effect.promise(() => loadAgent(dir)))
result.agent = mergeDeep(result.agent, yield* Effect.promise(() => loadMode(dir)))
const list = yield* Effect.promise(() => loadPlugin(dir))
- track(dir, list)
+ yield* track(dir, list)
}
if (process.env.OPENCODE_CONFIG_CONTENT) {
@@ -1433,7 +1438,7 @@ export namespace Config {
dir: ctx.directory,
source,
})
- merge(source, next, "local")
+ yield* merge(source, next, "local")
log.debug("loaded custom config from OPENCODE_CONFIG_CONTENT")
}
@@ -1462,7 +1467,7 @@ export namespace Config {
for (const providerID of Object.keys(next.provider ?? {})) {
consoleManagedProviders.add(providerID)
}
- merge(source, next, "global")
+ yield* merge(source, next, "global")
}
}).pipe(
Effect.catch((err) => {
@@ -1477,7 +1482,7 @@ export namespace Config {
if (existsSync(managedDir)) {
for (const file of ["opencode.json", "opencode.jsonc"]) {
const source = path.join(managedDir, file)
- merge(source, yield* loadFile(source), "global")
+ yield* merge(source, yield* loadFile(source), "global")
}
}
diff --git a/packages/opencode/src/project/instance.ts b/packages/opencode/src/project/instance.ts
index 33078183b..60665a99a 100644
--- a/packages/opencode/src/project/instance.ts
+++ b/packages/opencode/src/project/instance.ts
@@ -90,12 +90,13 @@ export const Instance = {
* Returns true if path is inside Instance.directory OR Instance.worktree.
* Paths within the worktree but outside the working directory should not trigger external_directory permission.
*/
- containsPath(filepath: string) {
- if (Filesystem.contains(Instance.directory, filepath)) return true
+ containsPath(filepath: string, ctx?: InstanceContext) {
+ const instance = ctx ?? Instance
+ if (Filesystem.contains(instance.directory, filepath)) return true
// Non-git projects set worktree to "/" which would match ANY absolute path.
// Skip worktree check in this case to preserve external_directory permissions.
if (Instance.worktree === "/") return false
- return Filesystem.contains(Instance.worktree, filepath)
+ return Filesystem.contains(instance.worktree, filepath)
},
/**
* Captures the current instance ALS context and returns a wrapper that