forked from block/goose
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
App is loading, connecting to goose server.
- Loading branch information
1 parent
5a42c53
commit 3e9bd41
Showing
21 changed files
with
770 additions
and
176 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Svelte Electron UI Migration Plan | ||
|
||
## Overview | ||
|
||
This plan outlines the strategy for creating a Svelte-based UI for 'Goose AI', while maintaining the ability to pull updates from upstream. The goal is to create a parallel UI implementation that doesn't interfere with the original React-based implementation. | ||
|
||
## Key Principles | ||
|
||
1. **Zero Upstream Modifications**: No changes to upstream files to maintain ability to pull updates | ||
2. **Clean Architecture**: Keep frontend (Svelte) and backend (Goose) separate, unlike the React implementation | ||
3. **API-First**: Focus on proper API communication between UI and Goose instances | ||
|
||
## Progress & Learnings | ||
|
||
#### Phase 1: Setup & Infrastructure ✓ | ||
|
||
1. Initialize SvelteKit 2 project with Electron, TailwindCSS, TypeScript ✓ | ||
2. Setup 'types' organization. Documented in 'acumen/types_instructions.md'. ✓ | ||
3. Basic Electron integration with preload scripts ✓ | ||
4. Goosed binary integration and startup ✓ | ||
|
||
#### Phase 2: Core Architecture (In Progress) | ||
|
||
1. Asset handling and build configuration | ||
|
||
- Vite + SvelteKit static adapter setup ✓ | ||
- Asset path resolution in Electron main process ✓ | ||
- Proper build output directory structure ✓ | ||
|
||
2. IPC Communication | ||
- Preload script configuration ✓ | ||
- Window API exposure ✓ | ||
- Config passing between processes ✓ | ||
|
||
#### Next Steps | ||
|
||
1. **Asset Loading** | ||
|
||
- [ ] Fix asset loading in development mode | ||
- [ ] Ensure proper asset paths in production build | ||
- [ ] Test static file serving through Electron protocol | ||
|
||
2. **UI Implementation** | ||
|
||
- [ ] Port core UI components from React | ||
- [ ] Implement chat interface | ||
- [ ] Add theme support | ||
- [ ] Implement window controls | ||
|
||
3. **State Management** | ||
|
||
- [ ] Define state management strategy | ||
- [ ] Implement chat history | ||
- [ ] Handle configuration persistence | ||
|
||
4. **Testing & Packaging** | ||
- [ ] Add unit tests for core functionality | ||
- [ ] Set up E2E testing | ||
- [ ] Configure electron-forge for production builds | ||
|
||
## Technical Decisions | ||
|
||
1. **Build System** | ||
|
||
- Using Vite for both main and renderer processes | ||
- SvelteKit with static adapter for SPA mode | ||
- Electron-forge for application packaging | ||
|
||
2. **Development Mode** | ||
|
||
- Vite dev server for renderer | ||
- Watch mode for main/preload scripts | ||
- Hot module replacement enabled | ||
|
||
3. **Production Build** | ||
|
||
- Static HTML/JS/CSS output | ||
- CommonJS for main/preload | ||
- ESM for renderer | ||
- Assets served through custom Electron protocol | ||
|
||
4. **Type System** | ||
- Strict TypeScript configuration | ||
- Shared types between processes | ||
- No type duplication | ||
- Component-specific types with components |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import Electron, { contextBridge, ipcRenderer } from "electron"; | ||
|
||
const config = JSON.parse( | ||
process.argv.find((arg) => arg.startsWith("{")) || "{}" | ||
); | ||
|
||
// Define the API types in a single place | ||
type ElectronAPI = { | ||
getConfig: () => Record<string, any>; | ||
hideWindow: () => void; | ||
directoryChooser: (replace: string) => void; | ||
createChatWindow: (query?: string, dir?: string, version?: string) => void; | ||
logInfo: (txt: string) => void; | ||
showNotification: (data: any) => void; | ||
createWingToWingWindow: (query: string) => void; | ||
openInChrome: (url: string) => void; | ||
fetchMetadata: (url: string) => Promise<any>; | ||
reloadApp: () => void; | ||
checkForOllama: () => Promise<boolean>; | ||
selectFileOrDirectory: () => Promise<string>; | ||
startPowerSaveBlocker: () => Promise<number>; | ||
stopPowerSaveBlocker: () => Promise<void>; | ||
getBinaryPath: (binaryName: string) => Promise<string>; | ||
on: ( | ||
channel: string, | ||
callback: (event: Electron.IpcRendererEvent, ...args: any[]) => void | ||
) => void; | ||
off: ( | ||
channel: string, | ||
callback: (event: Electron.IpcRendererEvent, ...args: any[]) => void | ||
) => void; | ||
}; | ||
|
||
type AppConfigAPI = { | ||
get: (key: string) => any; | ||
getAll: () => Record<string, any>; | ||
}; | ||
|
||
const electronAPI: ElectronAPI = { | ||
getConfig: () => config, | ||
hideWindow: () => ipcRenderer.send("hide-window"), | ||
directoryChooser: (replace: string) => | ||
ipcRenderer.send("directory-chooser", replace), | ||
createChatWindow: (query?: string, dir?: string, version?: string) => | ||
ipcRenderer.send("create-chat-window", query, dir, version), | ||
logInfo: (txt: string) => ipcRenderer.send("logInfo", txt), | ||
showNotification: (data: any) => ipcRenderer.send("notify", data), | ||
createWingToWingWindow: (query: string) => | ||
ipcRenderer.send("create-wing-to-wing-window", query), | ||
openInChrome: (url: string) => ipcRenderer.send("open-in-chrome", url), | ||
fetchMetadata: (url: string) => ipcRenderer.invoke("fetch-metadata", url), | ||
reloadApp: () => ipcRenderer.send("reload-app"), | ||
checkForOllama: () => ipcRenderer.invoke("check-ollama"), | ||
selectFileOrDirectory: () => ipcRenderer.invoke("select-file-or-directory"), | ||
startPowerSaveBlocker: () => ipcRenderer.invoke("start-power-save-blocker"), | ||
stopPowerSaveBlocker: () => ipcRenderer.invoke("stop-power-save-blocker"), | ||
getBinaryPath: (binaryName: string) => | ||
ipcRenderer.invoke("get-binary-path", binaryName), | ||
on: ( | ||
channel: string, | ||
callback: (event: Electron.IpcRendererEvent, ...args: any[]) => void | ||
) => { | ||
ipcRenderer.on(channel, callback); | ||
}, | ||
off: ( | ||
channel: string, | ||
callback: (event: Electron.IpcRendererEvent, ...args: any[]) => void | ||
) => { | ||
ipcRenderer.off(channel, callback); | ||
}, | ||
}; | ||
|
||
const appConfigAPI: AppConfigAPI = { | ||
get: (key: string) => config[key], | ||
getAll: () => config, | ||
}; | ||
|
||
// Expose the APIs | ||
contextBridge.exposeInMainWorld("electron", electronAPI); | ||
contextBridge.exposeInMainWorld("appConfig", appConfigAPI); | ||
|
||
// Type declaration for TypeScript | ||
declare global { | ||
interface Window { | ||
electron: ElectronAPI; | ||
appConfig: AppConfigAPI; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// See the Electron documentation for details on how to use preload scripts: | ||
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts | ||
import { contextBridge, ipcRenderer } from "electron"; | ||
|
||
export type ExposeInRendererTypes = typeof exposeInRenderer; | ||
const exposeInRenderer = { | ||
toggleDevTools: () => ipcRenderer.send("toggleDevTools"), | ||
setTitleBarColors: (bgColor: string, iconColor: string) => { | ||
document.documentElement.style.background = bgColor; | ||
ipcRenderer.send("setTitleBarColors", bgColor, iconColor); | ||
}, | ||
}; | ||
|
||
for (const [key, value] of Object.entries(exposeInRenderer)) | ||
contextBridge.exposeInMainWorld(key, value); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import adapter from "@sveltejs/adapter-static"; | ||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; | ||
|
||
/** @type {import('@sveltejs/kit').Config} */ | ||
const config = { | ||
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess | ||
// for more information about preprocessors | ||
preprocess: vitePreprocess(), | ||
|
||
kit: { | ||
csp: { | ||
directives: { | ||
"script-src": ["self"], | ||
}, | ||
}, | ||
|
||
paths: { | ||
relative: false, | ||
}, | ||
|
||
files: { | ||
assets: "static", | ||
lib: "src-renderer/lib", | ||
params: "src-renderer/params", | ||
routes: "src-renderer/routes", | ||
serviceWorker: "src-renderer/service-worker", | ||
appTemplate: "src-renderer/app.html", | ||
errorTemplate: "src-renderer/error.html", | ||
}, | ||
|
||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. | ||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter. | ||
// See https://kit.svelte.dev/docs/adapters for more information about adapters. | ||
adapter: adapter({ | ||
// SPA (Single-page application) | ||
// https://kit.svelte.dev/docs/single-page-apps | ||
fallback: "200.html", | ||
|
||
pages: ".vite/main_window", | ||
assets: ".vite/main_window", | ||
}), | ||
}, | ||
}; | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { defineConfig } from "vite"; | ||
import { builtinModules } from "node:module"; | ||
|
||
export default defineConfig({ | ||
build: { | ||
outDir: ".vite/main", | ||
minify: "esbuild", | ||
lib: { | ||
entry: "./src-main/main.ts", | ||
fileName: () => "[name].js", | ||
formats: ["es"], | ||
}, | ||
|
||
rollupOptions: { | ||
external: [ | ||
"electron", | ||
...builtinModules.map((m) => [m, `node:${m}`]).flat(), | ||
], | ||
}, | ||
}, | ||
plugins: [], | ||
resolve: { | ||
// Load the Node.js entry. | ||
mainFields: ["module", "jsnext:main", "jsnext"], | ||
}, | ||
clearScreen: false, | ||
}); |
Oops, something went wrong.