72 lines
2.8 KiB
TypeScript
72 lines
2.8 KiB
TypeScript
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 { Commands } from "../commands"
|
|
import { Runtime } from "../../framework/runtime"
|
|
import { Config } from "../../config"
|
|
import { Effect, Option } from "effect"
|
|
import { Server } from "../../services/server"
|
|
import { Updater } from "../../services/updater"
|
|
import { UpdatePreflight } from "../../services/update-preflight"
|
|
|
|
export default Runtime.handler(Commands, (input) =>
|
|
Effect.gen(function* () {
|
|
const requestedDirectory = Option.getOrUndefined(input.directory)
|
|
if (requestedDirectory !== undefined) process.chdir(requestedDirectory)
|
|
const updater = yield* Updater.Service
|
|
yield* updater.check().pipe(Effect.forkScoped)
|
|
const preflight = UpdatePreflight.make()
|
|
yield* Effect.addFinalizer(() => Effect.promise(() => preflight.close()))
|
|
const server = yield* Server.resolve({
|
|
server: Option.getOrUndefined(input.server),
|
|
standalone: input.standalone,
|
|
onStart: (reason, existing) => {
|
|
if (reason === "version-mismatch" && preflight.begin(existing?.version)) return
|
|
process.stderr.write(
|
|
reason === "version-mismatch"
|
|
? "Restarting background server (version mismatch)...\n"
|
|
: "Starting background server...\n",
|
|
)
|
|
},
|
|
}).pipe(
|
|
Effect.tapError(() =>
|
|
Effect.promise(() => preflight.fail("OpenCode update could not start the new background service")),
|
|
),
|
|
)
|
|
preflight.loading()
|
|
const config = yield* Config.Service
|
|
let disposeSlots: (() => void) | undefined
|
|
const context = yield* Effect.context()
|
|
const runFork = Effect.runForkWith(context)
|
|
const runPromise = Effect.runPromiseWith(context)
|
|
yield* run({
|
|
server,
|
|
args: { continue: input.continue, sessionID: Option.getOrUndefined(input.session) },
|
|
config: {
|
|
get: () => runPromise(config.get()),
|
|
update: (update) => runPromise(config.update(update)),
|
|
},
|
|
terminalHandoff: () => preflight.finish(),
|
|
log: (level, message, tags) => {
|
|
const effect =
|
|
level === "debug"
|
|
? Effect.logDebug(message, tags)
|
|
: level === "warn"
|
|
? Effect.logWarning(message, tags)
|
|
: level === "error"
|
|
? Effect.logError(message, tags)
|
|
: Effect.logInfo(message, tags)
|
|
runFork(effect)
|
|
},
|
|
pluginHost: {
|
|
async start(pluginInput) {
|
|
disposeSlots = await loadBuiltinPlugins(pluginInput.api, pluginInput.runtime)
|
|
},
|
|
async dispose() {
|
|
disposeSlots?.()
|
|
},
|
|
},
|
|
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)))
|
|
}),
|
|
)
|