Parcourir la source

fix(cli): load v2 tui config (#36466)

Co-authored-by: Dax Raad <d@ironbay.co>
opencode-agent[bot] il y a 1 mois
Parent
commit
8f904c8e9a

+ 2 - 2
packages/cli/src/commands/handlers/default.ts

@@ -2,9 +2,9 @@ import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { Global } from "@opencode-ai/core/global"
 import { run } from "@opencode-ai/tui"
 import { loadBuiltinPlugins } from "@opencode-ai/tui/builtins"
-import { TuiConfig } from "@opencode-ai/tui/config"
 import { Commands } from "../commands"
 import { Runtime } from "../../framework/runtime"
+import { TuiConfig } from "../../tui-config"
 import { Effect, Option } from "effect"
 import { Server } from "../../services/server"
 import { Updater } from "../../services/updater"
@@ -34,7 +34,7 @@ export default Runtime.handler(Commands, (input) =>
       ),
     )
     yield* Effect.promise(() => preflight.finish())
-    const config = TuiConfig.resolve({}, { terminalSuspend: false })
+    const config = yield* TuiConfig.load()
     let disposeSlots: (() => void) | undefined
     const runFork = Effect.runForkWith(yield* Effect.context())
     yield* run({

+ 24 - 0
packages/cli/src/tui-config.ts

@@ -0,0 +1,24 @@
+export * as TuiConfig from "./tui-config"
+
+import { Global } from "@opencode-ai/core/global"
+import { TuiConfig } from "@opencode-ai/tui/config"
+import { Effect, FileSystem, Option, Schema } from "effect"
+import { parse, type ParseError } from "jsonc-parser"
+import path from "path"
+
+export const load = Effect.fn("TuiConfig.load")(function* () {
+  const fs = yield* FileSystem.FileSystem
+  const global = yield* Global.Service
+  const filepath = path.join(global.config, "tui.json")
+  const text = yield* fs.readFileString(filepath).pipe(Effect.catch(() => Effect.succeed(undefined)))
+  if (!text) return TuiConfig.resolve({}, { terminalSuspend: process.platform !== "win32" })
+
+  const errors: ParseError[] = []
+  const input: unknown = parse(text, errors, { allowTrailingComma: true })
+  if (errors.length) return TuiConfig.resolve({}, { terminalSuspend: process.platform !== "win32" })
+
+  return TuiConfig.resolve(
+    Option.getOrElse(Schema.decodeUnknownOption(TuiConfig.Info)(input), () => ({})),
+    { terminalSuspend: process.platform !== "win32" },
+  )
+})

+ 25 - 0
packages/cli/test/tui-config.test.ts

@@ -0,0 +1,25 @@
+import { NodeFileSystem } from "@effect/platform-node"
+import { Global } from "@opencode-ai/core/global"
+import { Effect } from "effect"
+import { expect, test } from "bun:test"
+import path from "path"
+import { TuiConfig } from "../src/tui-config"
+
+test("loads the global tui config", async () => {
+  const directory = await Bun.$`mktemp -d`.text().then((value) => value.trim())
+  await Bun.write(path.join(directory, "tui.json"), JSON.stringify({ keybinds: { leader: "ctrl+o" } }))
+
+  try {
+    const config = await Effect.runPromise(
+      TuiConfig.load().pipe(
+        Effect.provide(Global.layerWith({ config: directory })),
+        Effect.provide(NodeFileSystem.layer),
+      ),
+    )
+
+    expect(config.keybinds.get("leader")?.[0]?.key).toBe("ctrl+o")
+    expect(config.keybinds.get("session.new")?.[0]?.key).toBe("<leader>n")
+  } finally {
+    await Bun.$`rm -rf ${directory}`
+  }
+})