From a43de3f86d582b00c22c537221d248fddf34c31a Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 13 Jul 2026 01:05:14 -0400 Subject: [PATCH] tui: remove legacy V1 CLI TUI integration to simplify startup --- packages/opencode/script/build.ts | 4 +- packages/opencode/src/cli/cmd/attach.ts | 100 --------- packages/opencode/src/cli/cmd/tui.ts | 198 ------------------ packages/opencode/src/cli/tui/layer.ts | 8 - packages/opencode/src/cli/tui/worker.ts | 54 ----- packages/opencode/src/index.ts | 4 - packages/opencode/src/plugin/tui/runtime.ts | 9 +- packages/opencode/src/temporary.ts | 2 - packages/opencode/test/cli/tui/attach.test.ts | 11 - packages/opencode/test/cli/tui/thread.test.ts | 89 -------- packages/tui/src/app.tsx | 67 +----- packages/tui/src/config/index.tsx | 3 +- packages/tui/src/plugin/runtime.tsx | 1 - 13 files changed, 8 insertions(+), 542 deletions(-) delete mode 100644 packages/opencode/src/cli/cmd/attach.ts delete mode 100644 packages/opencode/src/cli/cmd/tui.ts delete mode 100644 packages/opencode/src/cli/tui/layer.ts delete mode 100644 packages/opencode/src/cli/tui/worker.ts delete mode 100644 packages/opencode/test/cli/tui/attach.test.ts delete mode 100644 packages/opencode/test/cli/tui/thread.test.ts diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 236838dbde..9f59cffaef 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -159,7 +159,6 @@ for (const item of targets) { const localPath = path.resolve(dir, "node_modules/@opentui/core/parser.worker.js") const rootPath = path.resolve(dir, "../../node_modules/@opentui/core/parser.worker.js") const parserWorker = fs.realpathSync(fs.existsSync(localPath) ? localPath : rootPath) - const workerPath = "./src/cli/tui/worker.ts" // Use platform-specific bunfs root path based on target OS const bunfsRoot = item.os === "win32" ? "B:/~BUN/root/" : "/$bunfs/root/" @@ -185,13 +184,12 @@ for (const item of targets) { windows: {}, }, files: embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {}, - entrypoints: ["./src/index.ts", parserWorker, workerPath, ...(embeddedFileMap ? ["opencode-web-ui.gen.ts"] : [])], + entrypoints: ["./src/index.ts", parserWorker, ...(embeddedFileMap ? ["opencode-web-ui.gen.ts"] : [])], define: { FFF_LIBC: JSON.stringify(item.abi === "musl" ? "musl" : "gnu"), OPENCODE_VERSION: `'${Script.version}'`, OPENCODE_MODELS_DEV: generated.modelsData, OTUI_TREE_SITTER_WORKER_PATH: bunfsRoot + workerRelativePath, - OPENCODE_WORKER_PATH: workerPath, OPENCODE_CHANNEL: `'${Script.channel}'`, OPENCODE_LIBC: item.os === "linux" ? `'${item.abi ?? "glibc"}'` : "", ...(item.os === "linux" ? { "process.env.OPENTUI_LIBC": JSON.stringify(item.abi ?? "glibc") } : {}), diff --git a/packages/opencode/src/cli/cmd/attach.ts b/packages/opencode/src/cli/cmd/attach.ts deleted file mode 100644 index 0d06bd7c41..0000000000 --- a/packages/opencode/src/cli/cmd/attach.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { cmd } from "./cmd" -import { UI } from "@/cli/ui" -import { errorMessage } from "@opencode-ai/tui/util/error" -import { validateSession } from "../tui/validate-session" -import { ServerAuth } from "@/server/auth" -import { OpenCode } from "@opencode-ai/client/promise" -import { createOpencodeClient } from "@opencode-ai/sdk/v2" - -export const AttachCommand = cmd({ - command: "attach ", - describe: "attach to a running opencode server", - builder: (yargs) => - yargs - .positional("url", { - type: "string", - describe: "http://localhost:4096", - demandOption: true, - }) - .option("dir", { - type: "string", - description: "directory to run in", - }) - .option("continue", { - alias: ["c"], - describe: "continue the last session", - type: "boolean", - }) - .option("session", { - alias: ["s"], - type: "string", - describe: "session id to continue", - }) - .option("fork", { - type: "boolean", - describe: "fork the session when continuing (use with --continue or --session)", - }) - .option("password", { - alias: ["p"], - type: "string", - describe: "basic auth password (defaults to OPENCODE_SERVER_PASSWORD)", - }) - .option("username", { - alias: ["u"], - type: "string", - describe: "basic auth username (defaults to OPENCODE_SERVER_USERNAME or 'opencode')", - }), - handler: async (args) => { - const directory = (() => { - if (!args.dir) return undefined - try { - process.chdir(args.dir) - return process.cwd() - } catch { - // If the directory doesn't exist locally (remote attach), pass it through. - return args.dir - } - })() - - const { TuiConfig } = await import("@/config/tui") - if (args.fork && !args.continue && !args.session) { - UI.error("--fork requires --continue or --session") - process.exitCode = 1 - return - } - - const headers = ServerAuth.headers({ password: args.password, username: args.username }) - const config = await TuiConfig.get() - - try { - await validateSession({ - url: args.url, - sessionID: args.session, - directory, - headers, - }) - } catch (error) { - UI.error(errorMessage(error)) - process.exitCode = 1 - return - } - - const { Effect } = await import("effect") - const { run } = await import("../tui/layer") - const { createLegacyTuiPluginHost } = await import("@/plugin/tui/runtime") - await Effect.runPromise( - run({ - // @ts-expect-error V1 does not consume the V2-only server input. - client: createOpencodeClient({ baseUrl: args.url, headers, directory }), - api: OpenCode.make({ baseUrl: args.url, headers }), - config, - pluginHost: createLegacyTuiPluginHost(), - args: { - continue: args.continue, - sessionID: args.session, - fork: args.fork, - }, - }), - ) - }, -}) diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts deleted file mode 100644 index 6f9dd25f51..0000000000 --- a/packages/opencode/src/cli/cmd/tui.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { cmd } from "@/cli/cmd/cmd" -import { Rpc } from "@/util/rpc" -import { type rpc } from "../tui/worker" -import path from "path" -import { fileURLToPath } from "url" -import { UI } from "@/cli/ui" -import { errorMessage } from "@opencode-ai/tui/util/error" -import { withTimeout } from "@/util/timeout" -import { withNetworkOptions, resolveNetworkOptionsNoConfig, hasArg } from "@/cli/network" -import { Filesystem } from "@/util/filesystem" -import { OpenCode } from "@opencode-ai/client/promise" -import { createOpencodeClient } from "@opencode-ai/sdk/v2" -import { writeHeapSnapshot } from "v8" -import { ServerAuth } from "@/server/auth" -import { validateSession } from "../tui/validate-session" -import { win32InstallCtrlCGuard } from "@opencode-ai/tui/terminal-win32" - -declare global { - const OPENCODE_WORKER_PATH: string -} - -async function target() { - if (typeof OPENCODE_WORKER_PATH !== "undefined") return OPENCODE_WORKER_PATH - const dist = new URL("./cli/tui/worker.js", import.meta.url) - if (await Filesystem.exists(fileURLToPath(dist))) return dist - return new URL("../tui/worker.ts", import.meta.url) -} - -async function input(value?: string) { - const piped = process.stdin.isTTY ? undefined : await Bun.stdin.text() - if (!value) return piped - if (!piped) return value - return piped + "\n" + value -} - -export function resolveThreadDirectory(project?: string, envPWD = process.env.PWD, cwd = process.cwd()) { - const root = Filesystem.resolve(envPWD ?? cwd) - if (project) return Filesystem.resolve(path.isAbsolute(project) ? project : path.join(root, project)) - return Filesystem.resolve(cwd) -} - -export const TuiThreadCommand = cmd({ - command: "$0 [project]", - describe: "start opencode tui", - builder: (yargs) => - withNetworkOptions(yargs) - .positional("project", { - type: "string", - describe: "path to start opencode in", - }) - .option("model", { - type: "string", - alias: ["m"], - describe: "model to use in the format of provider/model", - }) - .option("continue", { - alias: ["c"], - describe: "continue the last session", - type: "boolean", - }) - .option("session", { - alias: ["s"], - type: "string", - describe: "session id to continue", - }) - .option("fork", { - type: "boolean", - describe: "fork the session when continuing (use with --continue or --session)", - }) - .option("prompt", { - type: "string", - describe: "prompt to use", - }) - .option("agent", { - type: "string", - describe: "agent to use", - }) - .option("auto", { - type: "boolean", - describe: "auto-approve permissions that are not explicitly denied (dangerous!)", - default: false, - }) - .option("yolo", { - type: "boolean", - hidden: true, - default: false, - }) - .option("dangerously-skip-permissions", { - type: "boolean", - hidden: true, - default: false, - }), - handler: async (args) => { - const unguard = win32InstallCtrlCGuard() - try { - const { TuiConfig } = await import("@/config/tui") - if (args.fork && !args.continue && !args.session) { - UI.error("--fork requires --continue or --session") - process.exitCode = 1 - return - } - - // Resolve relative --project paths from PWD, then use the real cwd after - // chdir so the thread and worker share the same directory key. - const next = resolveThreadDirectory(args.project) - const file = await target() - try { - process.chdir(next) - } catch { - UI.error("Failed to change directory to " + next) - return - } - const cwd = Filesystem.resolve(process.cwd()) - - const worker = new Worker(file, { - env: Object.fromEntries( - Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] !== undefined), - ), - }) - const client = Rpc.client(worker) - const reload = () => { - client.call("reload", undefined).catch(() => {}) - } - process.on("SIGUSR2", reload) - - let stopped = false - const stop = async () => { - if (stopped) return - stopped = true - process.off("SIGUSR2", reload) - await withTimeout(client.call("shutdown", undefined), 5000).catch(() => {}) - worker.terminate() - } - - const prompt = await input(args.prompt) - const config = await TuiConfig.get() - - const network = resolveNetworkOptionsNoConfig(args) - const external = hasArg("--port") || hasArg("--hostname") || network.mdns === true - const headers = external ? ServerAuth.headers() : undefined - const url = (await client.call("server", network)).url - - try { - await validateSession({ - url, - sessionID: args.session, - directory: cwd, - headers, - }) - } catch (error) { - UI.error(errorMessage(error)) - process.exitCode = 1 - return - } - - setTimeout(() => { - client.call("checkUpgrade", { directory: cwd }).catch(() => {}) - }, 1000).unref?.() - - try { - const { Effect } = await import("effect") - const { run } = await import("../tui/layer") - const { createLegacyTuiPluginHost } = await import("@/plugin/tui/runtime") - await Effect.runPromise( - run({ - // @ts-expect-error V1 does not consume the V2-only server input. - client: createOpencodeClient({ baseUrl: url, headers, directory: cwd }), - api: OpenCode.make({ baseUrl: url, headers }), - async onSnapshot() { - const tui = writeHeapSnapshot("tui.heapsnapshot") - const server = await client.call("snapshot", undefined) - return [tui, server] - }, - config, - pluginHost: createLegacyTuiPluginHost(), - args: { - continue: args.continue, - sessionID: args.session, - agent: args.agent, - model: args.model, - prompt, - fork: args.fork, - auto: args.auto || args.yolo || args["dangerously-skip-permissions"], - }, - }), - ) - } finally { - await stop() - } - } finally { - try { - unguard?.() - } catch {} - } - process.exit(0) - }, -}) -// scratch diff --git a/packages/opencode/src/cli/tui/layer.ts b/packages/opencode/src/cli/tui/layer.ts deleted file mode 100644 index a592b86dae..0000000000 --- a/packages/opencode/src/cli/tui/layer.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { run as runTui, type TuiInput } from "@opencode-ai/tui" -import { Global } from "@opencode-ai/core/global" -import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" -import { Effect } from "effect" - -export function run(input: TuiInput) { - return runTui(input).pipe(Effect.provide(AppNodeBuilder.build(Global.node))) -} diff --git a/packages/opencode/src/cli/tui/worker.ts b/packages/opencode/src/cli/tui/worker.ts deleted file mode 100644 index c03b3b7076..0000000000 --- a/packages/opencode/src/cli/tui/worker.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Server } from "@/server/server" -import { InstanceRuntime } from "@/project/instance-runtime" -import { Rpc } from "@/util/rpc" -import { upgrade } from "@/cli/upgrade" -import { Config } from "@/config/config" -import { writeHeapSnapshot } from "node:v8" -import { Heap } from "@/cli/heap" -import { AppRuntime } from "@/effect/app-runtime" -import { Effect } from "effect" -import { disposeAllInstancesAndEmitGlobalDisposed } from "@/server/global-lifecycle" - -Heap.start() - -const onUnhandledRejection = (_error: unknown) => {} - -const onUncaughtException = (_error: Error) => {} - -process.on("unhandledRejection", onUnhandledRejection) -process.on("uncaughtException", onUncaughtException) - -let server: Awaited> | undefined - -export const rpc = { - snapshot() { - const result = writeHeapSnapshot("server.heapsnapshot") - return result - }, - async server(input: { port: number; hostname: string; mdns?: boolean; cors?: string[] }) { - if (server) await server.stop(true) - server = await Server.listen(input) - return { url: server.url.toString() } - }, - async checkUpgrade(input: { directory: string }) { - await InstanceRuntime.load({ directory: input.directory }) - await upgrade().catch(() => {}) - }, - async reload() { - await AppRuntime.runPromise( - Effect.gen(function* () { - const cfg = yield* Config.Service - yield* cfg.invalidate() - yield* disposeAllInstancesAndEmitGlobalDisposed({ swallowErrors: true }) - }), - ) - }, - async shutdown() { - await InstanceRuntime.disposeAllInstances() - if (server) await server.stop(true) - process.off("unhandledRejection", onUnhandledRejection) - process.off("uncaughtException", onUncaughtException) - }, -} - -Rpc.listen(rpc) diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index daa99d43c0..1a62f05c7a 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -18,9 +18,7 @@ import { McpCommand } from "./cli/cmd/mcp" import { GithubCommand } from "./cli/cmd/github" import { ExportCommand } from "./cli/cmd/export" import { ImportCommand } from "./cli/cmd/import" -import { AttachCommand } from "./cli/cmd/attach" import { V2ServeCommand } from "./cli/cmd/v2-serve" -import { TuiThreadCommand } from "./cli/cmd/tui" import { AcpCommand } from "./cli/cmd/acp" import { EOL } from "os" import { WebCommand } from "./cli/cmd/web" @@ -82,8 +80,6 @@ const cli = yargs(args) .command(AcpCommand) .command(McpCommand) .command(V2ServeCommand) - .command(TuiThreadCommand) - .command(AttachCommand) .command(RunCommand) .command(GenerateCommand) .command(DebugCommand) diff --git a/packages/opencode/src/plugin/tui/runtime.ts b/packages/opencode/src/plugin/tui/runtime.ts index 6b07166795..e39484dd19 100644 --- a/packages/opencode/src/plugin/tui/runtime.ts +++ b/packages/opencode/src/plugin/tui/runtime.ts @@ -42,7 +42,7 @@ import { ConfigPluginV1 } from "@opencode-ai/core/v1/config/plugin" import { createCommandShim } from "@opencode-ai/tui/plugin/command-shim" import { RuntimeFlags } from "@/effect/runtime-flags" import { Effect } from "effect" -import { createPluginRuntime, type PluginRuntime, type TuiPluginHost } from "@opencode-ai/tui/plugin/runtime" +import { createPluginRuntime, type PluginRuntime } from "@opencode-ai/tui/plugin/runtime" ensureRuntimePluginSupport({ additional: keymapRuntimeModules }) @@ -1121,11 +1121,4 @@ async function load(input: { } } -export function createLegacyTuiPluginHost(): TuiPluginHost { - return { - start: init, - dispose, - } -} - export * as TuiPluginRuntime from "./runtime" diff --git a/packages/opencode/src/temporary.ts b/packages/opencode/src/temporary.ts index 8ece4b89ef..ee9afb60b4 100644 --- a/packages/opencode/src/temporary.ts +++ b/packages/opencode/src/temporary.ts @@ -1,5 +1,4 @@ import yargs from "yargs" -import { TuiThreadCommand } from "./cli/cmd/tui" import { V2ServeCommand } from "./cli/cmd/v2-serve" import { InstallationVersion } from "@opencode-ai/core/installation/version" import { hideBin } from "yargs/helpers" @@ -29,5 +28,4 @@ const cli = yargs(hideBin(process.argv)) if (opts.logLevel) process.env.OPENCODE_LOG_LEVEL = opts.logLevel }) .command(V2ServeCommand) - .command(TuiThreadCommand) .parse() diff --git a/packages/opencode/test/cli/tui/attach.test.ts b/packages/opencode/test/cli/tui/attach.test.ts deleted file mode 100644 index 3535063d0e..0000000000 --- a/packages/opencode/test/cli/tui/attach.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, expect, test } from "bun:test" - -describe("tui attach", () => { - test("loads the TUI integration lazily", async () => { - const source = await Bun.file(new URL("../../../src/cli/cmd/attach.ts", import.meta.url)).text() - - expect(source).toContain('await import("../tui/layer")') - expect(source).toMatch(/await import\(["']@\/plugin\/tui\/runtime["']\)/) - expect(source).not.toContain('import("./app")') - }) -}) diff --git a/packages/opencode/test/cli/tui/thread.test.ts b/packages/opencode/test/cli/tui/thread.test.ts deleted file mode 100644 index 4c5d69d67f..0000000000 --- a/packages/opencode/test/cli/tui/thread.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { describe, expect, test } from "bun:test" -import { Effect } from "effect" -import fs from "fs/promises" -import path from "path" -import yargs from "yargs" -import { tmpdir } from "../../fixture/fixture" -import { TuiThreadCommand, resolveThreadDirectory } from "../../../src/cli/cmd/tui" -import { cliIt } from "../../lib/cli-process" - -describe("tui thread", () => { - test("loads the TUI integration lazily", async () => { - const source = await Bun.file(new URL("../../../src/cli/cmd/tui.ts", import.meta.url)).text() - - expect(source).toContain('await import("../tui/layer")') - expect(source).toMatch(/await import\(["']@\/plugin\/tui\/runtime["']\)/) - expect(source).not.toContain('import("./app")') - }) - - test("forwards the CLI environment to the TUI worker", async () => { - const source = await Bun.file(new URL("../../../src/cli/cmd/tui.ts", import.meta.url)).text() - - expect(source).toMatch(/new Worker\(file, \{\s*env: Object\.fromEntries\(\s*Object\.entries\(process\.env\)/) - }) - - async function check(project?: string) { - await using tmp = await tmpdir({ git: true }) - const link = path.join(path.dirname(tmp.path), path.basename(tmp.path) + "-link") - const type = process.platform === "win32" ? "junction" : "dir" - - try { - await fs.symlink(tmp.path, link, type) - expect(resolveThreadDirectory(project, link, tmp.path)).toBe(tmp.path) - } finally { - await fs.rm(link, { recursive: true, force: true }).catch(() => undefined) - } - } - - test("uses the real cwd when PWD points at a symlink", async () => { - await check() - }) - - test("uses the real cwd after resolving a relative project from PWD", async () => { - await check(".") - }) - - test("resolves a relative project from PWD when cwd differs", async () => { - await using pwd = await tmpdir({ git: true }) - await using cwd = await tmpdir({ git: true }) - - expect(resolveThreadDirectory(".", pwd.path, cwd.path)).toBe(pwd.path) - expect(resolveThreadDirectory(undefined, pwd.path, cwd.path)).toBe(cwd.path) - }) - - test("preserves boolean negation for existing options", async () => { - const args = await yargs([]) - .command({ ...TuiThreadCommand, handler: () => {} }) - .exitProcess(false) - .parse(["--mdns", "--no-mdns"]) - - expect(args.mdns).toBe(false) - }) - - cliIt.live("rejects removed top-level mini alias", ({ opencode }) => - Effect.gen(function* () { - const result = yield* opencode.spawn(["--mini"]) - - opencode.expectExit(result, 1) - expect(result.stderr).not.toContain("opencode mini requires a TTY stdout") - }), - ) - - cliIt.live("rejects removed run mini flag", ({ opencode }) => - Effect.gen(function* () { - const result = yield* opencode.spawn(["run", "--mini"]) - - opencode.expectExit(result, 1) - expect(result.stderr).not.toContain("opencode mini requires a TTY stdout") - }), - ) - - cliIt.live("rejects removed attach mini alias", ({ opencode }) => - Effect.gen(function* () { - const result = yield* opencode.spawn(["attach", "http://127.0.0.1:1", "--mini"]) - - opencode.expectExit(result, 1) - expect(result.stderr).not.toContain("opencode mini requires a TTY stdout") - }), - ) -}) diff --git a/packages/tui/src/app.tsx b/packages/tui/src/app.tsx index a1a286aaf4..7507c9208e 100644 --- a/packages/tui/src/app.tsx +++ b/packages/tui/src/app.tsx @@ -77,7 +77,6 @@ import { ArgsProvider, useArgs, type Args } from "./context/args" import open from "open" import { PromptRefProvider, usePromptRef } from "./context/prompt" import { Config, ConfigProvider, useConfig } from "./config" -import { TuiConfigV1 } from "./config/v1" import { createTuiApiAdapters } from "./plugin/adapters" import { createTuiApi } from "./plugin/api" import { createPluginRuntime, PluginRuntimeProvider, usePluginRuntime, type TuiPluginHost } from "./plugin/runtime" @@ -139,7 +138,6 @@ const appBindingCommands = [ "diff.open", "app.debug", "app.console", - "app.heap_snapshot", "terminal.suspend", "terminal.title.toggle", "app.toggle.animations", @@ -155,8 +153,7 @@ export type TuiInput = { reload?: () => Promise } args: Args - config: Config.Interface | TuiConfigV1.Resolved - onSnapshot?: () => Promise + config: Config.Interface pluginHost: TuiPluginHost terminalHandoff?: () => Promise< | { @@ -201,45 +198,12 @@ function isVersionGreater(left: string, right: string) { return a.prerelease.localeCompare(b.prerelease, undefined, { numeric: true }) > 0 } -function fromV1(config: TuiConfigV1.Resolved): Config.Info { - return { - theme: config.theme ? { name: config.theme } : undefined, - plugins: config.plugin?.map((plugin) => - typeof plugin === "string" ? plugin : { package: plugin[0], options: plugin[1] }, - ), - leader: { timeout: config.leader_timeout }, - scroll: - config.scroll_speed === undefined && config.scroll_acceleration === undefined - ? undefined - : { speed: config.scroll_speed, acceleration: config.scroll_acceleration?.enabled }, - attention: config.attention, - diffs: config.diff_style === undefined ? undefined : { view: config.diff_style === "stacked" ? "unified" : "auto" }, - mouse: config.mouse, - } -} - -function isConfigInterface(config: Config.Interface | TuiConfigV1.Resolved): config is Config.Interface { - return ( - "get" in config && typeof config.get === "function" && "update" in config && typeof config.update === "function" - ) -} - export const run = Effect.fn("Tui.run")(function* (input: TuiInput) { const log = input.log ?? (() => {}) const global = yield* Global.Service - const configInput = input.config - const loaded = yield* Effect.gen(function* () { - if (isConfigInterface(configInput)) { - return { - service: configInput, - info: yield* Effect.tryPromise(() => configInput.get()), - legacy: undefined, - } - } - return { service: undefined, info: fromV1(configInput), legacy: configInput } + const config = Config.resolve(yield* Effect.tryPromise(() => input.config.get()), { + terminalSuspend: process.platform !== "win32", }) - const config = Config.resolve(loaded.info, { terminalSuspend: process.platform !== "win32" }) - if (loaded.legacy) config.keybinds = loaded.legacy.keybinds const options = { baseUrl: input.server.endpoint.url, headers: Service.headers(input.server.endpoint) } const api = OpenCode.make(options) const directory = yield* Effect.tryPromise(() => api.file.list({ location: { directory: process.cwd() } })).pipe( @@ -376,7 +340,7 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) { @@ -412,9 +376,7 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) { Promise pluginHost: TuiPluginHost - pluginConfig: any pair?: DialogPairCredentials }) { const log = useLog({ component: "app" }) const startup = useTuiStartup() - const configContext = useConfig() - const config = configContext.data + const config = useConfig().data const route = useRoute() const dimensions = useTerminalDimensions() const renderer = useRenderer() @@ -555,7 +514,6 @@ function App(props: { props.pluginHost .start({ api, - config: props.pluginConfig, runtime: pluginRuntime, dispose: () => attention.dispose(), }) @@ -859,7 +817,6 @@ function App(props: { name: "opencode.settings", title: "Open settings", slashName: "settings", - enabled: configContext.writable, run: () => { dialog.replace(() => ) }, @@ -983,20 +940,6 @@ function App(props: { dialog.clear() }, }, - { - name: "app.heap_snapshot", - title: "Write heap snapshot", - category: "System", - run: async () => { - const files = await props.onSnapshot?.() - toast.show({ - variant: "info", - message: `Heap snapshot written to ${files?.join(", ")}`, - duration: 5000, - }) - dialog.clear() - }, - }, { name: "terminal.suspend", title: "Suspend terminal", diff --git a/packages/tui/src/config/index.tsx b/packages/tui/src/config/index.tsx index 94715d7212..8c6d9c0a85 100644 --- a/packages/tui/src/config/index.tsx +++ b/packages/tui/src/config/index.tsx @@ -179,7 +179,6 @@ export function resolve(input: Info, options: { terminalSuspend: boolean }): Res const ConfigContext = createContext<{ data: Resolved update: Interface["update"] - writable: boolean }>() export function ConfigProvider(props: { @@ -197,7 +196,7 @@ export function ConfigProvider(props: { return info } return ( - {props.children} + {props.children} ) } diff --git a/packages/tui/src/plugin/runtime.tsx b/packages/tui/src/plugin/runtime.tsx index edd9571515..4e8fa51f67 100644 --- a/packages/tui/src/plugin/runtime.tsx +++ b/packages/tui/src/plugin/runtime.tsx @@ -60,7 +60,6 @@ export type PluginRuntime = ReturnType export type TuiPluginHost = { start(input: { api: TuiPluginApi - config: any runtime: PluginRuntime dispose?: () => void }): Promise