|
|
@@ -4,7 +4,7 @@ import { z } from "zod"
|
|
|
import { App } from "../app/app"
|
|
|
import { Filesystem } from "../util/filesystem"
|
|
|
import { ModelsDev } from "../provider/models"
|
|
|
-import { mergeDeep } from "remeda"
|
|
|
+import { mergeDeep, pipe } from "remeda"
|
|
|
import { Global } from "../global"
|
|
|
import fs from "fs/promises"
|
|
|
import { lazy } from "../util/lazy"
|
|
|
@@ -175,7 +175,11 @@ export namespace Config {
|
|
|
export type Info = z.output<typeof Info>
|
|
|
|
|
|
export const global = lazy(async () => {
|
|
|
- let result = await load(path.join(Global.Path.config, "config.json"))
|
|
|
+ let result = pipe(
|
|
|
+ {},
|
|
|
+ mergeDeep(await load(path.join(Global.Path.config, "config.json"))),
|
|
|
+ mergeDeep(await load(path.join(Global.Path.config, "opencode.json"))),
|
|
|
+ )
|
|
|
|
|
|
await import(path.join(Global.Path.config, "config"), {
|
|
|
with: {
|
|
|
@@ -199,9 +203,10 @@ export namespace Config {
|
|
|
let text = await Bun.file(configPath)
|
|
|
.text()
|
|
|
.catch((err) => {
|
|
|
- if (err.code === "ENOENT") return "{}"
|
|
|
+ if (err.code === "ENOENT") return
|
|
|
throw new JsonError({ path: configPath }, { cause: err })
|
|
|
})
|
|
|
+ if (!text) return {}
|
|
|
|
|
|
text = text.replace(/\{env:([^}]+)\}/g, (_, varName) => {
|
|
|
return process.env[varName] || ""
|
|
|
@@ -226,7 +231,13 @@ export namespace Config {
|
|
|
}
|
|
|
|
|
|
const parsed = Info.safeParse(data)
|
|
|
- if (parsed.success) return parsed.data
|
|
|
+ if (parsed.success) {
|
|
|
+ if (!parsed.data.$schema) {
|
|
|
+ parsed.data.$schema = "https://opencode.ai/config.json"
|
|
|
+ await Bun.write(configPath, JSON.stringify(parsed.data, null, 2))
|
|
|
+ }
|
|
|
+ return parsed.data
|
|
|
+ }
|
|
|
throw new InvalidError({ path: configPath, issues: parsed.error.issues })
|
|
|
}
|
|
|
export const JsonError = NamedError.create(
|