Skip to content

Commit f08c149

Browse files
Apply PR #25962: feat(desktop): move server to utilityProcess
2 parents 9048b0f + d1cb190 commit f08c149

6 files changed

Lines changed: 415 additions & 93 deletions

File tree

packages/desktop/electron.vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default defineConfig({
3737
},
3838
build: {
3939
rollupOptions: {
40-
input: { index: "src/main/index.ts" },
40+
input: { index: "src/main/index.ts", sidecar: "src/main/sidecar.ts" },
4141
},
4242
externalizeDeps: { include: [nodePtyPkg] },
4343
},

packages/desktop/src/main/env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ interface ImportMetaEnv {
55
interface ImportMeta {
66
readonly env: ImportMetaEnv
77
}
8+
89
declare module "virtual:opencode-server" {
910
export namespace Server {
1011
export const listen: typeof import("../../../opencode/dist/types/src/node").Server.listen

packages/desktop/src/main/index.ts

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { getCACertificates, setDefaultCACertificates } from "node:tls"
88
import type { Event } from "electron"
99
import { app, BrowserWindow, dialog } from "electron"
1010
import pkg from "electron-updater"
11-
import { drizzle } from "drizzle-orm/node-sqlite/driver"
12-
import type { Server } from "virtual:opencode-server"
1311

1412
import contextMenu from "electron-context-menu"
1513
contextMenu({ showSaveImageAs: true, showLookUpSelection: false, showSearchWithGoogle: false })
@@ -48,7 +46,15 @@ import { registerIpcHandlers, sendDeepLinks, sendMenuCommand, sendSqliteMigratio
4846
import { initLogging } from "./logging"
4947
import { parseMarkdown } from "./markdown"
5048
import { createMenu } from "./menu"
51-
import { allocatePort, getDefaultServerUrl, setDefaultServerUrl, spawnLocalServer, spawnWslSidecar } from "./server"
49+
import {
50+
allocatePort,
51+
getDefaultServerUrl,
52+
preferAppEnv,
53+
setDefaultServerUrl,
54+
spawnLocalServer,
55+
spawnWslSidecar,
56+
type SidecarListener,
57+
} from "./server"
5258
import { createWslServersController } from "./wsl-servers"
5359
import {
5460
createLoadingWindow,
@@ -63,7 +69,7 @@ const initEmitter = new EventEmitter()
6369
let initStep: InitStep = { phase: "server_waiting" }
6470

6571
let mainWindow: BrowserWindow | null = null
66-
let server: Server.Listener | null = null
72+
let server: SidecarListener | null = null
6773
const loadingComplete = defer<void>()
6874

6975
const pendingDeepLinks: string[] = []
@@ -120,6 +126,8 @@ function setupApp() {
120126
return
121127
}
122128

129+
preferAppEnv(app.getPath("userData"))
130+
123131
app.on("second-instance", (_event: Event, argv: string[]) => {
124132
const urls = argv.filter((arg: string) => arg.startsWith("opencode://"))
125133
if (urls.length) {
@@ -136,20 +144,21 @@ function setupApp() {
136144
})
137145

138146
app.on("before-quit", () => {
139-
killSidecar()
147+
void killSidecar()
140148
wslServers.stopAll()
141149
})
142150

143151
app.on("will-quit", () => {
144-
killSidecar()
152+
void killSidecar()
145153
wslServers.stopAll()
146154
})
147155

148156
for (const signal of ["SIGINT", "SIGTERM"] as const) {
149157
process.on(signal, () => {
150-
killSidecar()
151-
wslServers.stopAll()
152-
app.exit(0)
158+
void killSidecar().finally(() => {
159+
wslServers.stopAll()
160+
app.exit(0)
161+
})
153162
})
154163
}
155164

@@ -215,23 +224,24 @@ async function initialize() {
215224
if (overlay) sendSqliteMigrationProgress(overlay, progress)
216225
if (mainWindow) sendSqliteMigrationProgress(mainWindow, progress)
217226
})
218-
219-
if (needsMigration) {
220-
const { Database, JsonMigration } = await import("virtual:opencode-server")
221-
await JsonMigration.run(drizzle({ client: Database.Client().$client }), {
222-
progress: (event: { current: number; total: number }) => {
223-
const percent = Math.round((event.current / event.total) * 100)
224-
initEmitter.emit("sqlite", { type: "InProgress", value: percent })
225-
},
226-
})
227-
initEmitter.emit("sqlite", { type: "Done" })
228-
}
229-
230227
logger.log("spawning sidecar", { url })
231-
const { listener, health } = await spawnLocalServer(hostname, port, password, () => {
232-
ensureLoopbackNoProxy()
233-
useEnvProxy()
234-
})
228+
const { listener, health } = await spawnLocalServer(
229+
hostname,
230+
port,
231+
password,
232+
() => {
233+
ensureLoopbackNoProxy()
234+
useEnvProxy()
235+
},
236+
{
237+
needsMigration,
238+
userDataPath: app.getPath("userData"),
239+
onSqliteProgress: (progress) => initEmitter.emit("sqlite", progress),
240+
onStdout: (message) => logger.log("sidecar stdout", { message }),
241+
onStderr: (message) => logger.warn("sidecar stderr", { message }),
242+
onExit: (code) => logger.warn("sidecar exited", { code }),
243+
},
244+
)
235245
server = listener
236246
serverReady.resolve({
237247
url,
@@ -333,19 +343,21 @@ registerIpcHandlers({
333343
setBackgroundColor: (color) => setBackgroundColor(color),
334344
})
335345

336-
function killSidecar() {
346+
async function killSidecar() {
337347
if (!server) return
338-
server.stop()
348+
const current = server
339349
server = null
350+
await current.stop()
340351
}
341352

342353
function relaunchApp() {
343354
// app.exit() skips before-quit / will-quit, so relaunch callers must
344355
// explicitly stop sidecars here rather than relying on process hooks.
345-
killSidecar()
346-
wslServers.stopAll()
347-
app.relaunch()
348-
app.exit(0)
356+
void killSidecar().finally(() => {
357+
wslServers.stopAll()
358+
app.relaunch()
359+
app.exit(0)
360+
})
349361
}
350362

351363
function ensureLoopbackNoProxy() {
@@ -445,7 +457,7 @@ async function installUpdate() {
445457
logger.log("installing downloaded update", {
446458
version: downloadedUpdateVersion,
447459
})
448-
killSidecar()
460+
await killSidecar()
449461
wslServers.stopAll()
450462
autoUpdater.quitAndInstall()
451463
}

packages/desktop/src/main/ipc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const pickerFilters = (ext?: string[]) => {
2121
}
2222

2323
type Deps = {
24-
killSidecar: () => void
24+
killSidecar: () => Promise<void> | void
2525
relaunch: () => void
2626
awaitInitialization: (sendStep: (step: InitStep) => void) => Promise<ServerReadyData>
2727
getWslServersState: () => Promise<WslServersState> | WslServersState

0 commit comments

Comments
 (0)