mirror of
https://github.com/anomalyco/opencode.git
synced 2026-02-10 02:44:21 +00:00
Compare commits
1 Commits
production
...
fix/plugin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
440eb76e52 |
@@ -145,11 +145,20 @@ export namespace Config {
|
||||
log.debug("loading config from OPENCODE_CONFIG_DIR", { path: Flag.OPENCODE_CONFIG_DIR })
|
||||
}
|
||||
|
||||
const deps = []
|
||||
const deps: Promise<void>[] = []
|
||||
|
||||
for (const dir of unique(directories)) {
|
||||
if (dir.endsWith(".opencode") || dir === Flag.OPENCODE_CONFIG_DIR) {
|
||||
for (const file of ["opencode.jsonc", "opencode.json"]) {
|
||||
const files = ["opencode.jsonc", "opencode.json"]
|
||||
const isConfigDir = dir.endsWith(".opencode") || dir === Flag.OPENCODE_CONFIG_DIR || dir === Global.Path.config
|
||||
const configs = isConfigDir
|
||||
? await Promise.all(files.map((file) => loadFile(path.join(dir, file), { resolvePlugins: false })))
|
||||
: []
|
||||
const plugins = configs.flatMap((config) => config.plugin ?? [])
|
||||
const shouldInstall = await needsInstall(dir, plugins)
|
||||
if (shouldInstall) await installDependencies(dir, plugins)
|
||||
|
||||
if (isConfigDir) {
|
||||
for (const file of files) {
|
||||
log.debug(`loading config from ${path.join(dir, file)}`)
|
||||
result = mergeConfigConcatArrays(result, await loadFile(path.join(dir, file)))
|
||||
// to satisfy the type checker
|
||||
@@ -159,13 +168,6 @@ export namespace Config {
|
||||
}
|
||||
}
|
||||
|
||||
deps.push(
|
||||
iife(async () => {
|
||||
const shouldInstall = await needsInstall(dir)
|
||||
if (shouldInstall) await installDependencies(dir)
|
||||
}),
|
||||
)
|
||||
|
||||
result.command = mergeDeep(result.command ?? {}, await loadCommand(dir))
|
||||
result.agent = mergeDeep(result.agent, await loadAgent(dir))
|
||||
result.agent = mergeDeep(result.agent, await loadMode(dir))
|
||||
@@ -247,7 +249,7 @@ export namespace Config {
|
||||
await Promise.all(deps)
|
||||
}
|
||||
|
||||
export async function installDependencies(dir: string) {
|
||||
export async function installDependencies(dir: string, plugins: string[] = []) {
|
||||
const pkg = path.join(dir, "package.json")
|
||||
const targetVersion = Installation.isLocal() ? "*" : Installation.VERSION
|
||||
|
||||
@@ -258,6 +260,10 @@ export namespace Config {
|
||||
...json.dependencies,
|
||||
"@opencode-ai/plugin": targetVersion,
|
||||
}
|
||||
const pluginDeps = deps(plugins)
|
||||
for (const [name, version] of Object.entries(pluginDeps)) {
|
||||
json.dependencies[name] = version
|
||||
}
|
||||
await Bun.write(pkg, JSON.stringify(json, null, 2))
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000))
|
||||
|
||||
@@ -286,7 +292,7 @@ export namespace Config {
|
||||
}
|
||||
}
|
||||
|
||||
async function needsInstall(dir: string) {
|
||||
async function needsInstall(dir: string, plugins: string[] = []) {
|
||||
// Some config dirs may be read-only.
|
||||
// Installing deps there will fail; skip installation in that case.
|
||||
const writable = await isWritable(dir)
|
||||
@@ -318,8 +324,27 @@ export namespace Config {
|
||||
})
|
||||
return true
|
||||
}
|
||||
if (depVersion === targetVersion) return false
|
||||
return true
|
||||
if (depVersion !== targetVersion) return true
|
||||
|
||||
const pluginDeps = deps(plugins)
|
||||
for (const [name, version] of Object.entries(pluginDeps)) {
|
||||
if (dependencies[name] !== version) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function deps(items: string[]) {
|
||||
const result: Record<string, string> = {}
|
||||
for (const item of items) {
|
||||
if (!item) continue
|
||||
if (item.startsWith("file://")) continue
|
||||
if (item.startsWith("./") || item.startsWith("../") || item.startsWith("/") || item.startsWith("~")) continue
|
||||
const lastAt = item.lastIndexOf("@")
|
||||
const pkg = lastAt > 0 ? item.substring(0, lastAt) : item
|
||||
const version = lastAt > 0 ? item.substring(lastAt + 1) : "latest"
|
||||
result[pkg] = version
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function rel(item: string, patterns: string[]) {
|
||||
@@ -1216,7 +1241,7 @@ export namespace Config {
|
||||
return result
|
||||
})
|
||||
|
||||
async function loadFile(filepath: string): Promise<Info> {
|
||||
async function loadFile(filepath: string, options: { resolvePlugins?: boolean } = {}): Promise<Info> {
|
||||
log.info("loading", { path: filepath })
|
||||
let text = await Bun.file(filepath)
|
||||
.text()
|
||||
@@ -1225,10 +1250,10 @@ export namespace Config {
|
||||
throw new JsonError({ path: filepath }, { cause: err })
|
||||
})
|
||||
if (!text) return {}
|
||||
return load(text, filepath)
|
||||
return load(text, filepath, options)
|
||||
}
|
||||
|
||||
async function load(text: string, configFilepath: string) {
|
||||
async function load(text: string, configFilepath: string, options: { resolvePlugins?: boolean } = {}) {
|
||||
const original = text
|
||||
text = text.replace(/\{env:([^}]+)\}/g, (_, varName) => {
|
||||
return process.env[varName] || ""
|
||||
@@ -1304,7 +1329,7 @@ export namespace Config {
|
||||
await Bun.write(configFilepath, updated).catch(() => {})
|
||||
}
|
||||
const data = parsed.data
|
||||
if (data.plugin) {
|
||||
if (data.plugin && options.resolvePlugins !== false) {
|
||||
for (let i = 0; i < data.plugin.length; i++) {
|
||||
const plugin = data.plugin[i]
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user