Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/cli/src/commands/handlers/default.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { LayerNode } from "@opencode/util/effect/layer-node"
import { Global } from "@opencode/util/global"
import { run } from "@opencode/tui"
import { Commands } from "../commands"
import { Runtime } from "../../framework/runtime"
import { Config } from "../../config"
Expand All @@ -14,6 +13,7 @@ import { Env } from "../../env"

export default Runtime.handler(Commands, (input) =>
Effect.gen(function* () {
const tui = import("@opencode/tui")
const requestedDirectory = Option.getOrUndefined(input.directory)
const requestedServer = Option.getOrUndefined(input.server)
if (requestedDirectory !== undefined) process.chdir(requestedDirectory)
Expand Down Expand Up @@ -57,6 +57,7 @@ export default Runtime.handler(Commands, (input) =>
const runFork = Effect.runForkWith(context)
const runPromise = Effect.runPromiseWith(context)
const service = server.service
const { run } = yield* Effect.promise(() => tui)
yield* run({
app: {
name: process.env.OPENCODE_CLIENT ?? OPENCODE_ARTIFACT,
Expand Down
41 changes: 24 additions & 17 deletions packages/tui/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render, useRenderer, useTerminalDimensions } from "@opentui/solid"
import { registerOpencodeSpinner } from "./component/register-spinner"
import { Effect, Latch } from "effect"
import { Effect, Fiber, Latch } from "effect"
import { Service, type Endpoint } from "@opencode/client/effect/service"
import { OpenCode, type SessionInfo } from "@opencode/client"
import { Global } from "@opencode/util/global"
Expand Down Expand Up @@ -203,17 +203,19 @@ export type TuiInput = {
export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
const log = input.log ?? (() => {})
const global = yield* Global.Service
const config = Config.resolve(yield* Effect.tryPromise(() => input.config.get()), {
terminalSuspend: process.platform !== "win32",
})
const options = { baseUrl: input.server.endpoint.url, headers: Service.headers(input.server.endpoint) }
const api = OpenCode.make(options)
const location = yield* Effect.tryPromise(() => api.file.list({ location: { directory: process.cwd() } })).pipe(
const locationFiber = yield* Effect.tryPromise(() => api.file.list({ location: { directory: process.cwd() } })).pipe(
Effect.map((response) => response.location),
Effect.catch(() => Effect.tryPromise(() => api.location.get())),
Effect.forkChild({ startImmediately: true }),
)
const directory = location.directory
const pluginDirectories = yield* Effect.promise(() => localPluginDirectories(process.cwd(), global.config))
const pluginDirectoriesFiber = yield* Effect.promise(() =>
localPluginDirectories(process.cwd(), global.config),
).pipe(Effect.forkChild({ startImmediately: true }))
const config = Config.resolve(yield* Effect.tryPromise(() => input.config.get()), {
terminalSuspend: process.platform !== "win32",
})
const handoff = input.terminalHandoff ? yield* Effect.promise(input.terminalHandoff) : undefined
const managed = input.server.service
const service = managed
Expand Down Expand Up @@ -284,11 +286,16 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
() => Effect.sync(() => process.off("SIGHUP", onSighup)),
)
renderer.once("destroy", () => shutdown.openUnsafe())
yield* Effect.tryPromise(async () => {
const mode = handoff?.mode ?? (await renderer.waitForThemeMode(1000)) ?? "dark"
if (renderer.isDestroyed) return
const mode = handoff?.mode ?? (yield* Effect.tryPromise(() => renderer.waitForThemeMode(1000))) ?? "dark"
const [location, pluginDirectories] = yield* Effect.all([
Fiber.join(locationFiber),
Fiber.join(pluginDirectoriesFiber),
])
const directory = location.directory
if (renderer.isDestroyed) return { epilogue: exit.epilogue, reason: exit.reason }

await render(() => {
yield* Effect.tryPromise(() =>
render(() => {
return (
<LogProvider log={log}>
<ExitProvider
Expand Down Expand Up @@ -446,12 +453,12 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
</ExitProvider>
</LogProvider>
)
}, renderer)
if (handoff) {
renderer.once(CliRenderEvents.FRAME, handoff.complete)
renderer.requestRender()
}
})
}, renderer),
)
if (handoff) {
renderer.once(CliRenderEvents.FRAME, handoff.complete)
renderer.requestRender()
}
yield* shutdown.await
return { epilogue: exit.epilogue, reason: exit.reason }
}),
Expand Down
Loading