Skip to content

Commit

Permalink
Provide ComfyUI capable installer
Browse files Browse the repository at this point in the history
for demo purposes, directly bundle comfyUI into installer
In the future, this is supposed to be downloaded in the
running application, by the user.

Signed-off-by: Florian Esser <[email protected]>
  • Loading branch information
florianesser-tng committed Nov 22, 2024
1 parent 2bca5d0 commit bca8705
Show file tree
Hide file tree
Showing 368 changed files with 470,018 additions and 2 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ installer.nsh
*.exe
*.7z
*.whl
ComfyUI/
1 change: 0 additions & 1 deletion ComfyUI
Submodule ComfyUI deleted from 518c0d
1 change: 1 addition & 0 deletions ComfyUI/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @comfyanonymous
41 changes: 41 additions & 0 deletions ComfyUI/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Contributing to ComfyUI

Welcome, and thank you for your interest in contributing to ComfyUI!

There are several ways in which you can contribute, beyond writing code. The goal of this document is to provide a high-level overview of how you can get involved.

## Asking Questions

Have a question? Instead of opening an issue, please ask on [Discord](https://comfy.org/discord) or [Matrix](https://app.element.io/#/room/%23comfyui_space%3Amatrix.org) channels. Our team and the community will help you.

## Providing Feedback

Your comments and feedback are welcome, and the development team is available via a handful of different channels.

See the `#bug-report`, `#feature-request` and `#feedback` channels on Discord.

## Reporting Issues

Have you identified a reproducible problem in ComfyUI? Do you have a feature request? We want to hear about it! Here's how you can report your issue as effectively as possible.


### Look For an Existing Issue

Before you create a new issue, please do a search in [open issues](https://github.com/comfyanonymous/ComfyUI/issues) to see if the issue or feature request has already been filed.

If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment:

* 👍 - upvote
* 👎 - downvote

If you cannot find an existing issue that describes your bug or feature, create a new issue. We have an issue template in place to organize new issues.


### Creating Pull Requests

* Please refer to the article on [creating pull requests](https://github.com/comfyanonymous/ComfyUI/wiki/How-to-Contribute-Code) and contributing to this project.


## Thank You

Your contributions to open source, large or small, make great projects like this possible. Thank you for taking the time to contribute.
674 changes: 674 additions & 0 deletions ComfyUI/LICENSE

Large diffs are not rendered by default.

300 changes: 300 additions & 0 deletions ComfyUI/README.md

Large diffs are not rendered by default.

Empty file added ComfyUI/api_server/__init__.py
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions ComfyUI/api_server/routes/internal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ComfyUI Internal Routes

All routes under the `/internal` path are designated for **internal use by ComfyUI only**. These routes are not intended for use by external applications may change at any time without notice.
Empty file.
76 changes: 76 additions & 0 deletions ComfyUI/api_server/routes/internal/internal_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from aiohttp import web
from typing import Optional
from folder_paths import models_dir, user_directory, output_directory, folder_names_and_paths
from api_server.services.file_service import FileService
from api_server.services.terminal_service import TerminalService
import app.logger

class InternalRoutes:
'''
The top level web router for internal routes: /internal/*
The endpoints here should NOT be depended upon. It is for ComfyUI frontend use only.
Check README.md for more information.
'''

def __init__(self, prompt_server):
self.routes: web.RouteTableDef = web.RouteTableDef()
self._app: Optional[web.Application] = None
self.file_service = FileService({
"models": models_dir,
"user": user_directory,
"output": output_directory
})
self.prompt_server = prompt_server
self.terminal_service = TerminalService(prompt_server)

def setup_routes(self):
@self.routes.get('/files')
async def list_files(request):
directory_key = request.query.get('directory', '')
try:
file_list = self.file_service.list_files(directory_key)
return web.json_response({"files": file_list})
except ValueError as e:
return web.json_response({"error": str(e)}, status=400)
except Exception as e:
return web.json_response({"error": str(e)}, status=500)

@self.routes.get('/logs')
async def get_logs(request):
return web.json_response("".join([(l["t"] + " - " + l["m"]) for l in app.logger.get_logs()]))

Check failure on line 41 in ComfyUI/api_server/routes/internal/internal_routes.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E741)

ComfyUI/api_server/routes/internal/internal_routes.py:41:77: E741 Ambiguous variable name: `l`

@self.routes.get('/logs/raw')
async def get_logs(request):

Check failure on line 44 in ComfyUI/api_server/routes/internal/internal_routes.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F811)

ComfyUI/api_server/routes/internal/internal_routes.py:44:19: F811 Redefinition of unused `get_logs` from line 40
self.terminal_service.update_size()
return web.json_response({
"entries": list(app.logger.get_logs()),
"size": {"cols": self.terminal_service.cols, "rows": self.terminal_service.rows}
})

@self.routes.patch('/logs/subscribe')
async def subscribe_logs(request):
json_data = await request.json()
client_id = json_data["clientId"]
enabled = json_data["enabled"]
if enabled:
self.terminal_service.subscribe(client_id)
else:
self.terminal_service.unsubscribe(client_id)

return web.Response(status=200)


@self.routes.get('/folder_paths')
async def get_folder_paths(request):
response = {}
for key in folder_names_and_paths:
response[key] = folder_names_and_paths[key][0]
return web.json_response(response)

def get_app(self):
if self._app is None:
self._app = web.Application()
self.setup_routes()
self._app.add_routes(self.routes)
return self._app
Empty file.
13 changes: 13 additions & 0 deletions ComfyUI/api_server/services/file_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import Dict, List, Optional
from api_server.utils.file_operations import FileSystemOperations, FileSystemItem

class FileService:
def __init__(self, allowed_directories: Dict[str, str], file_system_ops: Optional[FileSystemOperations] = None):
self.allowed_directories: Dict[str, str] = allowed_directories
self.file_system_ops: FileSystemOperations = file_system_ops or FileSystemOperations()

def list_files(self, directory_key: str) -> List[FileSystemItem]:
if directory_key not in self.allowed_directories:
raise ValueError("Invalid directory key")
directory_path: str = self.allowed_directories[directory_key]
return self.file_system_ops.walk_directory(directory_path)
60 changes: 60 additions & 0 deletions ComfyUI/api_server/services/terminal_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from app.logger import on_flush
import os
import shutil


class TerminalService:
def __init__(self, server):
self.server = server
self.cols = None
self.rows = None
self.subscriptions = set()
on_flush(self.send_messages)

def get_terminal_size(self):
try:
size = os.get_terminal_size()
return (size.columns, size.lines)
except OSError:
try:
size = shutil.get_terminal_size()
return (size.columns, size.lines)
except OSError:
return (80, 24) # fallback to 80x24

def update_size(self):
columns, lines = self.get_terminal_size()
changed = False

if columns != self.cols:
self.cols = columns
changed = True

if lines != self.rows:
self.rows = lines
changed = True

if changed:
return {"cols": self.cols, "rows": self.rows}

return None

def subscribe(self, client_id):
self.subscriptions.add(client_id)

def unsubscribe(self, client_id):
self.subscriptions.discard(client_id)

def send_messages(self, entries):
if not len(entries) or not len(self.subscriptions):
return

new_size = self.update_size()

for client_id in self.subscriptions.copy(): # prevent: Set changed size during iteration
if client_id not in self.server.sockets:
# Automatically unsub if the socket has disconnected
self.unsubscribe(client_id)
continue

self.server.send_sync("logs", {"entries": entries, "size": new_size}, client_id)
42 changes: 42 additions & 0 deletions ComfyUI/api_server/utils/file_operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os
from typing import List, Union, TypedDict, Literal
from typing_extensions import TypeGuard
class FileInfo(TypedDict):
name: str
path: str
type: Literal["file"]
size: int

class DirectoryInfo(TypedDict):
name: str
path: str
type: Literal["directory"]

FileSystemItem = Union[FileInfo, DirectoryInfo]

def is_file_info(item: FileSystemItem) -> TypeGuard[FileInfo]:
return item["type"] == "file"

class FileSystemOperations:
@staticmethod
def walk_directory(directory: str) -> List[FileSystemItem]:
file_list: List[FileSystemItem] = []
for root, dirs, files in os.walk(directory):
for name in files:
file_path = os.path.join(root, name)
relative_path = os.path.relpath(file_path, directory)
file_list.append({
"name": name,
"path": relative_path,
"type": "file",
"size": os.path.getsize(file_path)
})
for name in dirs:
dir_path = os.path.join(root, name)
relative_path = os.path.relpath(dir_path, directory)
file_list.append({
"name": name,
"path": relative_path,
"type": "directory"
})
return file_list
Empty file added ComfyUI/app/__init__.py
Empty file.
54 changes: 54 additions & 0 deletions ComfyUI/app/app_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import os
import json
from aiohttp import web


class AppSettings():
def __init__(self, user_manager):
self.user_manager = user_manager

def get_settings(self, request):
file = self.user_manager.get_request_user_filepath(
request, "comfy.settings.json")
if os.path.isfile(file):
with open(file) as f:
return json.load(f)
else:
return {}

def save_settings(self, request, settings):
file = self.user_manager.get_request_user_filepath(
request, "comfy.settings.json")
with open(file, "w") as f:
f.write(json.dumps(settings, indent=4))

def add_routes(self, routes):
@routes.get("/settings")
async def get_settings(request):
return web.json_response(self.get_settings(request))

@routes.get("/settings/{id}")
async def get_setting(request):
value = None
settings = self.get_settings(request)
setting_id = request.match_info.get("id", None)
if setting_id and setting_id in settings:
value = settings[setting_id]
return web.json_response(value)

@routes.post("/settings")
async def post_settings(request):
settings = self.get_settings(request)
new_settings = await request.json()
self.save_settings(request, {**settings, **new_settings})
return web.Response(status=200)

@routes.post("/settings/{id}")
async def post_setting(request):
setting_id = request.match_info.get("id", None)
if not setting_id:
return web.Response(status=400)
settings = self.get_settings(request)
settings[setting_id] = await request.json()
self.save_settings(request, settings)
return web.Response(status=200)
Loading

0 comments on commit bca8705

Please sign in to comment.