import { contextBridge, ipcRenderer } from "electron" export interface ElectronAPI { selectFolder: () => Promise createInstance: ( id: string, folder: string, binaryPath?: string, environmentVariables?: Record, ) => Promise<{ id: string; port: number; pid: number; binaryPath: string }> stopInstance: (pid: number) => Promise onInstanceStarted: (callback: (data: { id: string; port: number; pid: number; binaryPath: string }) => void) => void onInstanceError: (callback: (data: { id: string; error: string }) => void) => void onInstanceStopped: (callback: (data: { id: string }) => void) => void onInstanceLog: ( callback: (data: { id: string entry: { timestamp: number; level: "info" | "error" | "warn" | "debug"; message: string } }) => void, ) => void onNewInstance: (callback: () => void) => void scanDirectory: (workspaceFolder: string) => Promise // OpenCode binary operations selectOpenCodeBinary: () => Promise validateOpenCodeBinary: (path: string) => Promise<{ valid: boolean; version?: string; error?: string }> // Storage operations getConfigPath: () => Promise getInstancesDir: () => Promise readConfigFile: () => Promise writeConfigFile: (content: string) => Promise readInstanceFile: (instanceId: string) => Promise writeInstanceFile: (instanceId: string, content: string) => Promise deleteInstanceFile: (instanceId: string) => Promise onConfigChanged: (callback: () => void) => () => void } const electronAPI: ElectronAPI = { selectFolder: () => ipcRenderer.invoke("dialog:selectFolder"), createInstance: (id: string, folder: string, binaryPath?: string, environmentVariables?: Record) => ipcRenderer.invoke("instance:create", id, folder, binaryPath, environmentVariables), stopInstance: (pid: number) => ipcRenderer.invoke("instance:stop", pid), onInstanceStarted: (callback) => { ipcRenderer.on("instance:started", (_, data) => callback(data)) }, onInstanceError: (callback) => { ipcRenderer.on("instance:error", (_, data) => callback(data)) }, onInstanceStopped: (callback) => { ipcRenderer.on("instance:stopped", (_, data) => callback(data)) }, onInstanceLog: (callback) => { ipcRenderer.on("instance:log", (_, data) => callback(data)) }, onNewInstance: (callback) => { ipcRenderer.on("menu:newInstance", () => callback()) }, scanDirectory: (workspaceFolder: string) => ipcRenderer.invoke("fs:scanDirectory", workspaceFolder), // OpenCode binary operations selectOpenCodeBinary: () => ipcRenderer.invoke("dialog:selectOpenCodeBinary"), validateOpenCodeBinary: (path: string) => ipcRenderer.invoke("opencode:validateBinary", path), // Storage operations getConfigPath: () => ipcRenderer.invoke("storage:getConfigPath"), getInstancesDir: () => ipcRenderer.invoke("storage:getInstancesDir"), readConfigFile: () => ipcRenderer.invoke("storage:readConfigFile"), writeConfigFile: (content: string) => ipcRenderer.invoke("storage:writeConfigFile", content), readInstanceFile: (filename: string) => ipcRenderer.invoke("storage:readInstanceFile", filename), writeInstanceFile: (filename: string, content: string) => ipcRenderer.invoke("storage:writeInstanceFile", filename, content), deleteInstanceFile: (filename: string) => ipcRenderer.invoke("storage:deleteInstanceFile", filename), onConfigChanged: (callback: () => void) => { ipcRenderer.on("storage:configChanged", () => callback()) return () => ipcRenderer.removeAllListeners("storage:configChanged") }, } contextBridge.exposeInMainWorld("electronAPI", electronAPI) declare global { interface Window { electronAPI: ElectronAPI } }