Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terminal commands #237

Merged
merged 15 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,28 @@ You can also build the package and/or distributables using the `make` command:
yarn make
```

If you get an error similar to:

```
The module '/electron/node_modules/node-pty/build/Release/pty.node' was compiled against a different Node.js version using NODE_MODULE_VERSION 115. This version of Node.js requires NODE_MODULE_VERSION 125. Please try re-compiling or re-installing the module (for instance, using `npm rebuild` or `npm install`).
```

You will need to rebuild the node-pty using [electron-rebuild](https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules), for example:

```
npx electron-rebuild
```

or if that fails

```
yarn install -D @electron/rebuild
rm -rf node_modules
rm yarn.lock
yarn install
electron-rebuild
```

### Debugger

There are helpful debug launch scripts for VSCode / Cursor under `.vscode/launch.json`. It will start the dev server as defined in `.vscode/tasks.json`. Then attach the debugger.
Expand Down
1 change: 1 addition & 0 deletions builder-debug.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const debugConfig: Configuration = {
icon: './assets/UI/Comfy_Logo_x256.png',
target: 'appimage',
},
asarUnpack: ['**/node_modules/node-pty/**/*'],
};

export default debugConfig;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"main": ".vite/build/main.js",
"packageManager": "[email protected]",
"config": {
"frontendVersion": "1.4.0",
"frontendVersion": "1.4.2",
"comfyVersion": "0.2.7",
"managerCommit": "e629215c100c89a9a9d33fc03be3248069ff67ef",
"uvVersion": "0.5.1"
Expand Down Expand Up @@ -55,6 +55,7 @@
"devDependencies": {
"@electron/fuses": "^1.8.0",
"@electron/notarize": "^2.4.0",
"@electron/rebuild": "^3.7.1",
"@electron/windows-sign": "^1.1.3",
"@playwright/test": "^1.47.2",
"@sentry/wizard": "^3.30.0",
Expand Down Expand Up @@ -97,6 +98,7 @@
"electron-log": "^5.2.0",
"electron-store": "8.2.0",
"jest": "^29.7.0",
"node-pty": "^1.0.0",
"systeminformation": "^5.23.5",
"tar": "^7.4.3",
"wait-on": "^8.0.1",
Expand Down
4 changes: 4 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export const IPC_CHANNELS = {
OPEN_PATH: 'open-path',
OPEN_LOGS_PATH: 'open-logs-path',
OPEN_DEV_TOOLS: 'open-dev-tools',
TERMINAL_WRITE: 'execute-terminal-command',
TERMINAL_RESIZE: 'resize-terminal',
TERMINAL_RESTORE: 'restore-terminal',
TERMINAL_ON_OUTPUT: 'terminal-output',
IS_FIRST_TIME_SETUP: 'is-first-time-setup',
GET_SYSTEM_PATHS: 'get-system-paths',
VALIDATE_INSTALL_PATH: 'validate-install-path',
Expand Down
19 changes: 18 additions & 1 deletion src/main-process/comfyDesktopApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,20 @@ import path from 'path';
import { getModelsDirectory } from '../utils';
import { DownloadManager } from '../models/DownloadManager';
import { VirtualEnvironment } from '../virtualEnvironment';
import { Terminal } from '../terminal';
import { getAppResourcesPath } from '../install/resourcePaths';

export class ComfyDesktopApp {
public comfyServer: ComfyServer | null = null;
private terminal: Terminal;

constructor(
public basePath: string,
public comfySettings: ComfySettings,
public appWindow: AppWindow
) {}
) {
this.terminal = new Terminal(this.appWindow, getAppResourcesPath());
}

get pythonInstallPath() {
return app.isPackaged ? this.basePath : path.join(app.getAppPath(), 'assets');
Expand Down Expand Up @@ -104,6 +109,18 @@ export class ComfyDesktopApp {
return null;
}
});

ipcMain.handle(IPC_CHANNELS.TERMINAL_WRITE, (_event, command: string) => {
this.terminal.write(command);
});

ipcMain.handle(IPC_CHANNELS.TERMINAL_RESIZE, (_event, cols: number, rows: number) => {
this.terminal.resize(cols, rows);
});

ipcMain.handle(IPC_CHANNELS.TERMINAL_RESTORE, (_event) => {
return this.terminal.restore();
});
}

/**
Expand Down
2 changes: 0 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ if (!gotTheLock) {
...options,
});
});

try {
const comfyDesktopApp = await ComfyDesktopApp.create(appWindow);
await comfyDesktopApp.initialize();
Expand All @@ -90,7 +89,6 @@ if (!gotTheLock) {
if (!useExternalServer) {
await comfyDesktopApp.startComfyServer({ host, port, extraServerArgs });
}

appWindow.sendServerStartProgress(ProgressStatus.READY);
appWindow.loadComfyUI({ host, port, extraServerArgs });
} catch (error) {
Expand Down
34 changes: 34 additions & 0 deletions src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,40 @@ const electronAPI = {
extras,
});
},
Terminal: {
/**
* Writes the data to the terminal
* @param data The command to execute
*/
write: (data: string): Promise<string> => {
return ipcRenderer.invoke(IPC_CHANNELS.TERMINAL_WRITE, data);
},
/**
* Resizes the terminal
* @param data The command to execute
*/
resize: (cols: number, rows: number): Promise<void> => {
return ipcRenderer.invoke(IPC_CHANNELS.TERMINAL_RESIZE, cols, rows);
},
/**
* Gets the data required to restore the terminal
* @param data The command to execute
*/
restore: (): Promise<{ buffer: string[]; pos: { x: number; y: number } }> => {
return ipcRenderer.invoke(IPC_CHANNELS.TERMINAL_RESTORE);
},
/**
* Callback for terminal output messages
* @param callback The output handler
*/
onOutput: (callback: (message: string) => void) => {
const handler = (_event: Electron.IpcRendererEvent, value: string) => {
callback(value);
};
ipcRenderer.on(IPC_CHANNELS.TERMINAL_ON_OUTPUT, handler);
return () => ipcRenderer.off(IPC_CHANNELS.TERMINAL_ON_OUTPUT, handler);
},
},
/**
* Check if the user has completed the first time setup wizard.
*/
Expand Down
67 changes: 67 additions & 0 deletions src/terminal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as os from 'node:os';
import * as pty from 'node-pty';
import { AppWindow } from './main-process/appWindow';
import { IPC_CHANNELS } from './constants';

export class Terminal {
#pty: pty.IPty | undefined;
#window: AppWindow | undefined;
#cwd: string | undefined;

readonly sessionBuffer: string[] = [];
readonly size = { cols: 80, rows: 30 };

get pty() {
this.#pty ??= this.#createPty();
return this.#pty;
}

get window() {
if (!this.#window) throw new Error('AppWindow not initialized.');
return this.#window;
}

constructor(window: AppWindow, cwd: string) {
this.#window = window;
this.#cwd = cwd;
}

write(data: string) {
this.pty.write(data);
}

resize(cols: number, rows: number) {
this.pty.resize(cols, rows);
this.size.cols = cols;
this.size.rows = rows;
}

restore() {
return {
buffer: this.sessionBuffer,
size: this.size,
};
}

#createPty() {
const window = this.window;
// TODO: does this want to be a setting?
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
const instance = pty.spawn(shell, [], {
handleFlowControl: false,
conptyInheritCursor: false,
name: 'comfyui-terminal',
cols: this.size.cols,
rows: this.size.rows,
cwd: this.#cwd,
});

instance.onData((data) => {
this.sessionBuffer.push(data);
window.send(IPC_CHANNELS.TERMINAL_ON_OUTPUT, data);
if (this.sessionBuffer.length > 1000) this.sessionBuffer.shift();
});

return instance;
}
}
68 changes: 66 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ __metadata:
dependencies:
"@electron/fuses": "npm:^1.8.0"
"@electron/notarize": "npm:^2.4.0"
"@electron/rebuild": "npm:^3.7.1"
"@electron/windows-sign": "npm:^1.1.3"
"@playwright/test": "npm:^1.47.2"
"@sentry/electron": "npm:^5.4.0"
Expand Down Expand Up @@ -497,6 +498,7 @@ __metadata:
husky: "npm:^9.1.6"
jest: "npm:^29.7.0"
lint-staged: "npm:^15.2.10"
node-pty: "npm:^1.0.0"
prettier: "npm:^3.3.3"
rimraf: "npm:^6.0.1"
systeminformation: "npm:^5.23.5"
Expand Down Expand Up @@ -576,6 +578,26 @@ __metadata:
languageName: node
linkType: hard

"@electron/node-gyp@git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2":
version: 10.2.0-electron.1
resolution: "@electron/node-gyp@https://github.com/electron/node-gyp.git#commit=06b29aafb7708acef8b3669835c8a7857ebc92d2"
dependencies:
env-paths: "npm:^2.2.0"
exponential-backoff: "npm:^3.1.1"
glob: "npm:^8.1.0"
graceful-fs: "npm:^4.2.6"
make-fetch-happen: "npm:^10.2.1"
nopt: "npm:^6.0.0"
proc-log: "npm:^2.0.1"
semver: "npm:^7.3.5"
tar: "npm:^6.2.1"
which: "npm:^2.0.2"
bin:
node-gyp: ./bin/node-gyp.js
checksum: 10c0/e8c97bb5347bf0871312860010b70379069359bf05a6beb9e4d898d0831f9f8447f35b887a86d5241989e804813cf72054327928da38714a6102f791e802c8d9
languageName: node
linkType: hard

"@electron/notarize@npm:2.5.0, @electron/notarize@npm:^2.4.0":
version: 2.5.0
resolution: "@electron/notarize@npm:2.5.0"
Expand Down Expand Up @@ -628,6 +650,31 @@ __metadata:
languageName: node
linkType: hard

"@electron/rebuild@npm:^3.7.1":
version: 3.7.1
resolution: "@electron/rebuild@npm:3.7.1"
dependencies:
"@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2"
"@malept/cross-spawn-promise": "npm:^2.0.0"
chalk: "npm:^4.0.0"
debug: "npm:^4.1.1"
detect-libc: "npm:^2.0.1"
fs-extra: "npm:^10.0.0"
got: "npm:^11.7.0"
node-abi: "npm:^3.45.0"
node-api-version: "npm:^0.2.0"
node-gyp: "npm:latest"
ora: "npm:^5.1.0"
read-binary-file-arch: "npm:^1.0.6"
semver: "npm:^7.3.5"
tar: "npm:^6.0.5"
yargs: "npm:^17.0.1"
bin:
electron-rebuild: lib/cli.js
checksum: 10c0/ef498ec1eb6d2870f4331dd53d84132a4fb7d2ef6a0058854731d3261fc0af3e2c8549c1c268801b7c2c9e93519b22d67b2a4fe7ed0136214100980801e2a372
languageName: node
linkType: hard

"@electron/universal@npm:2.0.1":
version: 2.0.1
resolution: "@electron/universal@npm:2.0.1"
Expand Down Expand Up @@ -9364,7 +9411,7 @@ __metadata:
languageName: node
linkType: hard

"make-fetch-happen@npm:^10.0.3":
"make-fetch-happen@npm:^10.0.3, make-fetch-happen@npm:^10.2.1":
version: 10.2.1
resolution: "make-fetch-happen@npm:10.2.1"
dependencies:
Expand Down Expand Up @@ -9822,7 +9869,7 @@ __metadata:
languageName: node
linkType: hard

"nan@npm:^2.14.0":
"nan@npm:^2.14.0, nan@npm:^2.17.0":
version: 2.22.0
resolution: "nan@npm:2.22.0"
dependencies:
Expand Down Expand Up @@ -9966,6 +10013,16 @@ __metadata:
languageName: node
linkType: hard

"node-pty@npm:^1.0.0":
version: 1.0.0
resolution: "node-pty@npm:1.0.0"
dependencies:
nan: "npm:^2.17.0"
node-gyp: "npm:latest"
checksum: 10c0/c308686826eb2f7616735f4c71e6e41ff630346b14319972dbdf9711640bc6975ce21eab66a47b7ce9a88c70308fe81bfd9840127388d5fa26c52afbad255871
languageName: node
linkType: hard

"node-releases@npm:^2.0.18":
version: 2.0.18
resolution: "node-releases@npm:2.0.18"
Expand Down Expand Up @@ -10727,6 +10784,13 @@ __metadata:
languageName: node
linkType: hard

"proc-log@npm:^2.0.1":
version: 2.0.1
resolution: "proc-log@npm:2.0.1"
checksum: 10c0/701c501429775ce34cec28ef6a1c976537274b42917212fb8a5975ebcecb0a85612907fd7f99ff28ff4c2112bb84a0f4322fc9b9e1e52a8562fcbb1d5b3ce608
languageName: node
linkType: hard

"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0":
version: 4.2.0
resolution: "proc-log@npm:4.2.0"
Expand Down
Loading