Merge branch 'dev' into opencode-remote-voice
This commit is contained in:
commit
ce209e22a2
156 changed files with 7458 additions and 2876 deletions
|
|
@ -28,8 +28,10 @@ const APP_IDS: Record<string, string> = {
|
|||
beta: "ai.opencode.desktop.beta",
|
||||
prod: "ai.opencode.desktop",
|
||||
}
|
||||
const appId = app.isPackaged ? APP_IDS[CHANNEL] : "ai.opencode.desktop.dev"
|
||||
app.setName(app.isPackaged ? APP_NAMES[CHANNEL] : "OpenCode Dev")
|
||||
app.setPath("userData", join(app.getPath("appData"), app.isPackaged ? APP_IDS[CHANNEL] : "ai.opencode.desktop.dev"))
|
||||
app.setAppUserModelId(appId)
|
||||
app.setPath("userData", join(app.getPath("appData"), appId))
|
||||
const { autoUpdater } = pkg
|
||||
|
||||
import type { InitStep, ServerReadyData, SqliteMigrationProgress, WslConfig } from "../preload/types"
|
||||
|
|
@ -41,6 +43,7 @@ import { parseMarkdown } from "./markdown"
|
|||
import { createMenu } from "./menu"
|
||||
import { getDefaultServerUrl, getWslConfig, setDefaultServerUrl, setWslConfig, spawnLocalServer } from "./server"
|
||||
import { createLoadingWindow, createMainWindow, setBackgroundColor, setDockIcon } from "./windows"
|
||||
import { drizzle } from "drizzle-orm/node-sqlite/driver"
|
||||
import type { Server } from "virtual:opencode-server"
|
||||
|
||||
const initEmitter = new EventEmitter()
|
||||
|
|
@ -137,15 +140,6 @@ async function initialize() {
|
|||
const url = `http://${hostname}:${port}`
|
||||
const password = randomUUID()
|
||||
|
||||
logger.log("spawning sidecar", { url })
|
||||
const { listener, health } = await spawnLocalServer(hostname, port, password)
|
||||
server = listener
|
||||
serverReady.resolve({
|
||||
url,
|
||||
username: "opencode",
|
||||
password,
|
||||
})
|
||||
|
||||
const loadingTask = (async () => {
|
||||
logger.log("sidecar connection started", { url })
|
||||
|
||||
|
|
@ -156,10 +150,32 @@ async function initialize() {
|
|||
if (progress.type === "Done") sqliteDone?.resolve()
|
||||
})
|
||||
|
||||
if (needsMigration) {
|
||||
const { Database, JsonMigration } = await import("virtual:opencode-server")
|
||||
await JsonMigration.run(drizzle({ client: Database.Client().$client }), {
|
||||
progress: (event: { current: number; total: number }) => {
|
||||
const percent = Math.round(event.current / event.total) * 100
|
||||
initEmitter.emit("sqlite", { type: "InProgress", value: percent })
|
||||
},
|
||||
})
|
||||
initEmitter.emit("sqlite", { type: "Done" })
|
||||
|
||||
sqliteDone?.resolve()
|
||||
}
|
||||
|
||||
if (needsMigration) {
|
||||
await sqliteDone?.promise
|
||||
}
|
||||
|
||||
logger.log("spawning sidecar", { url })
|
||||
const { listener, health } = await spawnLocalServer(hostname, port, password)
|
||||
server = listener
|
||||
serverReady.resolve({
|
||||
url,
|
||||
username: "opencode",
|
||||
password,
|
||||
})
|
||||
|
||||
await Promise.race([
|
||||
health.wait,
|
||||
delay(30_000).then(() => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs"
|
|||
import { homedir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
import { CHANNEL } from "./constants"
|
||||
import { getStore, store } from "./store"
|
||||
import { getStore } from "./store"
|
||||
|
||||
const TAURI_MIGRATED_KEY = "tauriMigrated"
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ function migrateFile(datPath: string, filename: string) {
|
|||
}
|
||||
|
||||
export function migrate() {
|
||||
if (store.get(TAURI_MIGRATED_KEY)) {
|
||||
if (getStore().get(TAURI_MIGRATED_KEY)) {
|
||||
log.log("tauri migration: already done, skipping")
|
||||
return
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ export function migrate() {
|
|||
|
||||
if (!existsSync(dir)) {
|
||||
log.log("tauri migration: no tauri data directory found, nothing to migrate")
|
||||
store.set(TAURI_MIGRATED_KEY, true)
|
||||
getStore().set(TAURI_MIGRATED_KEY, true)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -87,5 +87,5 @@ export function migrate() {
|
|||
}
|
||||
|
||||
log.log("tauri migration: complete")
|
||||
store.set(TAURI_MIGRATED_KEY, true)
|
||||
getStore().set(TAURI_MIGRATED_KEY, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ import { randomBytes } from "node:crypto"
|
|||
import { app } from "electron"
|
||||
import { DEFAULT_SERVER_URL_KEY, WSL_ENABLED_KEY } from "./constants"
|
||||
import { getUserShell, loadShellEnv } from "./shell-env"
|
||||
import { store } from "./store"
|
||||
import { getStore } from "./store"
|
||||
|
||||
const DEFAULT_RELAY_URL = "https://apn.dev.opencode.ai"
|
||||
const RELAY_SECRET_KEY = "relaySecret"
|
||||
|
||||
function getOrCreateRelaySecret(): string {
|
||||
const existing = store.get(RELAY_SECRET_KEY)
|
||||
const existing = getStore().get(RELAY_SECRET_KEY)
|
||||
if (typeof existing === "string" && existing.length > 0) return existing
|
||||
const secret = randomBytes(18).toString("base64url")
|
||||
store.set(RELAY_SECRET_KEY, secret)
|
||||
getStore().set(RELAY_SECRET_KEY, secret)
|
||||
return secret
|
||||
}
|
||||
|
||||
|
|
@ -20,26 +20,26 @@ export type WslConfig = { enabled: boolean }
|
|||
export type HealthCheck = { wait: Promise<void> }
|
||||
|
||||
export function getDefaultServerUrl(): string | null {
|
||||
const value = store.get(DEFAULT_SERVER_URL_KEY)
|
||||
const value = getStore().get(DEFAULT_SERVER_URL_KEY)
|
||||
return typeof value === "string" ? value : null
|
||||
}
|
||||
|
||||
export function setDefaultServerUrl(url: string | null) {
|
||||
if (url) {
|
||||
store.set(DEFAULT_SERVER_URL_KEY, url)
|
||||
getStore().set(DEFAULT_SERVER_URL_KEY, url)
|
||||
return
|
||||
}
|
||||
|
||||
store.delete(DEFAULT_SERVER_URL_KEY)
|
||||
getStore().delete(DEFAULT_SERVER_URL_KEY)
|
||||
}
|
||||
|
||||
export function getWslConfig(): WslConfig {
|
||||
const value = store.get(WSL_ENABLED_KEY)
|
||||
const value = getStore().get(WSL_ENABLED_KEY)
|
||||
return { enabled: typeof value === "boolean" ? value : false }
|
||||
}
|
||||
|
||||
export function setWslConfig(config: WslConfig) {
|
||||
store.set(WSL_ENABLED_KEY, config.enabled)
|
||||
getStore().set(WSL_ENABLED_KEY, config.enabled)
|
||||
}
|
||||
|
||||
export async function spawnLocalServer(hostname: string, port: number, password: string) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import { SETTINGS_STORE } from "./constants"
|
|||
|
||||
const cache = new Map<string, Store>()
|
||||
|
||||
// We cannot instantiate the electron-store at module load time because
|
||||
// module import hoisting causes this to run before app.setPath("userData", ...)
|
||||
// in index.ts has executed, which would result in files being written to the default directory
|
||||
// (e.g. bad: %APPDATA%\@opencode-ai\desktop-electron\opencode.settings vs good: %APPDATA%\ai.opencode.desktop.dev\opencode.settings).
|
||||
export function getStore(name = SETTINGS_STORE) {
|
||||
const cached = cache.get(name)
|
||||
if (cached) return cached
|
||||
|
|
@ -11,5 +15,3 @@ export function getStore(name = SETTINGS_STORE) {
|
|||
cache.set(name, next)
|
||||
return next
|
||||
}
|
||||
|
||||
export const store = getStore(SETTINGS_STORE)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue