Skip to content

Commit d995059

Browse files
authored
core: migrate config loading to Effect framework (#23032)
1 parent 81f0885 commit d995059

5 files changed

Lines changed: 265 additions & 253 deletions

File tree

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ export function tui(input: {
135135
await TuiPluginRuntime.dispose()
136136
}
137137

138+
console.log("starting renderer")
138139
const renderer = await createCliRenderer(rendererConfig(input.config))
140+
console.log("renderer started")
139141

140142
await render(() => {
141143
return (

packages/opencode/src/cli/cmd/tui/config/tui-migrate.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,10 @@ async function backupAndStripLegacy(file: string, source: string) {
132132
}
133133

134134
async function opencodeFiles(input: { directories: string[]; cwd: string }) {
135-
const project = Flag.OPENCODE_DISABLE_PROJECT_CONFIG ? [] : await ConfigPaths.projectFiles("opencode", input.cwd)
136-
const files = [...project, ...ConfigPaths.fileInDirectory(Global.Path.config, "opencode")]
135+
const files = [
136+
...ConfigPaths.fileInDirectory(Global.Path.config, "opencode"),
137+
...(await Filesystem.findUp(["opencode.json", "opencode.jsonc"], input.cwd, undefined, { rootFirst: true })),
138+
]
137139
for (const dir of unique(input.directories)) {
138140
files.push(...ConfigPaths.fileInDirectory(dir, "opencode"))
139141
}

packages/opencode/src/cli/cmd/tui/config/tui.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,34 +89,33 @@ async function mergeFile(acc: Acc, file: string, ctx: { directory: string }) {
8989
acc.result.plugin_origins = plugins
9090
}
9191

92-
async function loadState(ctx: { directory: string }) {
92+
const loadState = Effect.fn("TuiConfig.loadState")(function* (ctx: { directory: string }) {
9393
// Every config dir we may read from: global config dir, any `.opencode`
9494
// folders between cwd and home, and OPENCODE_CONFIG_DIR.
95-
const directories = await ConfigPaths.directories(ctx.directory)
96-
// One-time migration: extract tui keys (theme/keybinds/tui) from existing
97-
// opencode.json files into sibling tui.json files.
98-
await migrateTuiConfig({ directories, cwd: ctx.directory })
95+
const directories = yield* ConfigPaths.directories(ctx.directory)
96+
yield* Effect.promise(() => migrateTuiConfig({ directories, cwd: ctx.directory }))
9997

100-
const projectFiles = Flag.OPENCODE_DISABLE_PROJECT_CONFIG ? [] : await ConfigPaths.projectFiles("tui", ctx.directory)
98+
const projectFiles = Flag.OPENCODE_DISABLE_PROJECT_CONFIG ? [] : yield* ConfigPaths.files("tui", ctx.directory)
10199

102100
const acc: Acc = {
103101
result: {},
104102
}
105103

106104
// 1. Global tui config (lowest precedence).
107105
for (const file of ConfigPaths.fileInDirectory(Global.Path.config, "tui")) {
108-
await mergeFile(acc, file, ctx)
106+
yield* Effect.promise(() => mergeFile(acc, file, ctx)).pipe(Effect.orDie)
109107
}
110108

111109
// 2. Explicit OPENCODE_TUI_CONFIG override, if set.
112110
if (Flag.OPENCODE_TUI_CONFIG) {
113-
await mergeFile(acc, Flag.OPENCODE_TUI_CONFIG, ctx)
114-
log.debug("loaded custom tui config", { path: Flag.OPENCODE_TUI_CONFIG })
111+
const configFile = Flag.OPENCODE_TUI_CONFIG
112+
yield* Effect.promise(() => mergeFile(acc, configFile, ctx)).pipe(Effect.orDie)
113+
log.debug("loaded custom tui config", { path: configFile })
115114
}
116115

117116
// 3. Project tui files, applied root-first so the closest file wins.
118117
for (const file of projectFiles) {
119-
await mergeFile(acc, file, ctx)
118+
yield* Effect.promise(() => mergeFile(acc, file, ctx)).pipe(Effect.orDie)
120119
}
121120

122121
// 4. `.opencode` directories (and OPENCODE_CONFIG_DIR) discovered while
@@ -127,7 +126,7 @@ async function loadState(ctx: { directory: string }) {
127126
for (const dir of dirs) {
128127
if (!dir.endsWith(".opencode") && dir !== Flag.OPENCODE_CONFIG_DIR) continue
129128
for (const file of ConfigPaths.fileInDirectory(dir, "tui")) {
130-
await mergeFile(acc, file, ctx)
129+
yield* Effect.promise(() => mergeFile(acc, file, ctx)).pipe(Effect.orDie)
131130
}
132131
}
133132

@@ -146,14 +145,14 @@ async function loadState(ctx: { directory: string }) {
146145
config: acc.result,
147146
dirs: acc.result.plugin?.length ? dirs : [],
148147
}
149-
}
148+
})
150149

151150
export const layer = Layer.effect(
152151
Service,
153152
Effect.gen(function* () {
154153
const directory = yield* CurrentWorkingDirectory
155154
const npm = yield* Npm.Service
156-
const data = yield* Effect.promise(() => loadState({ directory }))
155+
const data = yield* loadState({ directory })
157156
const deps = yield* Effect.forEach(
158157
data.dirs,
159158
(dir) =>
@@ -176,7 +175,7 @@ export const layer = Layer.effect(
176175
}).pipe(Effect.withSpan("TuiConfig.layer")),
177176
)
178177

179-
export const defaultLayer = layer.pipe(Layer.provide(Npm.defaultLayer))
178+
export const defaultLayer = layer.pipe(Layer.provide(Npm.defaultLayer), Layer.provide(AppFileSystem.defaultLayer))
180179

181180
const { runPromise } = makeRuntime(Service, defaultLayer)
182181

0 commit comments

Comments
 (0)