From cfdcdddb8025608a994ad69fb9ca46040c77d56e Mon Sep 17 00:00:00 2001 From: alichherawalla Date: Thu, 10 Sep 2026 20:47:38 -0700 Subject: [PATCH 001/204] interim --- package-lock.json | 8 ++++ package.json | 1 + src/main/index.ts | 3 ++ src/preload/index.ts | 46 +++++++++++++++++++ src/renderer/src/App.tsx | 8 ++++ src/renderer/src/assets/main.css | 8 ++++ .../src/components/MemoryChat/index.tsx | 31 +++++++++++++ .../src/components/MemoryChat/interfaces.tsx | 2 + src/renderer/src/components/Settings.tsx | 10 ++++ src/renderer/src/env.d.ts | 28 +++++++++++ src/renderer/src/main.tsx | 6 ++- src/shared/renderer-csp.ts | 2 +- 12 files changed, 151 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index a69220dbf..8f8f27393 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,6 +63,7 @@ "remark-parse": "^11.0.0", "sharp": "^0.35.2", "tailwind-merge": "^3.4.0", + "three": "^0.186.0", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", "unified": "^11.0.5", @@ -166,6 +167,7 @@ "dependencies": { "@noble/hashes": "1.8.0", "@offgrid/automation": "*", + "@offgrid/models": "*", "bonjour-service": "^1.2.1", "js-sha512": "^0.9.0", "tweetnacl": "^1.0.3", @@ -19864,6 +19866,12 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/three": { + "version": "0.186.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.186.0.tgz", + "integrity": "sha512-cr/fIM2ddMSVbYVgkfD4jLJv7Fh/8ZTjvo+7gQeSVGUZHxpx9FDwoL5iC7hUz/LiRA8wMbqfnb90xKfm1/HHkQ==", + "license": "MIT" + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", diff --git a/package.json b/package.json index 189809ad9..7ada98bba 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "remark-parse": "^11.0.0", "sharp": "^0.35.2", "tailwind-merge": "^3.4.0", + "three": "^0.186.0", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", "unified": "^11.0.5", diff --git a/src/main/index.ts b/src/main/index.ts index ef38bb9ba..17c9c2acf 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -25,6 +25,7 @@ import { setupDesktopBackupIPC } from './backup/ipc' import { preloadPath } from './preload-path' import { rendererHtmlPath } from './renderer-path' import { setMainWindow } from './main-window' +import { registerGodTwinWindowIpc, showGodTwinWindow } from './god-twin-window' import { startModelServer, stopModelServer } from './model-server' import { startMediaServer, stopMediaServer, mediaUrlFor } from './media-server' import { capturePathFromUrl, serveCaptureFile } from './ogcapture-serve' @@ -464,7 +465,9 @@ app.whenReady().then(async () => { } ]) + registerGodTwinWindowIpc() createWindow() + if (windowPresentation.showWindow) showGodTwinWindow() // Network checks, model work, and optional services now run beside the visible shell. void runIndependentStartupStages([ diff --git a/src/preload/index.ts b/src/preload/index.ts index de00682f7..757d02613 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -185,6 +185,52 @@ const offGridApi = { return unsubscribe(channel, sub) }, proOff: (channel: string) => ipcRenderer.removeAllListeners(channel), + godTwin: { + wake: (): Promise => ipcRenderer.invoke('god-twin:wake'), + getEnabled: (): Promise => ipcRenderer.invoke('god-twin:enabled:get'), + setEnabled: (enabled: boolean): Promise => + ipcRenderer.invoke('god-twin:enabled:set', enabled), + getPreferences: (): Promise<{ + state: 'idle' | 'walking' | 'running' | 'fighting' | 'resting' + spinning: boolean + }> => ipcRenderer.invoke('god-twin:preferences:get'), + setPreferences: (preferences: { + state?: 'idle' | 'walking' | 'running' | 'fighting' | 'resting' + spinning?: boolean + }): Promise<{ + state: 'idle' | 'walking' | 'running' | 'fighting' | 'resting' + spinning: boolean + }> => ipcRenderer.invoke('god-twin:preferences:set', preferences), + setListening: (listening: boolean): void => + ipcRenderer.send('god-twin:listening', listening), + setState: (state: 'idle' | 'walking' | 'running' | 'fighting' | 'resting'): void => + ipcRenderer.send('god-twin:state', state), + resize: ( + edge: 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw', + deltaX: number, + deltaY: number + ): void => ipcRenderer.send('god-twin:resize', { edge, deltaX, deltaY }), + onWake: (callback: () => void): (() => void) => { + const listener = (): void => callback() + ipcRenderer.on('god-twin:wake', listener) + return unsubscribe('god-twin:wake', listener) + }, + onListening: (callback: (listening: boolean) => void): (() => void) => { + const listener = (_event: unknown, listening: boolean): void => callback(listening) + ipcRenderer.on('god-twin:listening', listener) + return unsubscribe('god-twin:listening', listener) + }, + onState: ( + callback: (state: 'idle' | 'walking' | 'running' | 'fighting' | 'resting') => void + ): (() => void) => { + const listener = ( + _event: unknown, + state: 'idle' | 'walking' | 'running' | 'fighting' | 'resting' + ): void => callback(state) + ipcRenderer.on('god-twin:state', listener) + return unsubscribe('god-twin:state', listener) + } + }, // Loopback HTTP URL for seekable local media (meeting recordings) —