| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- import { app } from "electron"
- import { DEFAULT_SERVER_URL_KEY, WSL_ENABLED_KEY } from "./constants"
- import { getUserShell, loadShellEnv } from "./shell-env"
- import { getStore } from "./store"
- export type WslConfig = { enabled: boolean }
- export type HealthCheck = { wait: Promise<void> }
- export function getDefaultServerUrl(): string | null {
- const value = getStore().get(DEFAULT_SERVER_URL_KEY)
- return typeof value === "string" ? value : null
- }
- export function setDefaultServerUrl(url: string | null) {
- if (url) {
- getStore().set(DEFAULT_SERVER_URL_KEY, url)
- return
- }
- getStore().delete(DEFAULT_SERVER_URL_KEY)
- }
- export function getWslConfig(): WslConfig {
- const value = getStore().get(WSL_ENABLED_KEY)
- return { enabled: typeof value === "boolean" ? value : false }
- }
- export function setWslConfig(config: WslConfig) {
- getStore().set(WSL_ENABLED_KEY, config.enabled)
- }
- export async function spawnLocalServer(hostname: string, port: number, password: string) {
- prepareServerEnv(password)
- const { Log, Server } = await import("virtual:opencode-server")
- await Log.init({ level: "WARN" })
- const listener = await Server.listen({
- port,
- hostname,
- username: "opencode",
- password,
- cors: ["oc://renderer"],
- })
- const wait = (async () => {
- const url = `http://${hostname}:${port}`
- const ready = async () => {
- while (true) {
- await new Promise((resolve) => setTimeout(resolve, 100))
- if (await checkHealth(url, password)) return
- }
- }
- await ready()
- })()
- return { listener, health: { wait } }
- }
- function prepareServerEnv(password: string) {
- const shell = process.platform === "win32" ? null : getUserShell()
- const shellEnv = shell ? (loadShellEnv(shell) ?? {}) : {}
- const env = {
- ...process.env,
- ...shellEnv,
- OPENCODE_EXPERIMENTAL_ICON_DISCOVERY: "true",
- OPENCODE_EXPERIMENTAL_FILEWATCHER: "true",
- OPENCODE_CLIENT: "desktop",
- OPENCODE_SERVER_USERNAME: "opencode",
- OPENCODE_SERVER_PASSWORD: password,
- XDG_STATE_HOME: app.getPath("userData"),
- }
- Object.assign(process.env, env)
- }
- export async function checkHealth(url: string, password?: string | null): Promise<boolean> {
- let healthUrl: URL
- try {
- healthUrl = new URL("/global/health", url)
- } catch {
- return false
- }
- const headers = new Headers()
- if (password) {
- const auth = Buffer.from(`opencode:${password}`).toString("base64")
- headers.set("authorization", `Basic ${auth}`)
- }
- try {
- const res = await fetch(healthUrl, {
- method: "GET",
- headers,
- signal: AbortSignal.timeout(3000),
- })
- return res.ok
- } catch {
- return false
- }
- }
|