mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-06-24 16:59:29 +08:00
Merge branch 'master' into sam3d_body
This commit is contained in:
commit
cf7c5a0bde
@ -1400,7 +1400,8 @@ class V3Data(TypedDict):
|
|||||||
class HiddenHolder:
|
class HiddenHolder:
|
||||||
def __init__(self, unique_id: str, prompt: Any,
|
def __init__(self, unique_id: str, prompt: Any,
|
||||||
extra_pnginfo: Any, dynprompt: Any,
|
extra_pnginfo: Any, dynprompt: Any,
|
||||||
auth_token_comfy_org: str, api_key_comfy_org: str, **kwargs):
|
auth_token_comfy_org: str, api_key_comfy_org: str,
|
||||||
|
comfy_usage_source: str = None, **kwargs):
|
||||||
self.unique_id = unique_id
|
self.unique_id = unique_id
|
||||||
"""UNIQUE_ID is the unique identifier of the node, and matches the id property of the node on the client side. It is commonly used in client-server communications (see messages)."""
|
"""UNIQUE_ID is the unique identifier of the node, and matches the id property of the node on the client side. It is commonly used in client-server communications (see messages)."""
|
||||||
self.prompt = prompt
|
self.prompt = prompt
|
||||||
@ -1413,6 +1414,8 @@ class HiddenHolder:
|
|||||||
"""AUTH_TOKEN_COMFY_ORG is a token acquired from signing into a ComfyOrg account on frontend."""
|
"""AUTH_TOKEN_COMFY_ORG is a token acquired from signing into a ComfyOrg account on frontend."""
|
||||||
self.api_key_comfy_org = api_key_comfy_org
|
self.api_key_comfy_org = api_key_comfy_org
|
||||||
"""API_KEY_COMFY_ORG is an API Key generated by ComfyOrg that allows skipping signing into a ComfyOrg account on frontend."""
|
"""API_KEY_COMFY_ORG is an API Key generated by ComfyOrg that allows skipping signing into a ComfyOrg account on frontend."""
|
||||||
|
self.comfy_usage_source = comfy_usage_source
|
||||||
|
"""COMFY_USAGE_SOURCE identifies the client that submitted the prompt (e.g. comfyui-frontend, comfy-cli, comfyui-mcp); forwarded to API nodes' upstream requests via the Comfy-Usage-Source header."""
|
||||||
|
|
||||||
def __getattr__(self, key: str):
|
def __getattr__(self, key: str):
|
||||||
'''If hidden variable not found, return None.'''
|
'''If hidden variable not found, return None.'''
|
||||||
@ -1429,6 +1432,7 @@ class HiddenHolder:
|
|||||||
dynprompt=d.get(Hidden.dynprompt, None),
|
dynprompt=d.get(Hidden.dynprompt, None),
|
||||||
auth_token_comfy_org=d.get(Hidden.auth_token_comfy_org, None),
|
auth_token_comfy_org=d.get(Hidden.auth_token_comfy_org, None),
|
||||||
api_key_comfy_org=d.get(Hidden.api_key_comfy_org, None),
|
api_key_comfy_org=d.get(Hidden.api_key_comfy_org, None),
|
||||||
|
comfy_usage_source=d.get(Hidden.comfy_usage_source, None),
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -1451,6 +1455,8 @@ class Hidden(str, Enum):
|
|||||||
"""AUTH_TOKEN_COMFY_ORG is a token acquired from signing into a ComfyOrg account on frontend."""
|
"""AUTH_TOKEN_COMFY_ORG is a token acquired from signing into a ComfyOrg account on frontend."""
|
||||||
api_key_comfy_org = "API_KEY_COMFY_ORG"
|
api_key_comfy_org = "API_KEY_COMFY_ORG"
|
||||||
"""API_KEY_COMFY_ORG is an API Key generated by ComfyOrg that allows skipping signing into a ComfyOrg account on frontend."""
|
"""API_KEY_COMFY_ORG is an API Key generated by ComfyOrg that allows skipping signing into a ComfyOrg account on frontend."""
|
||||||
|
comfy_usage_source = "COMFY_USAGE_SOURCE"
|
||||||
|
"""COMFY_USAGE_SOURCE identifies the client that submitted the prompt (e.g. comfyui-frontend, comfy-cli, comfyui-mcp); forwarded to API nodes' upstream requests via the Comfy-Usage-Source header."""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -1654,6 +1660,8 @@ class Schema:
|
|||||||
self.hidden.append(Hidden.auth_token_comfy_org)
|
self.hidden.append(Hidden.auth_token_comfy_org)
|
||||||
if Hidden.api_key_comfy_org not in self.hidden:
|
if Hidden.api_key_comfy_org not in self.hidden:
|
||||||
self.hidden.append(Hidden.api_key_comfy_org)
|
self.hidden.append(Hidden.api_key_comfy_org)
|
||||||
|
if Hidden.comfy_usage_source not in self.hidden:
|
||||||
|
self.hidden.append(Hidden.comfy_usage_source)
|
||||||
# if is an output_node, will need prompt and extra_pnginfo
|
# if is an output_node, will need prompt and extra_pnginfo
|
||||||
if self.is_output_node:
|
if self.is_output_node:
|
||||||
if Hidden.prompt not in self.hidden:
|
if Hidden.prompt not in self.hidden:
|
||||||
|
|||||||
@ -289,7 +289,7 @@ class BriaRemoveVideoBackground(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
is_api_node=True,
|
is_api_node=True,
|
||||||
price_badge=IO.PriceBadge(
|
price_badge=IO.PriceBadge(
|
||||||
expr="""{"type":"usd","usd":0.14,"format":{"suffix":"/second"}}""",
|
expr="""{"type":"usd","usd":0.0042,"format":{"suffix":"/second"}}""",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ class BriaVideoGreenScreen(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
is_api_node=True,
|
is_api_node=True,
|
||||||
price_badge=IO.PriceBadge(
|
price_badge=IO.PriceBadge(
|
||||||
expr="""{"type":"usd","usd":0.14,"format":{"suffix":"/second"}}""",
|
expr="""{"type":"usd","usd":0.0042,"format":{"suffix":"/second"}}""",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -433,7 +433,7 @@ class BriaVideoReplaceBackground(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
is_api_node=True,
|
is_api_node=True,
|
||||||
price_badge=IO.PriceBadge(
|
price_badge=IO.PriceBadge(
|
||||||
expr="""{"type":"usd","usd":0.14,"format":{"suffix":"/second"}}""",
|
expr="""{"type":"usd","usd":0.0042,"format":{"suffix":"/second"}}""",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -452,7 +452,10 @@ class BriaVideoReplaceBackground(IO.ComfyNode):
|
|||||||
validate_video_duration(background_video, max_duration=60.0)
|
validate_video_duration(background_video, max_duration=60.0)
|
||||||
background_url = await upload_video_to_comfyapi(cls, background_video, wait_label="Uploading background")
|
background_url = await upload_video_to_comfyapi(cls, background_video, wait_label="Uploading background")
|
||||||
else:
|
else:
|
||||||
background_url = await upload_image_to_comfyapi(cls, background_image, wait_label="Uploading background")
|
# Bria's replace_background 500s on RGBA, so drop the alpha channel before upload.
|
||||||
|
background_url = await upload_image_to_comfyapi(
|
||||||
|
cls, background_image[:, :, :, :3], wait_label="Uploading background"
|
||||||
|
)
|
||||||
response = await sync_op(
|
response = await sync_op(
|
||||||
cls,
|
cls,
|
||||||
ApiEndpoint(path="/proxy/bria/v2/video/edit/replace_background", method="POST"),
|
ApiEndpoint(path="/proxy/bria/v2/video/edit/replace_background", method="POST"),
|
||||||
@ -530,7 +533,7 @@ class BriaTransparentVideoBackground(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
is_api_node=True,
|
is_api_node=True,
|
||||||
price_badge=IO.PriceBadge(
|
price_badge=IO.PriceBadge(
|
||||||
expr="""{"type":"usd","usd":0.14,"format":{"suffix":"/second"}}""",
|
expr="""{"type":"usd","usd":0.0042,"format":{"suffix":"/second"}}""",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -571,7 +574,7 @@ class BriaExtension(ComfyExtension):
|
|||||||
BriaRemoveImageBackground,
|
BriaRemoveImageBackground,
|
||||||
BriaRemoveVideoBackground,
|
BriaRemoveVideoBackground,
|
||||||
BriaVideoGreenScreen,
|
BriaVideoGreenScreen,
|
||||||
# BriaVideoReplaceBackground, # server returns Status 500 when we pass background video
|
BriaVideoReplaceBackground,
|
||||||
BriaTransparentVideoBackground,
|
BriaTransparentVideoBackground,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ from comfy_api_nodes.util import (
|
|||||||
)
|
)
|
||||||
from comfy_api_nodes.util._helpers import (
|
from comfy_api_nodes.util._helpers import (
|
||||||
default_base_url,
|
default_base_url,
|
||||||
get_auth_header,
|
get_comfy_api_headers,
|
||||||
get_node_id,
|
get_node_id,
|
||||||
is_processing_interrupted,
|
is_processing_interrupted,
|
||||||
)
|
)
|
||||||
@ -174,8 +174,7 @@ async def _stream_sonilo_music(
|
|||||||
"""POST ``form`` to Sonilo, read the NDJSON stream, and return the first stream's audio bytes."""
|
"""POST ``form`` to Sonilo, read the NDJSON stream, and return the first stream's audio bytes."""
|
||||||
url = urljoin(default_base_url().rstrip("/") + "/", endpoint.path.lstrip("/"))
|
url = urljoin(default_base_url().rstrip("/") + "/", endpoint.path.lstrip("/"))
|
||||||
|
|
||||||
headers: dict[str, str] = {}
|
headers = get_comfy_api_headers(cls)
|
||||||
headers.update(get_auth_header(cls))
|
|
||||||
headers.update(endpoint.headers)
|
headers.update(endpoint.headers)
|
||||||
|
|
||||||
node_id = get_node_id(cls)
|
node_id = get_node_id(cls)
|
||||||
|
|||||||
@ -9,6 +9,7 @@ from io import BytesIO
|
|||||||
from yarl import URL
|
from yarl import URL
|
||||||
|
|
||||||
from comfy.cli_args import args
|
from comfy.cli_args import args
|
||||||
|
from comfy.deploy_environment import get_deploy_environment
|
||||||
from comfy.model_management import processing_interrupted
|
from comfy.model_management import processing_interrupted
|
||||||
from comfy_api.latest import IO
|
from comfy_api.latest import IO
|
||||||
|
|
||||||
@ -35,6 +36,30 @@ def get_auth_header(node_cls: type[IO.ComfyNode]) -> dict[str, str]:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def get_usage_source(node_cls: type[IO.ComfyNode]) -> str:
|
||||||
|
"""Source of the prompt that triggered this API node.
|
||||||
|
|
||||||
|
Defaults to "comfyui-api" when the submitting client didn't identify itself,
|
||||||
|
i.e. a direct API call to this server.
|
||||||
|
"""
|
||||||
|
return node_cls.hidden.comfy_usage_source or "comfyui-api"
|
||||||
|
|
||||||
|
|
||||||
|
def get_comfy_api_headers(node_cls: type[IO.ComfyNode]) -> dict[str, str]:
|
||||||
|
"""Common headers (auth, deploy environment, usage source) for Comfy API requests.
|
||||||
|
|
||||||
|
Centralizes the shared header set so every Comfy API request sends a consistent
|
||||||
|
set and new shared headers only need to be added in one place. Intended for
|
||||||
|
relative/cloud URLs resolved against ``default_base_url()``; because the result
|
||||||
|
includes auth, callers must not attach it to arbitrary absolute/presigned URLs.
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
**get_auth_header(node_cls),
|
||||||
|
"Comfy-Env": get_deploy_environment(),
|
||||||
|
"Comfy-Usage-Source": get_usage_source(node_cls),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def default_base_url() -> str:
|
def default_base_url() -> str:
|
||||||
return getattr(args, "comfy_api_base", "https://api.comfy.org")
|
return getattr(args, "comfy_api_base", "https://api.comfy.org")
|
||||||
|
|
||||||
|
|||||||
@ -19,12 +19,10 @@ from comfy import utils
|
|||||||
from comfy_api.latest import IO
|
from comfy_api.latest import IO
|
||||||
from server import PromptServer
|
from server import PromptServer
|
||||||
|
|
||||||
from comfy.deploy_environment import get_deploy_environment
|
|
||||||
|
|
||||||
from . import request_logger
|
from . import request_logger
|
||||||
from ._helpers import (
|
from ._helpers import (
|
||||||
default_base_url,
|
default_base_url,
|
||||||
get_auth_header,
|
get_comfy_api_headers,
|
||||||
get_node_id,
|
get_node_id,
|
||||||
is_processing_interrupted,
|
is_processing_interrupted,
|
||||||
sleep_with_interrupt,
|
sleep_with_interrupt,
|
||||||
@ -645,8 +643,7 @@ async def _request_base(cfg: _RequestConfig, expect_binary: bool):
|
|||||||
|
|
||||||
payload_headers = {"Accept": "*/*"} if expect_binary else {"Accept": "application/json"}
|
payload_headers = {"Accept": "*/*"} if expect_binary else {"Accept": "application/json"}
|
||||||
if not parsed_url.scheme and not parsed_url.netloc: # is URL relative?
|
if not parsed_url.scheme and not parsed_url.netloc: # is URL relative?
|
||||||
payload_headers.update(get_auth_header(cfg.node_cls))
|
payload_headers.update(get_comfy_api_headers(cfg.node_cls))
|
||||||
payload_headers["Comfy-Env"] = get_deploy_environment()
|
|
||||||
if cfg.endpoint.headers:
|
if cfg.endpoint.headers:
|
||||||
payload_headers.update(cfg.endpoint.headers)
|
payload_headers.update(cfg.endpoint.headers)
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from folder_paths import get_output_directory
|
|||||||
from . import request_logger
|
from . import request_logger
|
||||||
from ._helpers import (
|
from ._helpers import (
|
||||||
default_base_url,
|
default_base_url,
|
||||||
get_auth_header,
|
get_comfy_api_headers,
|
||||||
is_processing_interrupted,
|
is_processing_interrupted,
|
||||||
sleep_with_interrupt,
|
sleep_with_interrupt,
|
||||||
to_aiohttp_url,
|
to_aiohttp_url,
|
||||||
@ -64,7 +64,7 @@ async def download_url_to_bytesio(
|
|||||||
if cls is None:
|
if cls is None:
|
||||||
raise ValueError("For relative 'cloud' paths, the `cls` parameter is required.")
|
raise ValueError("For relative 'cloud' paths, the `cls` parameter is required.")
|
||||||
url = urljoin(default_base_url().rstrip("/") + "/", url.lstrip("/"))
|
url = urljoin(default_base_url().rstrip("/") + "/", url.lstrip("/"))
|
||||||
headers = get_auth_header(cls)
|
headers = get_comfy_api_headers(cls)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
attempt += 1
|
attempt += 1
|
||||||
|
|||||||
@ -200,6 +200,8 @@ def get_input_data(inputs, class_def, unique_id, execution_list=None, dynprompt=
|
|||||||
hidden_inputs_v3[io.Hidden.auth_token_comfy_org] = extra_data.get("auth_token_comfy_org", None)
|
hidden_inputs_v3[io.Hidden.auth_token_comfy_org] = extra_data.get("auth_token_comfy_org", None)
|
||||||
if io.Hidden.api_key_comfy_org.name in hidden:
|
if io.Hidden.api_key_comfy_org.name in hidden:
|
||||||
hidden_inputs_v3[io.Hidden.api_key_comfy_org] = extra_data.get("api_key_comfy_org", None)
|
hidden_inputs_v3[io.Hidden.api_key_comfy_org] = extra_data.get("api_key_comfy_org", None)
|
||||||
|
if io.Hidden.comfy_usage_source.name in hidden:
|
||||||
|
hidden_inputs_v3[io.Hidden.comfy_usage_source] = extra_data.get("comfy_usage_source", None)
|
||||||
else:
|
else:
|
||||||
if "hidden" in valid_inputs:
|
if "hidden" in valid_inputs:
|
||||||
h = valid_inputs["hidden"]
|
h = valid_inputs["hidden"]
|
||||||
@ -216,6 +218,8 @@ def get_input_data(inputs, class_def, unique_id, execution_list=None, dynprompt=
|
|||||||
input_data_all[x] = [extra_data.get("auth_token_comfy_org", None)]
|
input_data_all[x] = [extra_data.get("auth_token_comfy_org", None)]
|
||||||
if h[x] == "API_KEY_COMFY_ORG":
|
if h[x] == "API_KEY_COMFY_ORG":
|
||||||
input_data_all[x] = [extra_data.get("api_key_comfy_org", None)]
|
input_data_all[x] = [extra_data.get("api_key_comfy_org", None)]
|
||||||
|
if h[x] == "COMFY_USAGE_SOURCE":
|
||||||
|
input_data_all[x] = [extra_data.get("comfy_usage_source", None)]
|
||||||
v3_data["hidden_inputs"] = hidden_inputs_v3
|
v3_data["hidden_inputs"] = hidden_inputs_v3
|
||||||
return input_data_all, missing_keys, v3_data
|
return input_data_all, missing_keys, v3_data
|
||||||
|
|
||||||
|
|||||||
@ -971,6 +971,11 @@ class PromptServer():
|
|||||||
|
|
||||||
if "client_id" in json_data:
|
if "client_id" in json_data:
|
||||||
extra_data["client_id"] = json_data["client_id"]
|
extra_data["client_id"] = json_data["client_id"]
|
||||||
|
|
||||||
|
if "comfy_usage_source" not in extra_data:
|
||||||
|
usage_source = request.headers.get("Comfy-Usage-Source")
|
||||||
|
if usage_source:
|
||||||
|
extra_data["comfy_usage_source"] = usage_source
|
||||||
if valid[0]:
|
if valid[0]:
|
||||||
outputs_to_execute = valid[2]
|
outputs_to_execute = valid[2]
|
||||||
sensitive = {}
|
sensitive = {}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user