Open-Generative-AI/electron/preload.js
Anil Matcha 032ab0c693 feat(local-ai): add Wan2GP HTTP provider as a second local engine
The desktop app already has a bundled sd.cpp engine for local generation. This
adds a second, complementary engine: an HTTP client that talks to a user-run
Wan2GP Gradio server (https://github.com/deepbeepmeep/Wan2GP). Useful when
sd.cpp can't run a target model — Wan2GP brings video models (Wan 2.2,
Hunyuan, LTX) and large image models (Flux, Qwen-Image) without bundling
Python or weights into the app.

Architecture
- Each model in the unified catalog now carries a `provider` field
  (`'sdcpp' | 'wan2gp'`). The renderer's `localAI.generate()` routes to the
  right backend based on that flag.
- sd.cpp keeps its existing IPC channels (`local-ai:*`) untouched. Wan2GP
  gets its own channel namespace (`wan2gp:*`) and lives in its own
  `electron/lib/wan2gpProvider.js`.
- Wan2GP server URL is persisted in `userData/local-ai/wan2gp.json`.
  `Settings → Local Models` exposes a config bar to test/save the URL.
- Generation streams Gradio v4 SSE protocol; both engines emit progress on
  the shared `local-ai:progress` channel.

ImageStudio
- Local-model dropdown now filters out video models (`type === 'video'`)
  since the studio is image-only. SD 1.5 / SDXL / Z-Image (sd.cpp) and Flux /
  Qwen-Image (Wan2GP) still surface; Wan/Hunyuan/LTX are hidden until the
  Video Studio is wired up to the same surface.
- Progress event handler updated to tolerate both engines' shapes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 02:13:58 +05:30

40 lines
2.1 KiB
JavaScript

const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('localAI', {
isElectron: true,
// ── sd.cpp engine ──────────────────────────────────────────────────────
getBinaryStatus: () => ipcRenderer.invoke('local-ai:binary-status'),
downloadBinary: () => ipcRenderer.invoke('local-ai:download-binary'),
listModels: () => ipcRenderer.invoke('local-ai:list-models'),
downloadModel: (modelId) => ipcRenderer.invoke('local-ai:download-model', modelId),
downloadAuxiliary: (auxKey) => ipcRenderer.invoke('local-ai:download-auxiliary', auxKey),
deleteModel: (modelId) => ipcRenderer.invoke('local-ai:delete-model', modelId),
cancelDownload: (modelId) => ipcRenderer.invoke('local-ai:cancel-download', modelId),
generate: (params) => ipcRenderer.invoke('local-ai:generate', params),
cancelGeneration: () => ipcRenderer.invoke('local-ai:cancel-generation'),
// ── Wan2GP engine (remote Gradio server) ───────────────────────────────
wan2gp: {
getConfig: () => ipcRenderer.invoke('wan2gp:get-config'),
setUrl: (url) => ipcRenderer.invoke('wan2gp:set-url', url),
probe: (url) => ipcRenderer.invoke('wan2gp:probe', url),
listModels: () => ipcRenderer.invoke('wan2gp:list-models'),
generate: (params) => ipcRenderer.invoke('wan2gp:generate', params),
cancelGeneration: () => ipcRenderer.invoke('wan2gp:cancel-generation'),
},
// Progress events — both engines emit on local-ai:progress
onProgress: (callback) => {
const listener = (_, data) => callback(data);
ipcRenderer.on('local-ai:progress', listener);
return () => ipcRenderer.removeListener('local-ai:progress', listener);
},
onDownloadProgress: (callback) => {
const listener = (_, data) => callback(data);
ipcRenderer.on('local-ai:download-progress', listener);
return () => ipcRenderer.removeListener('local-ai:download-progress', listener);
},
});