mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-07-21 23:41:28 +08:00
Improved API support
- Run comfyui workflows directly inside other python applications using EmbeddedComfyClient. - Optional telemetry in prompts and models using anonymity preserving Plausible self-hosted or hosted. - Better OpenAPI schema - Basic support for distributed ComfyUI backends. Limitations: no progress reporting, no easy way to start your own distributed backend, requires RabbitMQ as a message broker.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# do not import all endpoints into this module because that uses a lot of memory and stack frames
|
||||
# if you need the ability to import all endpoints from this module, import them with
|
||||
# from comfy.api.apis.paths.object_info import ObjectInfo
|
||||
|
||||
path = "/object_info"
|
||||
@@ -0,0 +1,114 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
|
||||
"""
|
||||
|
||||
from comfy.api import api_client
|
||||
from comfy.api.shared_imports.operation_imports import * # pyright: ignore [reportWildcardImportFromLibrary]
|
||||
|
||||
from .. import path
|
||||
from .responses import response_200
|
||||
|
||||
|
||||
__StatusCodeToResponse = typing.TypedDict(
|
||||
'__StatusCodeToResponse',
|
||||
{
|
||||
'200': typing.Type[response_200.ResponseFor200],
|
||||
}
|
||||
)
|
||||
_status_code_to_response: __StatusCodeToResponse = {
|
||||
'200': response_200.ResponseFor200,
|
||||
}
|
||||
_non_error_status_codes = frozenset({
|
||||
'200',
|
||||
})
|
||||
|
||||
_all_accept_content_types = (
|
||||
"application/json",
|
||||
)
|
||||
|
||||
|
||||
class BaseApi(api_client.Api):
|
||||
@typing.overload
|
||||
def _get_object_info(
|
||||
self,
|
||||
*,
|
||||
skip_deserialization: typing.Literal[False] = False,
|
||||
accept_content_types: typing.Tuple[str, ...] = _all_accept_content_types,
|
||||
server_index: typing.Optional[int] = None,
|
||||
stream: bool = False,
|
||||
timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
|
||||
) -> response_200.ApiResponse: ...
|
||||
|
||||
@typing.overload
|
||||
def _get_object_info(
|
||||
self,
|
||||
*,
|
||||
skip_deserialization: typing.Literal[True],
|
||||
accept_content_types: typing.Tuple[str, ...] = _all_accept_content_types,
|
||||
server_index: typing.Optional[int] = None,
|
||||
stream: bool = False,
|
||||
timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
|
||||
) -> api_response.ApiResponseWithoutDeserialization: ...
|
||||
|
||||
def _get_object_info(
|
||||
self,
|
||||
*,
|
||||
skip_deserialization: bool = False,
|
||||
accept_content_types: typing.Tuple[str, ...] = _all_accept_content_types,
|
||||
server_index: typing.Optional[int] = None,
|
||||
stream: bool = False,
|
||||
timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
|
||||
):
|
||||
"""
|
||||
(UI) Get object info
|
||||
:param skip_deserialization: If true then api_response.response will be set but
|
||||
api_response.body and api_response.headers will not be deserialized into schema
|
||||
class instances
|
||||
"""
|
||||
used_path = path
|
||||
headers = self._get_headers(accept_content_types=accept_content_types)
|
||||
# TODO add cookie handling
|
||||
host = self.api_client.configuration.get_server_url(
|
||||
"servers", server_index
|
||||
)
|
||||
|
||||
raw_response = self.api_client.call_api(
|
||||
resource_path=used_path,
|
||||
method='get',
|
||||
host=host,
|
||||
headers=headers,
|
||||
stream=stream,
|
||||
timeout=timeout,
|
||||
)
|
||||
|
||||
if skip_deserialization:
|
||||
skip_deser_response = api_response.ApiResponseWithoutDeserialization(response=raw_response)
|
||||
self._verify_response_status(skip_deser_response)
|
||||
return skip_deser_response
|
||||
|
||||
status = str(raw_response.status)
|
||||
if status in _non_error_status_codes:
|
||||
status_code = typing.cast(
|
||||
typing.Literal[
|
||||
'200',
|
||||
],
|
||||
status
|
||||
)
|
||||
return _status_code_to_response[status_code].deserialize(
|
||||
raw_response, self.api_client.schema_configuration)
|
||||
|
||||
response = api_response.ApiResponseWithoutDeserialization(response=raw_response)
|
||||
self._verify_response_status(response)
|
||||
return response
|
||||
|
||||
|
||||
class GetObjectInfo(BaseApi):
|
||||
# this class is used by api classes that refer to endpoints with operationId.snakeCase fn names
|
||||
get_object_info = BaseApi._get_object_info
|
||||
|
||||
|
||||
class ApiForGet(BaseApi):
|
||||
# this class is used by api classes that refer to endpoints by path and http method names
|
||||
get = BaseApi._get_object_info
|
||||
@@ -0,0 +1,28 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
|
||||
"""
|
||||
|
||||
from comfy.api.shared_imports.response_imports import * # pyright: ignore [reportWildcardImportFromLibrary]
|
||||
|
||||
from .content.application_json import schema as application_json_schema
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class ApiResponse(api_response.ApiResponse):
|
||||
body: application_json_schema.SchemaDict
|
||||
headers: schemas.Unset
|
||||
|
||||
|
||||
class ResponseFor200(api_client.OpenApiResponse[ApiResponse]):
|
||||
@classmethod
|
||||
def get_response(cls, response, headers, body) -> ApiResponse:
|
||||
return ApiResponse(response=response, body=body, headers=headers)
|
||||
|
||||
|
||||
class ApplicationJsonMediaType(api_client.MediaType):
|
||||
schema: typing_extensions.TypeAlias = application_json_schema.Schema
|
||||
content = {
|
||||
'application/json': ApplicationJsonMediaType,
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
comfyui
|
||||
No description provided (generated by Openapi JSON Schema Generator https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) # noqa: E501
|
||||
The version of the OpenAPI document: 0.0.1
|
||||
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from comfy.api.shared_imports.schema_imports import * # pyright: ignore [reportWildcardImportFromLibrary]
|
||||
|
||||
|
||||
from comfy.api.components.schema import node
|
||||
|
||||
|
||||
class SchemaDict(schemas.immutabledict[str, node.NodeDict]):
|
||||
|
||||
__required_keys__: typing.FrozenSet[str] = frozenset({
|
||||
})
|
||||
__optional_keys__: typing.FrozenSet[str] = frozenset({
|
||||
})
|
||||
def __new__(
|
||||
cls,
|
||||
configuration_: typing.Optional[schema_configuration.SchemaConfiguration] = None,
|
||||
**kwargs: typing.Union[
|
||||
node.NodeDictInput,
|
||||
node.NodeDict,
|
||||
],
|
||||
):
|
||||
used_kwargs = typing.cast(SchemaDictInput, kwargs)
|
||||
return Schema.validate(used_kwargs, configuration=configuration_)
|
||||
|
||||
@staticmethod
|
||||
def from_dict_(
|
||||
arg: typing.Union[
|
||||
SchemaDictInput,
|
||||
SchemaDict
|
||||
],
|
||||
configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None
|
||||
) -> SchemaDict:
|
||||
return Schema.validate(arg, configuration=configuration)
|
||||
|
||||
def get_additional_property_(self, name: str) -> typing.Union[node.NodeDict, schemas.Unset]:
|
||||
schemas.raise_if_key_known(name, self.__required_keys__, self.__optional_keys__)
|
||||
val = self.get(name, schemas.unset)
|
||||
if isinstance(val, schemas.Unset):
|
||||
return val
|
||||
return typing.cast(
|
||||
node.NodeDict,
|
||||
val
|
||||
)
|
||||
SchemaDictInput = typing.Mapping[
|
||||
str,
|
||||
typing.Union[
|
||||
node.NodeDictInput,
|
||||
node.NodeDict,
|
||||
],
|
||||
]
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class Schema(
|
||||
schemas.Schema[SchemaDict, tuple]
|
||||
):
|
||||
types: typing.FrozenSet[typing.Type] = frozenset({schemas.immutabledict})
|
||||
additional_properties: typing.Type[node.Node] = dataclasses.field(default_factory=lambda: node.Node) # type: ignore
|
||||
type_to_output_cls: typing.Mapping[
|
||||
typing.Type,
|
||||
typing.Type
|
||||
] = dataclasses.field(
|
||||
default_factory=lambda: {
|
||||
schemas.immutabledict: SchemaDict
|
||||
}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def validate(
|
||||
cls,
|
||||
arg: typing.Union[
|
||||
SchemaDictInput,
|
||||
SchemaDict,
|
||||
],
|
||||
configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None
|
||||
) -> SchemaDict:
|
||||
return super().validate_base(
|
||||
arg,
|
||||
configuration=configuration,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user