diff --git a/.github/workflows/update-api-stubs.yml b/.github/workflows/update-api-stubs.yml deleted file mode 100644 index 2ae99b673..000000000 --- a/.github/workflows/update-api-stubs.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Generate Pydantic Stubs from api.comfy.org - -on: - schedule: - - cron: '0 0 * * 1' - workflow_dispatch: - -jobs: - generate-models: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install 'datamodel-code-generator[http]' - - - name: Generate API models - run: | - datamodel-codegen --use-subclass-enum --url https://api.comfy.org/openapi --output comfy_api_nodes/apis --output-model-type pydantic_v2.BaseModel - - - name: Check for changes - id: git-check - run: | - git diff --exit-code comfy_api_nodes/apis || echo "changes=true" >> $GITHUB_OUTPUT - - - name: Create Pull Request - if: steps.git-check.outputs.changes == 'true' - uses: peter-evans/create-pull-request@v5 - with: - commit-message: 'chore: update API models from OpenAPI spec' - title: 'Update API models from api.comfy.org' - body: | - This PR updates the API models based on the latest api.comfy.org OpenAPI specification. - - Generated automatically by the a Github workflow. - branch: update-api-stubs - delete-branch: true - base: main diff --git a/comfy_api_nodes/apis/PixverseController.py b/comfy_api_nodes/apis/PixverseController.py deleted file mode 100644 index 9095db2f8..000000000 --- a/comfy_api_nodes/apis/PixverseController.py +++ /dev/null @@ -1,17 +0,0 @@ -# generated by datamodel-codegen: -# filename: http://localhost:8080/openapi -# timestamp: 2025-04-22T20:42:39+00:00 - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel - -from . import PixverseDto - - -class ResponseData(BaseModel): - ErrCode: Optional[int] = None - ErrMsg: Optional[str] = None - Resp: Optional[PixverseDto.V2OpenAPII2VResp] = None diff --git a/comfy_api_nodes/apis/PixverseDto.py b/comfy_api_nodes/apis/PixverseDto.py deleted file mode 100644 index 35a0a7f1b..000000000 --- a/comfy_api_nodes/apis/PixverseDto.py +++ /dev/null @@ -1,57 +0,0 @@ -# generated by datamodel-codegen: -# filename: http://localhost:8080/openapi -# timestamp: 2025-04-22T20:42:39+00:00 - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Field, constr - - -class V2OpenAPII2VResp(BaseModel): - video_id: Optional[int] = Field(None, description='Video_id') - - -class V2OpenAPIT2VReq(BaseModel): - aspect_ratio: str = Field( - ..., description='Aspect ratio (16:9, 4:3, 1:1, 3:4, 9:16)', examples=['16:9'] - ) - duration: int = Field( - ..., - description='Video duration (5, 8 seconds, --model=v3.5 only allows 5,8; --quality=1080p does not support 8s)', - examples=[5], - ) - model: str = Field( - ..., description='Model version (only supports v3.5)', examples=['v3.5'] - ) - motion_mode: Optional[str] = Field( - 'normal', - description='Motion mode (normal, fast, --fast only available when duration=5; --quality=1080p does not support fast)', - examples=['normal'], - ) - negative_prompt: Optional[constr(max_length=2048)] = Field( - None, description='Negative prompt\n' - ) - prompt: constr(max_length=2048) = Field(..., description='Prompt') - quality: str = Field( - ..., - description='Video quality ("360p"(Turbo model), "540p", "720p", "1080p")', - examples=['540p'], - ) - seed: Optional[int] = Field(None, description='Random seed, range: 0 - 2147483647') - style: Optional[str] = Field( - None, - description='Style (effective when model=v3.5, "anime", "3d_animation", "clay", "comic", "cyberpunk") Do not include style parameter unless needed', - examples=['anime'], - ) - template_id: Optional[int] = Field( - None, - description='Template ID (template_id must be activated before use)', - examples=[302325299692608], - ) - water_mark: Optional[bool] = Field( - False, - description='Watermark (true: add watermark, false: no watermark)', - examples=[False], - ) diff --git a/comfy_api_nodes/apis/__init__.py b/comfy_api_nodes/apis/__init__.py deleted file mode 100644 index c6951095f..000000000 --- a/comfy_api_nodes/apis/__init__.py +++ /dev/null @@ -1,1769 +0,0 @@ -# generated by datamodel-codegen: -# filename: http://localhost:8080/openapi -# timestamp: 2025-04-22T20:42:39+00:00 - -from __future__ import annotations - -from datetime import datetime -from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Union -from uuid import UUID - -from pydantic import AnyUrl, BaseModel, Field, RootModel, confloat, conint, constr - - -class BFLFluxProGenerateRequest(BaseModel): - guidance_scale: Optional[confloat(ge=1.0, le=20.0)] = Field( - None, description='The guidance scale for generation.' - ) - height: conint(ge=64, le=2048) = Field( - ..., description='The height of the image to generate.' - ) - negative_prompt: Optional[str] = Field( - None, description='The negative prompt for image generation.' - ) - num_images: Optional[conint(ge=1, le=4)] = Field( - None, description='The number of images to generate.' - ) - num_inference_steps: Optional[conint(ge=1, le=100)] = Field( - None, description='The number of inference steps.' - ) - prompt: str = Field(..., description='The text prompt for image generation.') - seed: Optional[int] = Field(None, description='The seed value for reproducibility.') - width: conint(ge=64, le=2048) = Field( - ..., description='The width of the image to generate.' - ) - - -class BFLFluxProGenerateResponse(BaseModel): - id: str = Field(..., description='The unique identifier for the generation task.') - polling_url: str = Field(..., description='URL to poll for the generation result.') - - -class ComfyNode(BaseModel): - category: Optional[str] = Field( - None, - description='UI category where the node is listed, used for grouping nodes.', - ) - comfy_node_name: Optional[str] = Field( - None, description='Unique identifier for the node' - ) - deprecated: Optional[bool] = Field( - None, - description='Indicates if the node is deprecated. Deprecated nodes are hidden in the UI.', - ) - description: Optional[str] = Field( - None, description="Brief description of the node's functionality or purpose." - ) - experimental: Optional[bool] = Field( - None, - description='Indicates if the node is experimental, subject to changes or removal.', - ) - function: Optional[str] = Field( - None, description='Name of the entry-point function to execute the node.' - ) - input_types: Optional[str] = Field(None, description='Defines input parameters') - output_is_list: Optional[List[bool]] = Field( - None, description='Boolean values indicating if each output is a list.' - ) - return_names: Optional[str] = Field( - None, description='Names of the outputs for clarity in workflows.' - ) - return_types: Optional[str] = Field( - None, description='Specifies the types of outputs produced by the node.' - ) - - -class ComfyNodeCloudBuildInfo(BaseModel): - build_id: Optional[str] = None - location: Optional[str] = None - project_id: Optional[str] = None - project_number: Optional[str] = None - - -class Customer(BaseModel): - createdAt: Optional[datetime] = Field( - None, description='The date and time the user was created' - ) - email: Optional[str] = Field(None, description='The email address for this user') - id: str = Field(..., description='The firebase UID of the user') - name: Optional[str] = Field(None, description='The name for this user') - updatedAt: Optional[datetime] = Field( - None, description='The date and time the user was last updated' - ) - - -class Error(BaseModel): - details: Optional[List[str]] = Field( - None, - description='Optional detailed information about the error or hints for resolving it.', - ) - message: Optional[str] = Field( - None, description='A clear and concise description of the error.' - ) - - -class ErrorResponse(BaseModel): - error: str - message: str - - -class GitCommitSummary(BaseModel): - author: Optional[str] = Field(None, description='The author of the commit') - branch_name: Optional[str] = Field( - None, description='The branch where the commit was made' - ) - commit_hash: Optional[str] = Field(None, description='The hash of the commit') - commit_name: Optional[str] = Field(None, description='The name of the commit') - status_summary: Optional[Dict[str, str]] = Field( - None, description='A map of operating system to status pairs' - ) - timestamp: Optional[datetime] = Field( - None, description='The timestamp when the commit was made' - ) - - -class ImageRequest(BaseModel): - aspect_ratio: Optional[str] = Field( - None, - description="Optional. The aspect ratio (e.g., 'ASPECT_16_9', 'ASPECT_1_1'). Cannot be used with resolution. Defaults to 'ASPECT_1_1' if unspecified.", - ) - color_palette: Optional[Dict[str, Any]] = Field( - None, description='Optional. Color palette object. Only for V_2, V_2_TURBO.' - ) - magic_prompt_option: Optional[str] = Field( - None, description="Optional. MagicPrompt usage ('AUTO', 'ON', 'OFF')." - ) - model: str = Field(..., description="The model used (e.g., 'V_2', 'V_2A_TURBO')") - negative_prompt: Optional[str] = Field( - None, - description='Optional. Description of what to exclude. Only for V_1, V_1_TURBO, V_2, V_2_TURBO.', - ) - num_images: Optional[conint(ge=1, le=8)] = Field( - 1, description='Optional. Number of images to generate (1-8). Defaults to 1.' - ) - prompt: str = Field( - ..., description='Required. The prompt to use to generate the image.' - ) - resolution: Optional[str] = Field( - None, - description="Optional. Resolution (e.g., 'RESOLUTION_1024_1024'). Only for model V_2. Cannot be used with aspect_ratio.", - ) - seed: Optional[conint(ge=0, le=2147483647)] = Field( - None, description='Optional. A number between 0 and 2147483647.' - ) - style_type: Optional[str] = Field( - None, - description="Optional. Style type ('AUTO', 'GENERAL', 'REALISTIC', 'DESIGN', 'RENDER_3D', 'ANIME'). Only for models V_2 and above.", - ) - - -class IdeogramGenerateRequest(BaseModel): - image_request: ImageRequest = Field( - ..., description='The image generation request parameters.' - ) - - -class Datum(BaseModel): - is_image_safe: Optional[bool] = Field( - None, description='Indicates whether the image is considered safe.' - ) - prompt: Optional[str] = Field( - None, description='The prompt used to generate this image.' - ) - resolution: Optional[str] = Field( - None, description="The resolution of the generated image (e.g., '1024x1024')." - ) - seed: Optional[int] = Field( - None, description='The seed value used for this generation.' - ) - style_type: Optional[str] = Field( - None, - description="The style type used for generation (e.g., 'REALISTIC', 'ANIME').", - ) - url: Optional[str] = Field(None, description='URL to the generated image.') - - -class IdeogramGenerateResponse(BaseModel): - created: Optional[datetime] = Field( - None, description='Timestamp when the generation was created.' - ) - data: Optional[List[Datum]] = Field( - None, description='Array of generated image information.' - ) - - -class Code(Enum): - int_1100 = 1100 - int_1101 = 1101 - int_1102 = 1102 - int_1103 = 1103 - - -class Code1(Enum): - int_1000 = 1000 - int_1001 = 1001 - int_1002 = 1002 - int_1003 = 1003 - int_1004 = 1004 - - -class KlingErrorResponse(BaseModel): - code: int = Field( - ..., description='Error code value as defined in the API documentation' - ) - message: str = Field(..., description='Human-readable error message') - request_id: str = Field( - ..., description='Request ID for tracking and troubleshooting' - ) - - -class AspectRatio(str, Enum): - field_16_9 = '16:9' - field_9_16 = '9:16' - field_1_1 = '1:1' - - -class Config(BaseModel): - horizontal: Optional[confloat(ge=-10.0, le=10.0)] = None - pan: Optional[confloat(ge=-10.0, le=10.0)] = None - roll: Optional[confloat(ge=-10.0, le=10.0)] = None - tilt: Optional[confloat(ge=-10.0, le=10.0)] = None - vertical: Optional[confloat(ge=-10.0, le=10.0)] = None - zoom: Optional[confloat(ge=-10.0, le=10.0)] = None - - -class Type(str, Enum): - simple = 'simple' - down_back = 'down_back' - forward_up = 'forward_up' - right_turn_forward = 'right_turn_forward' - left_turn_forward = 'left_turn_forward' - - -class CameraControl(BaseModel): - config: Optional[Config] = None - type: Optional[Type] = Field(None, description='Predefined camera movements type') - - -class Duration(str, Enum): - field_5 = 5 - field_10 = 10 - - -class Mode(str, Enum): - std = 'std' - pro = 'pro' - - -class ModelName(str, Enum): - kling_v1 = 'kling-v1' - kling_v1_6 = 'kling-v1-6' - - -class KlingImage2VideoRequest(BaseModel): - aspect_ratio: Optional[AspectRatio] = '16:9' - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - camera_control: Optional[CameraControl] = None - cfg_scale: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.5, description='Flexibility in video generation' - ) - duration: Optional[Duration] = 5 - external_task_id: Optional[str] = Field(None, description='Customized Task ID') - image_url: Optional[AnyUrl] = Field( - None, description='URL of the image to be used for video generation' - ) - mode: Optional[Mode] = Field('std', description='Video generation mode') - model_name: Optional[ModelName] = Field('kling-v1', description='Model Name') - negative_prompt: Optional[constr(max_length=2500)] = Field( - None, description='Negative text prompt' - ) - prompt: Optional[constr(max_length=2500)] = Field( - None, description='Positive text prompt' - ) - - -class TaskInfo(BaseModel): - external_task_id: Optional[str] = None - - -class Video(BaseModel): - duration: Optional[str] = Field(None, description='Total video duration') - id: Optional[str] = Field(None, description='Generated video ID') - url: Optional[AnyUrl] = Field(None, description='URL for generated video') - - -class TaskResult(BaseModel): - videos: Optional[List[Video]] = None - - -class TaskStatus(str, Enum): - submitted = 'submitted' - processing = 'processing' - succeed = 'succeed' - failed = 'failed' - - -class Data(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_info: Optional[TaskInfo] = None - task_result: Optional[TaskResult] = None - task_status: Optional[TaskStatus] = None - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingImage2VideoResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class AspectRatio1(str, Enum): - field_16_9 = '16:9' - field_9_16 = '9:16' - field_1_1 = '1:1' - field_4_3 = '4:3' - field_3_4 = '3:4' - field_3_2 = '3:2' - field_2_3 = '2:3' - field_21_9 = '21:9' - - -class ImageReference(str, Enum): - subject = 'subject' - face = 'face' - - -class ModelName1(str, Enum): - kling_v1 = 'kling-v1' - kling_v1_5 = 'kling-v1-5' - - -class KlingImageGenerationsRequest(BaseModel): - aspect_ratio: Optional[AspectRatio1] = Field( - '16:9', description='Aspect ratio of the generated images' - ) - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - human_fidelity: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.45, description='Subject reference similarity' - ) - image: Optional[str] = Field( - None, description='Reference Image - Base64 encoded string or image URL' - ) - image_fidelity: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.5, description='Reference intensity for user-uploaded images' - ) - image_reference: Optional[ImageReference] = Field( - None, description='Image reference type' - ) - model_name: Optional[ModelName1] = Field('kling-v1', description='Model Name') - n: Optional[conint(ge=1, le=9)] = Field(1, description='Number of generated images') - negative_prompt: Optional[constr(max_length=200)] = Field( - None, description='Negative text prompt' - ) - prompt: constr(max_length=500) = Field(..., description='Positive text prompt') - - -class Image(BaseModel): - index: Optional[int] = Field(None, description='Image Number (0-9)') - url: Optional[AnyUrl] = Field(None, description='URL for generated image') - - -class TaskResult1(BaseModel): - images: Optional[List[Image]] = None - - -class Data1(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_result: Optional[TaskResult1] = None - task_status: Optional[TaskStatus] = None - task_status_msg: Optional[str] = Field(None, description='Task status information') - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingImageGenerationsResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data1] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class AspectRatio2(str, Enum): - field_16_9 = '16:9' - field_9_16 = '9:16' - field_1_1 = '1:1' - - -class CameraControl1(BaseModel): - config: Optional[Config] = None - type: Optional[Type] = Field(None, description='Predefined camera movements type') - - -class ModelName2(str, Enum): - kling_v1 = 'kling-v1' - kling_v1_6 = 'kling-v1-6' - - -class KlingLipSyncRequest(BaseModel): - aspect_ratio: Optional[AspectRatio2] = '16:9' - audio_url: Optional[AnyUrl] = Field( - None, description='URL of the audio to be used for lip-syncing' - ) - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - camera_control: Optional[CameraControl1] = None - cfg_scale: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.5, description='Flexibility in video generation' - ) - duration: Optional[Duration] = 5 - external_task_id: Optional[str] = Field(None, description='Customized Task ID') - mode: Optional[Mode] = Field('std', description='Video generation mode') - model_name: Optional[ModelName2] = Field('kling-v1', description='Model Name') - negative_prompt: Optional[constr(max_length=2500)] = Field( - None, description='Negative text prompt' - ) - prompt: Optional[constr(max_length=2500)] = Field( - None, description='Positive text prompt' - ) - video_url: Optional[AnyUrl] = Field( - None, description='URL of the video to be lip-synced' - ) - - -class TaskResult2(BaseModel): - videos: Optional[List[Video]] = None - - -class Data2(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_info: Optional[TaskInfo] = None - task_result: Optional[TaskResult2] = None - task_status: Optional[TaskStatus] = None - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingLipSyncResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data2] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class Code2(Enum): - int_1200 = 1200 - int_1201 = 1201 - int_1202 = 1202 - int_1203 = 1203 - - -class KlingRequestError(KlingErrorResponse): - code: Optional[Code2] = Field( - None, - description='- 1200: Invalid request parameters\n- 1201: Invalid parameters\n- 1202: Invalid request method\n- 1203: Requested resource does not exist\n', - ) - - -class ResourcePackType(str, Enum): - decreasing_total = 'decreasing_total' - constant_period = 'constant_period' - - -class Status(str, Enum): - toBeOnline = 'toBeOnline' - online = 'online' - expired = 'expired' - runOut = 'runOut' - - -class ResourcePackSubscribeInfo(BaseModel): - effective_time: Optional[int] = Field( - None, description='Effective time, Unix timestamp in ms' - ) - invalid_time: Optional[int] = Field( - None, description='Expiration time, Unix timestamp in ms' - ) - purchase_time: Optional[int] = Field( - None, description='Purchase time, Unix timestamp in ms' - ) - remaining_quantity: Optional[float] = Field( - None, description='Remaining quantity (updated with a 12-hour delay)' - ) - resource_pack_id: Optional[str] = Field(None, description='Resource package ID') - resource_pack_name: Optional[str] = Field(None, description='Resource package name') - resource_pack_type: Optional[ResourcePackType] = Field( - None, - description='Resource package type (decreasing_total=decreasing total, constant_period=constant periodicity)', - ) - status: Optional[Status] = Field(None, description='Resource Package Status') - total_quantity: Optional[float] = Field(None, description='Total quantity') - - -class Data3(BaseModel): - code: Optional[int] = Field(None, description='Error code; 0 indicates success') - msg: Optional[str] = Field(None, description='Error information') - resource_pack_subscribe_infos: Optional[List[ResourcePackSubscribeInfo]] = Field( - None, description='Resource package list' - ) - - -class KlingResourcePackageResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code; 0 indicates success') - data: Optional[Data3] = None - message: Optional[str] = Field(None, description='Error information') - request_id: Optional[str] = Field( - None, - description='Request ID, generated by the system, used to track requests and troubleshoot problems', - ) - - -class Code3(Enum): - int_5000 = 5000 - int_5001 = 5001 - int_5002 = 5002 - - -class KlingServerError(KlingErrorResponse): - code: Optional[Code3] = Field( - None, - description='- 5000: Internal server error\n- 5001: Service temporarily unavailable\n- 5002: Server internal timeout\n', - ) - - -class Code4(Enum): - int_1300 = 1300 - int_1301 = 1301 - int_1302 = 1302 - int_1303 = 1303 - int_1304 = 1304 - - -class KlingStrategyError(KlingErrorResponse): - code: Optional[Code4] = Field( - None, - description='- 1300: Trigger platform strategy\n- 1301: Trigger content security policy\n- 1302: API request too frequent\n- 1303: Concurrency/QPS exceeds limit\n- 1304: Trigger IP whitelist policy\n', - ) - - -class CameraControl2(BaseModel): - config: Optional[Config] = None - type: Optional[Type] = Field(None, description='Predefined camera movements type') - - -class KlingText2VideoRequest(BaseModel): - aspect_ratio: Optional[AspectRatio2] = '16:9' - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - camera_control: Optional[CameraControl2] = None - cfg_scale: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.5, description='Flexibility in video generation' - ) - duration: Optional[Duration] = 5 - external_task_id: Optional[str] = Field(None, description='Customized Task ID') - mode: Optional[Mode] = Field('std', description='Video generation mode') - model_name: Optional[ModelName2] = Field('kling-v1', description='Model Name') - negative_prompt: Optional[constr(max_length=2500)] = Field( - None, description='Negative text prompt' - ) - prompt: Optional[constr(max_length=2500)] = Field( - None, description='Positive text prompt' - ) - - -class TaskResult3(BaseModel): - videos: Optional[List[Video]] = None - - -class Data4(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_info: Optional[TaskInfo] = None - task_result: Optional[TaskResult3] = None - task_status: Optional[TaskStatus] = None - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingText2VideoResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data4] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class CameraControl3(BaseModel): - config: Optional[Config] = None - type: Optional[Type] = Field(None, description='Predefined camera movements type') - - -class KlingVideoEffectsRequest(BaseModel): - aspect_ratio: Optional[AspectRatio2] = '16:9' - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - camera_control: Optional[CameraControl3] = None - cfg_scale: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.5, description='Flexibility in video generation' - ) - duration: Optional[Duration] = 5 - external_task_id: Optional[str] = Field(None, description='Customized Task ID') - mode: Optional[Mode] = Field('std', description='Video generation mode') - model_name: Optional[ModelName2] = Field('kling-v1', description='Model Name') - negative_prompt: Optional[constr(max_length=2500)] = Field( - None, description='Negative text prompt' - ) - prompt: Optional[constr(max_length=2500)] = Field( - None, description='Positive text prompt' - ) - video_url: Optional[AnyUrl] = Field( - None, description='URL of the video to be used for effects generation' - ) - - -class TaskResult4(BaseModel): - videos: Optional[List[Video]] = None - - -class Data5(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_info: Optional[TaskInfo] = None - task_result: Optional[TaskResult4] = None - task_status: Optional[TaskStatus] = None - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingVideoEffectsResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data5] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class CameraControl4(BaseModel): - config: Optional[Config] = None - type: Optional[Type] = Field(None, description='Predefined camera movements type') - - -class KlingVideoExtendRequest(BaseModel): - aspect_ratio: Optional[AspectRatio2] = '16:9' - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - camera_control: Optional[CameraControl4] = None - cfg_scale: Optional[confloat(ge=0.0, le=1.0)] = Field( - 0.5, description='Flexibility in video generation' - ) - duration: Optional[Duration] = 5 - external_task_id: Optional[str] = Field(None, description='Customized Task ID') - mode: Optional[Mode] = Field('std', description='Video generation mode') - model_name: Optional[ModelName2] = Field('kling-v1', description='Model Name') - negative_prompt: Optional[constr(max_length=2500)] = Field( - None, description='Negative text prompt' - ) - prompt: Optional[constr(max_length=2500)] = Field( - None, description='Positive text prompt' - ) - video_url: Optional[AnyUrl] = Field( - None, description='URL of the video to be extended' - ) - - -class TaskResult5(BaseModel): - videos: Optional[List[Video]] = None - - -class Data6(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_info: Optional[TaskInfo] = None - task_result: Optional[TaskResult5] = None - task_status: Optional[TaskStatus] = None - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingVideoExtendResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data6] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class ModelName6(str, Enum): - kolors_virtual_try_on_v1 = 'kolors-virtual-try-on-v1' - kolors_virtual_try_on_v1_5 = 'kolors-virtual-try-on-v1-5' - - -class KlingVirtualTryOnRequest(BaseModel): - callback_url: Optional[AnyUrl] = Field( - None, description='The callback notification address' - ) - cloth_image: Optional[str] = Field( - None, - description='Reference clothing image - Base64 encoded string or image URL', - ) - human_image: str = Field( - ..., description='Reference human image - Base64 encoded string or image URL' - ) - model_name: Optional[ModelName6] = Field( - 'kolors-virtual-try-on-v1', description='Model Name' - ) - - -class Image1(BaseModel): - index: Optional[int] = Field(None, description='Image Number') - url: Optional[AnyUrl] = Field(None, description='URL for generated image') - - -class TaskResult6(BaseModel): - images: Optional[List[Image1]] = None - - -class Data7(BaseModel): - created_at: Optional[int] = Field(None, description='Task creation time') - task_id: Optional[str] = Field(None, description='Task ID') - task_result: Optional[TaskResult6] = None - task_status: Optional[TaskStatus] = None - task_status_msg: Optional[str] = Field(None, description='Task status information') - updated_at: Optional[int] = Field(None, description='Task update time') - - -class KlingVirtualTryOnResponse(BaseModel): - code: Optional[int] = Field(None, description='Error code') - data: Optional[Data7] = None - message: Optional[str] = Field(None, description='Error message') - request_id: Optional[str] = Field(None, description='Request ID') - - -class LumaAspectRatio(str, Enum): - field_1_1 = '1:1' - field_16_9 = '16:9' - field_9_16 = '9:16' - field_4_3 = '4:3' - field_3_4 = '3:4' - field_21_9 = '21:9' - field_9_21 = '9:21' - - -class LumaAssets(BaseModel): - image: Optional[AnyUrl] = Field(None, description='The URL of the image') - progress_video: Optional[AnyUrl] = Field( - None, description='The URL of the progress video' - ) - video: Optional[AnyUrl] = Field(None, description='The URL of the video') - - -class GenerationType(str, Enum): - add_audio = 'add_audio' - - -class LumaAudioGenerationRequest(BaseModel): - callback_url: Optional[AnyUrl] = Field( - None, description='The callback URL for the audio' - ) - generation_type: Optional[GenerationType] = 'add_audio' - negative_prompt: Optional[str] = Field( - None, description='The negative prompt of the audio' - ) - prompt: Optional[str] = Field(None, description='The prompt of the audio') - - -class LumaError(BaseModel): - detail: Optional[str] = Field(None, description='The error message') - - -class Type5(str, Enum): - generation = 'generation' - - -class LumaGenerationReference(BaseModel): - id: UUID = Field(..., description='The ID of the generation') - type: Literal['generation'] - - -class GenerationType1(str, Enum): - video = 'video' - - -class LumaGenerationType(str, Enum): - video = 'video' - image = 'image' - - -class GenerationType2(str, Enum): - image = 'image' - - -class LumaImageIdentity(BaseModel): - images: Optional[List[AnyUrl]] = Field( - None, description='The URLs of the image identity' - ) - - -class LumaImageModel(str, Enum): - photon_1 = 'photon-1' - photon_flash_1 = 'photon-flash-1' - - -class LumaImageRef(BaseModel): - url: Optional[AnyUrl] = Field(None, description='The URL of the image reference') - weight: Optional[float] = Field( - None, description='The weight of the image reference' - ) - - -class Type6(str, Enum): - image = 'image' - - -class LumaImageReference(BaseModel): - type: Literal['image'] - url: AnyUrl = Field(..., description='The URL of the image') - - -class LumaKeyframe(RootModel[Union[LumaGenerationReference, LumaImageReference]]): - root: Union[LumaGenerationReference, LumaImageReference] = Field( - ..., - description='A keyframe can be either a Generation reference, an Image, or a Video', - discriminator='type', - examples=[ - { - 'summary': 'Generation reference', - 'value': { - 'id': '123e4567-e89b-12d3-a456-426614174000', - 'type': 'generation', - }, - }, - { - 'summary': 'Image reference', - 'value': {'type': 'image', 'url': 'https://example.com/image.jpg'}, - }, - ], - ) - - -class LumaKeyframes(BaseModel): - frame0: Optional[LumaKeyframe] = None - frame1: Optional[LumaKeyframe] = None - - -class LumaModifyImageRef(BaseModel): - url: Optional[AnyUrl] = Field(None, description='The URL of the image reference') - weight: Optional[float] = Field( - None, description='The weight of the modify image reference' - ) - - -class LumaState(str, Enum): - queued = 'queued' - dreaming = 'dreaming' - completed = 'completed' - failed = 'failed' - - -class GenerationType3(str, Enum): - upscale_video = 'upscale_video' - - -class LumaVideoModel(str, Enum): - ray_1_6 = 'ray-1-6' - ray_2 = 'ray-2' - ray_flash_2 = 'ray-flash-2' - - -class LumaVideoModelOutputDuration1(str, Enum): - field_5s = '5s' - field_9s = '9s' - - -class LumaVideoModelOutputDuration( - RootModel[Union[LumaVideoModelOutputDuration1, str]] -): - root: Union[LumaVideoModelOutputDuration1, str] - - -class LumaVideoModelOutputResolution1(str, Enum): - field_540p = '540p' - field_720p = '720p' - field_1080p = '1080p' - field_4k = '4k' - - -class LumaVideoModelOutputResolution( - RootModel[Union[LumaVideoModelOutputResolution1, str]] -): - root: Union[LumaVideoModelOutputResolution1, str] - - -class MachineStats(BaseModel): - cpu_capacity: Optional[str] = Field(None, description='Total CPU on the machine.') - disk_capacity: Optional[str] = Field( - None, description='Total disk capacity on the machine.' - ) - gpu_type: Optional[str] = Field( - None, description='The GPU type. eg. NVIDIA Tesla K80' - ) - initial_cpu: Optional[str] = Field( - None, description='Initial CPU available before the job starts.' - ) - initial_disk: Optional[str] = Field( - None, description='Initial disk available before the job starts.' - ) - initial_ram: Optional[str] = Field( - None, description='Initial RAM available before the job starts.' - ) - machine_name: Optional[str] = Field(None, description='Name of the machine.') - memory_capacity: Optional[str] = Field( - None, description='Total memory on the machine.' - ) - os_version: Optional[str] = Field( - None, description='The operating system version. eg. Ubuntu Linux 20.04' - ) - pip_freeze: Optional[str] = Field(None, description='The pip freeze output') - vram_time_series: Optional[Dict[str, Any]] = Field( - None, description='Time series of VRAM usage.' - ) - - -class MinimaxBaseResponse(BaseModel): - status_code: int = Field( - ..., - description='Status code. 0 indicates success, other values indicate errors.', - ) - status_msg: str = Field( - ..., description='Specific error details or success message.' - ) - - -class File(BaseModel): - bytes: Optional[int] = Field(None, description='File size in bytes') - created_at: Optional[int] = Field( - None, description='Unix timestamp when the file was created, in seconds' - ) - download_url: Optional[str] = Field( - None, description='The URL to download the video' - ) - file_id: Optional[int] = Field(None, description='Unique identifier for the file') - filename: Optional[str] = Field(None, description='The name of the file') - purpose: Optional[str] = Field(None, description='The purpose of using the file') - - -class MinimaxFileRetrieveResponse(BaseModel): - base_resp: MinimaxBaseResponse - file: File - - -class Status1(str, Enum): - Queueing = 'Queueing' - Preparing = 'Preparing' - Processing = 'Processing' - Success = 'Success' - Fail = 'Fail' - - -class MinimaxTaskResultResponse(BaseModel): - base_resp: MinimaxBaseResponse - file_id: Optional[str] = Field( - None, - description='After the task status changes to Success, this field returns the file ID corresponding to the generated video.', - ) - status: Status1 = Field( - ..., - description="Task status: 'Queueing' (in queue), 'Preparing' (task is preparing), 'Processing' (generating), 'Success' (task completed successfully), or 'Fail' (task failed).", - ) - task_id: str = Field(..., description='The task ID being queried.') - - -class Model(str, Enum): - T2V_01_Director = 'T2V-01-Director' - I2V_01_Director = 'I2V-01-Director' - S2V_01 = 'S2V-01' - I2V_01 = 'I2V-01' - I2V_01_live = 'I2V-01-live' - T2V_01 = 'T2V-01' - - -class SubjectReferenceItem(BaseModel): - image: Optional[str] = Field( - None, description='URL or base64 encoding of the subject reference image.' - ) - mask: Optional[str] = Field( - None, - description='URL or base64 encoding of the mask for the subject reference image.', - ) - - -class MinimaxVideoGenerationRequest(BaseModel): - callback_url: Optional[str] = Field( - None, - description='Optional. URL to receive real-time status updates about the video generation task.', - ) - first_frame_image: Optional[str] = Field( - None, - description='URL or base64 encoding of the first frame image. Required when model is I2V-01, I2V-01-Director, or I2V-01-live.', - ) - model: Model = Field( - ..., - description='Required. ID of model. Options: T2V-01-Director, I2V-01-Director, S2V-01, I2V-01, I2V-01-live, T2V-01', - ) - prompt: Optional[constr(max_length=2000)] = Field( - None, - description='Description of the video. Should be less than 2000 characters. Supports camera movement instructions in [brackets].', - ) - prompt_optimizer: Optional[bool] = Field( - True, - description='If true (default), the model will automatically optimize the prompt. Set to false for more precise control.', - ) - subject_reference: Optional[List[SubjectReferenceItem]] = Field( - None, - description='Only available when model is S2V-01. The model will generate a video based on the subject uploaded through this parameter.', - ) - - -class MinimaxVideoGenerationResponse(BaseModel): - base_resp: MinimaxBaseResponse - task_id: str = Field( - ..., description='The task ID for the asynchronous video generation task.' - ) - - -class NodeStatus(str, Enum): - NodeStatusActive = 'NodeStatusActive' - NodeStatusDeleted = 'NodeStatusDeleted' - NodeStatusBanned = 'NodeStatusBanned' - - -class NodeVersionStatus(str, Enum): - NodeVersionStatusActive = 'NodeVersionStatusActive' - NodeVersionStatusDeleted = 'NodeVersionStatusDeleted' - NodeVersionStatusBanned = 'NodeVersionStatusBanned' - NodeVersionStatusPending = 'NodeVersionStatusPending' - NodeVersionStatusFlagged = 'NodeVersionStatusFlagged' - - -class NodeVersionUpdateRequest(BaseModel): - changelog: Optional[str] = Field( - None, description='The changelog describing the version changes.' - ) - deprecated: Optional[bool] = Field( - None, description='Whether the version is deprecated.' - ) - - -class Quality(str, Enum): - low = 'low' - medium = 'medium' - high = 'high' - - -class OpenAIImageEditRequest(BaseModel): - image: Union[bytes_aliased, List[bytes_aliased]] = Field( - ..., - description='Image(s) to edit. For DALL-E 2, only a single image is supported. For gpt-image-1, multiple images can be provided using image[] notation in form data.', - ) - mask: Optional[bytes_aliased] = Field( - None, - description='An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where image should be edited', - ) - model: str = Field( - ..., description='The model to use for image editing', examples=['gpt-image-1'] - ) - prompt: str = Field( - ..., - description='A text description of the desired edit', - examples=['Give the rocketship rainbow coloring'], - ) - quality: Optional[Quality] = Field( - None, description='The quality of the edited image', examples=['low'] - ) - - -class Background(str, Enum): - transparent = 'transparent' - opaque = 'opaque' - - -class Moderation(str, Enum): - low = 'low' - auto = 'auto' - - -class OutputFormat(str, Enum): - png = 'png' - webp = 'webp' - jpeg = 'jpeg' - - -class ResponseFormat(str, Enum): - url = 'url' - b64_json = 'b64_json' - - -class Style(str, Enum): - vivid = 'vivid' - natural = 'natural' - - -class OpenAIImageGenerationRequest(BaseModel): - background: Optional[Background] = Field( - None, description='Background transparency', examples=['opaque'] - ) - model: Optional[str] = Field( - None, - description='The model to use for image generation', - examples=['gpt-image-1'], - ) - moderation: Optional[Moderation] = Field( - None, description='Content moderation setting', examples=['auto'] - ) - n: Optional[int] = Field( - None, - description='The number of images to generate (1-10). Only 1 supported for dall-e-3.', - examples=[1], - ) - output_compression: Optional[int] = Field( - None, description='Compression level for JPEG or WebP (0-100)', examples=[100] - ) - output_format: Optional[OutputFormat] = Field( - None, description='Format of the output image', examples=['png'] - ) - prompt: str = Field( - ..., - description='A text description of the desired image', - examples=['Draw a rocket in front of a blackhole in deep space'], - ) - quality: Optional[Quality] = Field( - None, description='The quality of the generated image', examples=['high'] - ) - response_format: Optional[ResponseFormat] = Field( - None, description='Response format of image data', examples=['b64_json'] - ) - size: Optional[str] = Field( - None, - description='Size of the image (e.g., 1024x1024, 1536x1024, auto)', - examples=['1024x1536'], - ) - style: Optional[Style] = Field( - None, description='Style of the image (only for dall-e-3)', examples=['vivid'] - ) - user: Optional[str] = Field( - None, - description='A unique identifier for end-user monitoring', - examples=['user-1234'], - ) - - -class Datum1(BaseModel): - b64_json: Optional[str] = Field(None, description='Base64 encoded image data') - revised_prompt: Optional[str] = Field(None, description='Revised prompt') - url: Optional[str] = Field(None, description='URL of the image') - - -class OpenAIImageGenerationResponse(BaseModel): - data: Optional[List[Datum1]] = None - - -class PersonalAccessToken(BaseModel): - createdAt: Optional[datetime] = Field( - None, description='[Output Only]The date and time the token was created.' - ) - description: Optional[str] = Field( - None, - description="Optional. A more detailed description of the token's intended use.", - ) - id: Optional[UUID] = Field(None, description='Unique identifier for the GitCommit') - name: Optional[str] = Field( - None, - description='Required. The name of the token. Can be a simple description.', - ) - token: Optional[str] = Field( - None, - description='[Output Only]. The personal access token. Only returned during creation.', - ) - - -class PublisherStatus(str, Enum): - PublisherStatusActive = 'PublisherStatusActive' - PublisherStatusBanned = 'PublisherStatusBanned' - - -class PublisherUser(BaseModel): - email: Optional[str] = Field(None, description='The email address for this user.') - id: Optional[str] = Field(None, description='The unique id for this user.') - name: Optional[str] = Field(None, description='The name for this user.') - - -class RecraftImageGenerationRequest(BaseModel): - model: str = Field( - ..., description='The model to use for generation (e.g., "recraftv3")' - ) - n: conint(ge=1, le=4) = Field(..., description='The number of images to generate') - prompt: str = Field( - ..., description='The text prompt describing the image to generate' - ) - size: str = Field( - ..., description='The size of the generated image (e.g., "1024x1024")' - ) - style: Optional[str] = Field( - None, - description='The style to apply to the generated image (e.g., "digital_illustration")', - ) - - -class Datum2(BaseModel): - image_id: Optional[str] = Field( - None, description='Unique identifier for the generated image' - ) - url: Optional[str] = Field(None, description='URL to access the generated image') - - -class RecraftImageGenerationResponse(BaseModel): - created: int = Field( - ..., description='Unix timestamp when the generation was created' - ) - credits: int = Field(..., description='Number of credits used for the generation') - data: List[Datum2] = Field(..., description='Array of generated image information') - - -class StorageFile(BaseModel): - file_path: Optional[str] = Field(None, description='Path to the file in storage') - id: Optional[UUID] = Field( - None, description='Unique identifier for the storage file' - ) - public_url: Optional[str] = Field(None, description='Public URL') - - -class StripeAddress(BaseModel): - city: Optional[str] = None - country: Optional[str] = None - line1: Optional[str] = None - line2: Optional[str] = None - postal_code: Optional[str] = None - state: Optional[str] = None - - -class StripeAmountDetails(BaseModel): - tip: Optional[Dict[str, Any]] = None - - -class StripeBillingDetails(BaseModel): - address: Optional[StripeAddress] = None - email: Optional[str] = None - name: Optional[str] = None - phone: Optional[str] = None - tax_id: Optional[Any] = None - - -class Checks(BaseModel): - address_line1_check: Optional[Any] = None - address_postal_code_check: Optional[Any] = None - cvc_check: Optional[str] = None - - -class ExtendedAuthorization(BaseModel): - status: Optional[str] = None - - -class IncrementalAuthorization(BaseModel): - status: Optional[str] = None - - -class Multicapture(BaseModel): - status: Optional[str] = None - - -class NetworkToken(BaseModel): - used: Optional[bool] = None - - -class Overcapture(BaseModel): - maximum_amount_capturable: Optional[int] = None - status: Optional[str] = None - - -class StripeCardDetails(BaseModel): - amount_authorized: Optional[int] = None - authorization_code: Optional[Any] = None - brand: Optional[str] = None - checks: Optional[Checks] = None - country: Optional[str] = None - exp_month: Optional[int] = None - exp_year: Optional[int] = None - extended_authorization: Optional[ExtendedAuthorization] = None - fingerprint: Optional[str] = None - funding: Optional[str] = None - incremental_authorization: Optional[IncrementalAuthorization] = None - installments: Optional[Any] = None - last4: Optional[str] = None - mandate: Optional[Any] = None - multicapture: Optional[Multicapture] = None - network: Optional[str] = None - network_token: Optional[NetworkToken] = None - network_transaction_id: Optional[str] = None - overcapture: Optional[Overcapture] = None - regulated_status: Optional[str] = None - three_d_secure: Optional[Any] = None - wallet: Optional[Any] = None - - -class Object(str, Enum): - charge = 'charge' - - -class Object1(str, Enum): - event = 'event' - - -class Type7(str, Enum): - payment_intent_succeeded = 'payment_intent.succeeded' - - -class StripeOutcome(BaseModel): - advice_code: Optional[Any] = None - network_advice_code: Optional[Any] = None - network_decline_code: Optional[Any] = None - network_status: Optional[str] = None - reason: Optional[Any] = None - risk_level: Optional[str] = None - risk_score: Optional[int] = None - seller_message: Optional[str] = None - type: Optional[str] = None - - -class Object2(str, Enum): - payment_intent = 'payment_intent' - - -class StripePaymentMethodDetails(BaseModel): - card: Optional[StripeCardDetails] = None - type: Optional[str] = None - - -class Card(BaseModel): - installments: Optional[Any] = None - mandate_options: Optional[Any] = None - network: Optional[Any] = None - request_three_d_secure: Optional[str] = None - - -class StripePaymentMethodOptions(BaseModel): - card: Optional[Card] = None - - -class StripeRefundList(BaseModel): - data: Optional[List[Dict[str, Any]]] = None - has_more: Optional[bool] = None - object: Optional[str] = None - total_count: Optional[int] = None - url: Optional[str] = None - - -class StripeRequestInfo(BaseModel): - id: Optional[str] = None - idempotency_key: Optional[str] = None - - -class StripeShipping(BaseModel): - address: Optional[StripeAddress] = None - carrier: Optional[str] = None - name: Optional[str] = None - phone: Optional[str] = None - tracking_number: Optional[str] = None - - -class User(BaseModel): - email: Optional[str] = Field(None, description='The email address for this user.') - id: Optional[str] = Field(None, description='The unique id for this user.') - isAdmin: Optional[bool] = Field( - None, description='Indicates if the user has admin privileges.' - ) - isApproved: Optional[bool] = Field( - None, description='Indicates if the user is approved.' - ) - name: Optional[str] = Field(None, description='The name for this user.') - - -class Image2(BaseModel): - bytesBase64Encoded: str - gcsUri: Optional[str] = None - mimeType: Optional[str] = None - - -class Image3(BaseModel): - bytesBase64Encoded: Optional[str] = None - gcsUri: str - mimeType: Optional[str] = None - - -class Instance(BaseModel): - image: Optional[Union[Image2, Image3]] = Field( - None, description='Optional image to guide video generation' - ) - prompt: str = Field(..., description='Text description of the video') - - -class PersonGeneration(str, Enum): - ALLOW = 'ALLOW' - BLOCK = 'BLOCK' - - -class Parameters(BaseModel): - aspectRatio: Optional[str] = Field(None, examples=['16:9']) - durationSeconds: Optional[int] = None - enhancePrompt: Optional[bool] = None - negativePrompt: Optional[str] = None - personGeneration: Optional[PersonGeneration] = None - sampleCount: Optional[int] = None - seed: Optional[int] = None - storageUri: Optional[str] = Field( - None, description='Optional Cloud Storage URI to upload the video' - ) - - -class VeoRequestBody(BaseModel): - instances: Optional[List[Instance]] = None - parameters: Optional[Parameters] = None - - -class WorkflowRunStatus(str, Enum): - WorkflowRunStatusStarted = 'WorkflowRunStatusStarted' - WorkflowRunStatusFailed = 'WorkflowRunStatusFailed' - WorkflowRunStatusCompleted = 'WorkflowRunStatusCompleted' - - -class ActionJobResult(BaseModel): - action_job_id: Optional[str] = Field( - None, description='Identifier of the job this result belongs to' - ) - action_run_id: Optional[str] = Field( - None, description='Identifier of the run this result belongs to' - ) - author: Optional[str] = Field(None, description='The author of the commit') - avg_vram: Optional[int] = Field( - None, description='The average VRAM used by the job' - ) - branch_name: Optional[str] = Field( - None, description='Name of the relevant git branch' - ) - comfy_run_flags: Optional[str] = Field( - None, description='The comfy run flags. E.g. `--low-vram`' - ) - commit_hash: Optional[str] = Field(None, description='The hash of the commit') - commit_id: Optional[str] = Field(None, description='The ID of the commit') - commit_message: Optional[str] = Field(None, description='The message of the commit') - commit_time: Optional[int] = Field( - None, description='The Unix timestamp when the commit was made' - ) - cuda_version: Optional[str] = Field(None, description='CUDA version used') - end_time: Optional[int] = Field( - None, description='The end time of the job as a Unix timestamp.' - ) - git_repo: Optional[str] = Field(None, description='The repository name') - id: Optional[UUID] = Field(None, description='Unique identifier for the job result') - job_trigger_user: Optional[str] = Field( - None, description='The user who triggered the job.' - ) - machine_stats: Optional[MachineStats] = None - operating_system: Optional[str] = Field(None, description='Operating system used') - peak_vram: Optional[int] = Field(None, description='The peak VRAM used by the job') - pr_number: Optional[str] = Field(None, description='The pull request number') - python_version: Optional[str] = Field(None, description='PyTorch version used') - pytorch_version: Optional[str] = Field(None, description='PyTorch version used') - start_time: Optional[int] = Field( - None, description='The start time of the job as a Unix timestamp.' - ) - status: Optional[WorkflowRunStatus] = None - storage_file: Optional[StorageFile] = None - workflow_name: Optional[str] = Field(None, description='Name of the workflow') - - -class KlingAccountError(KlingErrorResponse): - code: Optional[Code] = Field( - None, - description='- 1100: Account exception\n- 1101: Account in arrears (postpaid scenario)\n- 1102: Resource pack depleted or expired (prepaid scenario)\n- 1103: Unauthorized access to requested resource\n', - ) - - -class KlingAuthenticationError(KlingErrorResponse): - code: Optional[Code1] = Field( - None, - description='- 1000: Authentication failed\n- 1001: Authorization is empty\n- 1002: Authorization is invalid\n- 1003: Authorization is not yet valid\n- 1004: Authorization has expired\n', - ) - - -class LumaGenerationRequest(BaseModel): - aspect_ratio: Optional[LumaAspectRatio] = '16:9' - callback_url: Optional[AnyUrl] = Field( - None, - description='The callback URL of the generation, a POST request with Generation object will be sent to the callback URL when the generation is dreaming, completed, or failed', - ) - duration: Optional[LumaVideoModelOutputDuration] = None - generation_type: Optional[GenerationType1] = 'video' - keyframes: Optional[LumaKeyframes] = None - loop: Optional[bool] = Field(None, description='Whether to loop the video') - model: Optional[LumaVideoModel] = 'ray-1-6' - prompt: Optional[str] = Field(None, description='The prompt of the generation') - resolution: Optional[LumaVideoModelOutputResolution] = None - - -class CharacterRef(BaseModel): - identity0: Optional[LumaImageIdentity] = None - - -class LumaImageGenerationRequest(BaseModel): - aspect_ratio: Optional[LumaAspectRatio] = '16:9' - callback_url: Optional[AnyUrl] = Field( - None, description='The callback URL for the generation' - ) - character_ref: Optional[CharacterRef] = None - generation_type: Optional[GenerationType2] = 'image' - image_ref: Optional[List[LumaImageRef]] = None - model: Optional[LumaImageModel] = 'photon-1' - modify_image_ref: Optional[LumaModifyImageRef] = None - prompt: Optional[str] = Field(None, description='The prompt of the generation') - style_ref: Optional[List[LumaImageRef]] = None - - -class LumaUpscaleVideoGenerationRequest(BaseModel): - callback_url: Optional[AnyUrl] = Field( - None, description='The callback URL for the upscale' - ) - generation_type: Optional[GenerationType3] = 'upscale_video' - resolution: Optional[LumaVideoModelOutputResolution] = None - - -class NodeVersion(BaseModel): - changelog: Optional[str] = Field( - None, description='Summary of changes made in this version' - ) - comfy_node_extract_status: Optional[str] = Field( - None, description='The status of comfy node extraction process.' - ) - createdAt: Optional[datetime] = Field( - None, description='The date and time the version was created.' - ) - dependencies: Optional[List[str]] = Field( - None, description='A list of pip dependencies required by the node.' - ) - deprecated: Optional[bool] = Field( - None, description='Indicates if this version is deprecated.' - ) - downloadUrl: Optional[str] = Field( - None, description='[Output Only] URL to download this version of the node' - ) - id: Optional[str] = None - node_id: Optional[str] = Field( - None, description='The unique identifier of the node.' - ) - status: Optional[NodeVersionStatus] = None - status_reason: Optional[str] = Field( - None, description='The reason for the status change.' - ) - version: Optional[str] = Field( - None, - description='The version identifier, following semantic versioning. Must be unique for the node.', - ) - - -class PublisherMember(BaseModel): - id: Optional[str] = Field( - None, description='The unique identifier for the publisher member.' - ) - role: Optional[str] = Field( - None, description='The role of the user in the publisher.' - ) - user: Optional[PublisherUser] = None - - -class StripeCharge(BaseModel): - amount: Optional[int] = None - amount_captured: Optional[int] = None - amount_refunded: Optional[int] = None - application: Optional[str] = None - application_fee: Optional[str] = None - application_fee_amount: Optional[int] = None - balance_transaction: Optional[str] = None - billing_details: Optional[StripeBillingDetails] = None - calculated_statement_descriptor: Optional[str] = None - captured: Optional[bool] = None - created: Optional[int] = None - currency: Optional[str] = None - customer: Optional[str] = None - description: Optional[str] = None - destination: Optional[Any] = None - dispute: Optional[Any] = None - disputed: Optional[bool] = None - failure_balance_transaction: Optional[Any] = None - failure_code: Optional[Any] = None - failure_message: Optional[Any] = None - fraud_details: Optional[Dict[str, Any]] = None - id: Optional[str] = None - invoice: Optional[Any] = None - livemode: Optional[bool] = None - metadata: Optional[Dict[str, Any]] = None - object: Optional[Object] = None - on_behalf_of: Optional[Any] = None - order: Optional[Any] = None - outcome: Optional[StripeOutcome] = None - paid: Optional[bool] = None - payment_intent: Optional[str] = None - payment_method: Optional[str] = None - payment_method_details: Optional[StripePaymentMethodDetails] = None - radar_options: Optional[Dict[str, Any]] = None - receipt_email: Optional[str] = None - receipt_number: Optional[str] = None - receipt_url: Optional[str] = None - refunded: Optional[bool] = None - refunds: Optional[StripeRefundList] = None - review: Optional[Any] = None - shipping: Optional[StripeShipping] = None - source: Optional[Any] = None - source_transfer: Optional[Any] = None - statement_descriptor: Optional[Any] = None - statement_descriptor_suffix: Optional[Any] = None - status: Optional[str] = None - transfer_data: Optional[Any] = None - transfer_group: Optional[Any] = None - - -class StripeChargeList(BaseModel): - data: Optional[List[StripeCharge]] = None - has_more: Optional[bool] = None - object: Optional[str] = None - total_count: Optional[int] = None - url: Optional[str] = None - - -class StripePaymentIntent(BaseModel): - amount: Optional[int] = None - amount_capturable: Optional[int] = None - amount_details: Optional[StripeAmountDetails] = None - amount_received: Optional[int] = None - application: Optional[str] = None - application_fee_amount: Optional[int] = None - automatic_payment_methods: Optional[Any] = None - canceled_at: Optional[int] = None - cancellation_reason: Optional[str] = None - capture_method: Optional[str] = None - charges: Optional[StripeChargeList] = None - client_secret: Optional[str] = None - confirmation_method: Optional[str] = None - created: Optional[int] = None - currency: Optional[str] = None - customer: Optional[str] = None - description: Optional[str] = None - id: Optional[str] = None - invoice: Optional[str] = None - last_payment_error: Optional[Any] = None - latest_charge: Optional[str] = None - livemode: Optional[bool] = None - metadata: Optional[Dict[str, Any]] = None - next_action: Optional[Any] = None - object: Optional[Object2] = None - on_behalf_of: Optional[Any] = None - payment_method: Optional[str] = None - payment_method_configuration_details: Optional[Any] = None - payment_method_options: Optional[StripePaymentMethodOptions] = None - payment_method_types: Optional[List[str]] = None - processing: Optional[Any] = None - receipt_email: Optional[str] = None - review: Optional[Any] = None - setup_future_usage: Optional[Any] = None - shipping: Optional[StripeShipping] = None - source: Optional[Any] = None - statement_descriptor: Optional[Any] = None - statement_descriptor_suffix: Optional[Any] = None - status: Optional[str] = None - transfer_data: Optional[Any] = None - transfer_group: Optional[Any] = None - - -class LumaGeneration(BaseModel): - assets: Optional[LumaAssets] = None - created_at: Optional[datetime] = Field( - None, description='The date and time when the generation was created' - ) - failure_reason: Optional[str] = Field( - None, description='The reason for the state of the generation' - ) - generation_type: Optional[LumaGenerationType] = None - id: Optional[UUID] = Field(None, description='The ID of the generation') - model: Optional[str] = Field(None, description='The model used for the generation') - request: Optional[ - Union[ - LumaGenerationRequest, - LumaImageGenerationRequest, - LumaUpscaleVideoGenerationRequest, - LumaAudioGenerationRequest, - ] - ] = Field(None, description='The request of the generation') - state: Optional[LumaState] = None - - -class Publisher(BaseModel): - createdAt: Optional[datetime] = Field( - None, description='The date and time the publisher was created.' - ) - description: Optional[str] = None - id: Optional[str] = Field( - None, - description="The unique identifier for the publisher. It's akin to a username. Should be lowercase.", - ) - logo: Optional[str] = Field(None, description="URL to the publisher's logo.") - members: Optional[List[PublisherMember]] = Field( - None, description='A list of members in the publisher.' - ) - name: Optional[str] = None - source_code_repo: Optional[str] = None - status: Optional[PublisherStatus] = None - support: Optional[str] = None - website: Optional[str] = None - - -class Data8(BaseModel): - object: Optional[StripePaymentIntent] = None - - -class StripeEvent(BaseModel): - api_version: Optional[str] = None - created: Optional[int] = None - data: Data8 - id: str - livemode: Optional[bool] = None - object: Object1 - pending_webhooks: Optional[int] = None - request: Optional[StripeRequestInfo] = None - type: Type7 - - -class Node(BaseModel): - author: Optional[str] = None - category: Optional[str] = Field(None, description='The category of the node.') - description: Optional[str] = None - downloads: Optional[int] = Field( - None, description='The number of downloads of the node.' - ) - icon: Optional[str] = Field(None, description="URL to the node's icon.") - id: Optional[str] = Field(None, description='The unique identifier of the node.') - latest_version: Optional[NodeVersion] = None - license: Optional[str] = Field( - None, description="The path to the LICENSE file in the node's repository." - ) - name: Optional[str] = Field(None, description='The display name of the node.') - publisher: Optional[Publisher] = None - rating: Optional[float] = Field(None, description='The average rating of the node.') - repository: Optional[str] = Field(None, description="URL to the node's repository.") - status: Optional[NodeStatus] = None - status_detail: Optional[str] = Field( - None, description='The status detail of the node.' - ) - tags: Optional[List[str]] = None - translations: Optional[Dict[str, Dict[str, Any]]] = None diff --git a/comfy_api_nodes/nodes_api.py b/comfy_api_nodes/nodes_api.py deleted file mode 100644 index b8a361470..000000000 --- a/comfy_api_nodes/nodes_api.py +++ /dev/null @@ -1,307 +0,0 @@ -import io -from inspect import cleandoc - -from comfy.comfy_types.node_typing import IO, ComfyNodeABC, InputTypeDict -from comfy_api_nodes.apis import ( - IdeogramGenerateRequest, - IdeogramGenerateResponse, - ImageRequest, - OpenAIImageGenerationRequest, - OpenAIImageGenerationResponse -) -from comfy_api_nodes.apis.client import ApiEndpoint, HttpMethod, SynchronousOperation - - -class IdeogramTextToImage(ComfyNodeABC): - """ - Generates images synchronously based on a given prompt and optional parameters. - - Images links are available for a limited period of time; if you would like to keep the image, you must download it. - """ - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(cls) -> InputTypeDict: - """ - Return a dictionary which contains config for all input fields. - Some types (string): "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT". - Input types "INT", "STRING" or "FLOAT" are special values for fields on the node. - The type can be a list for selection. - - Returns: `dict`: - - Key input_fields_group (`string`): Can be either required, hidden or optional. A node class must have property `required` - - Value input_fields (`dict`): Contains input fields config: - * Key field_name (`string`): Name of a entry-point method's argument - * Value field_config (`tuple`): - + First value is a string indicate the type of field or a list for selection. - + Secound value is a config for type "INT", "STRING" or "FLOAT". - """ - return { - "required": { - "prompt": (IO.STRING, { - "multiline": True, - "default": "", - "tooltip": "Prompt for the image generation", - }), - "model": (IO.COMBO, { "options": ["V_2", "V_2_TURBO", "V_1", "V_1_TURBO"], "default": "V_2", "tooltip": "Model to use for image generation"}), - }, - "optional": { - "aspect_ratio": (IO.COMBO, { "options": ["ASPECT_1_1", "ASPECT_4_3", "ASPECT_3_4", "ASPECT_16_9", "ASPECT_9_16", "ASPECT_2_1", "ASPECT_1_2", "ASPECT_3_2", "ASPECT_2_3", "ASPECT_4_5", "ASPECT_5_4"], "default": "ASPECT_1_1", "tooltip": "The aspect ratio for image generation. Cannot be used with resolution" - }), - "resolution": (IO.COMBO, { "options": ["1024x1024", "1024x1792", "1792x1024"], - "default": "1024x1024", - "tooltip": "The resolution for image generation (V2 only). Cannot be used with aspect_ratio" - }), - "magic_prompt_option": (IO.COMBO, { "options": ["AUTO", "ON", "OFF"], - "default": "AUTO", - "tooltip": "Determine if MagicPrompt should be used in generation" - }), - "seed": (IO.INT, { - "default": 0, - "min": 0, - "max": 2147483647, - "step": 1, - "display": "number" - }), - "style_type": (IO.COMBO, { "options": ["NONE", "ANIME", "CINEMATIC", "CREATIVE", "DIGITAL_ART", "PHOTOGRAPHIC"], - "default": "NONE", - "tooltip": "Style type for generation (V2+ only)" - }), - "negative_prompt": (IO.STRING, { - "multiline": True, - "default": "", - "tooltip": "Description of what to exclude from the image (V1/V2 only)" - }), - "num_images": (IO.INT, { - "default": 1, - "min": 1, - "max": 8, - "step": 1, - "display": "number" - }), - "color_palette": (IO.STRING, { - "multiline": False, - "default": "", - "tooltip": "Color palette preset name or hex colors with weights (V2/V2_TURBO only)" - }), - }, - "hidden": { - "auth_token": "AUTH_TOKEN_COMFY_ORG" - } - } - - RETURN_TYPES = (IO.IMAGE,) - DESCRIPTION = cleandoc(__doc__ or "") # Handle potential None value - FUNCTION = "api_call" - API_NODE = True - CATEGORY = "Example" - - def api_call(self, prompt, model, aspect_ratio=None, resolution=None, - magic_prompt_option="AUTO", seed=0, style_type="NONE", - negative_prompt="", num_images=1, color_palette="", auth_token=None): - - import numpy as np - import requests - import torch - from PIL import Image - - operation = SynchronousOperation( - endpoint=ApiEndpoint( - path="/proxy/ideogram/generate", - method=HttpMethod.POST, - request_model=IdeogramGenerateRequest, - response_model=IdeogramGenerateResponse - ), - request=IdeogramGenerateRequest( - image_request=ImageRequest( - prompt=prompt, - model=model, - num_images=num_images, - seed=seed, - aspect_ratio=aspect_ratio if aspect_ratio != "ASPECT_1_1" else None, - resolution=resolution if resolution != "1024x1024" else None, - magic_prompt_option=magic_prompt_option if magic_prompt_option != "AUTO" else None, - style_type=style_type if style_type != "NONE" else None, - negative_prompt=negative_prompt if negative_prompt else None, - color_palette=None - ) - ), - auth_token=auth_token - ) - - response = operation.execute() - - if not response.data or len(response.data) == 0: - raise Exception("No images were generated in the response") - image_url = response.data[0].url - - if not image_url: - raise Exception("No image URL was generated in the response") - img_response = requests.get(image_url) - if img_response.status_code != 200: - raise Exception("Failed to download the image") - - img = Image.open(io.BytesIO(img_response.content)) - img = img.convert("RGB") # Ensure RGB format - - # Convert to numpy array, normalize to float32 between 0 and 1 - img_array = np.array(img).astype(np.float32) / 255.0 - - # Convert to torch tensor and add batch dimension - img_tensor = torch.from_numpy(img_array)[None,] - - return (img_tensor,) - - """ - The node will always be re executed if any of the inputs change but - this method can be used to force the node to execute again even when the inputs don't change. - You can make this node return a number or a string. This value will be compared to the one returned the last time the node was - executed, if it is different the node will be executed again. - This method is used in the core repo for the LoadImage node where they return the image hash as a string, if the image hash - changes between executions the LoadImage node is executed again. - """ - #@classmethod - #def IS_CHANGED(s, image, string_field, int_field, float_field, print_to_screen): - # return "" - -class OpenAITextToImage(ComfyNodeABC): - """ - Generates images synchronously via OpenAI's DALL·E 3 endpoint. - - Uses the proxy at /proxy/dalle-3/generate. Returned URLs are short‑lived, - so download or cache results if you need to keep them. - """ - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(cls) -> InputTypeDict: - return { - "required": { - "prompt": (IO.STRING, { - "multiline": True, - "default": "", - "tooltip": "Text prompt for DALL·E", - }), - # TODO: add NEW MODEL - "model": (IO.COMBO, { - "options": ["dall-e-3", "dall-e-2"], - "default": "dall-e-3", - "tooltip": "OpenAI model name", - }), - }, - "optional": { - "n": (IO.INT, { - "default": 1, - "min": 1, - "max": 8, - "step": 1, - "display": "number", - "tooltip": "How many images to generate", - }), - "size": (IO.COMBO, { - "options": ["256x256", "512x512", "1024x1792", "1792x1024", "1024x1024", "1536x1024", "1024x1536", "auto"], - "default": "auto", - "tooltip": "Image size", - }), - "seed": (IO.INT, { - "default": 0, - "min": 0, - "max": 2**31-1, - "step": 1, - "display": "number", - "tooltip": "Optional random seed", - }), - }, - "hidden": { - "auth_token": "AUTH_TOKEN_COMFY_ORG" - } - } - - RETURN_TYPES = (IO.IMAGE,) - FUNCTION = "api_call" - CATEGORY = "Example" - DESCRIPTION = cleandoc(__doc__ or "") - API_NODE = True - - def api_call(self, prompt, model, n=1, size="1024x1024", seed=0, auth_token=None): - # Validate size based on model - if model == "dall-e-2": - if size == "auto": - size = "1024x1024" - valid_sizes = ["256x256", "512x512", "1024x1024"] - if size not in valid_sizes: - raise ValueError(f"Size {size} not valid for dall-e-2. Must be one of: {', '.join(valid_sizes)}") - elif model == "dall-e-3": - if size == "auto": - size = "1024x1024" - valid_sizes = ["1024x1024", "1792x1024", "1024x1792"] - if size not in valid_sizes: - raise ValueError(f"Size {size} not valid for dall-e-3. Must be one of: {', '.join(valid_sizes)}") - # TODO: add NEW MODEL - - - - import numpy as np - import torch - from PIL import Image - import requests - - # build the operation - operation = SynchronousOperation( - endpoint=ApiEndpoint( - path="/proxy/openai/images/generations", - method=HttpMethod.POST, - request_model=OpenAIImageGenerationRequest, - response_model=OpenAIImageGenerationResponse - ), - request=OpenAIImageGenerationRequest( - model=model, - prompt=prompt, - n=n, - size=size, - seed=seed if seed != 0 else None - ), - auth_token=auth_token - ) - - response = operation.execute() - - # validate raw JSON response - - data = response.data - if not data or len(data) == 0: - raise Exception("No images returned from OpenAI endpoint") - - # Get base64 image data - image_url = data[0].url - if not image_url: - raise Exception("No image URL was generated in the response") - img_response = requests.get(image_url) - if img_response.status_code != 200: - raise Exception("Failed to download the image") - - img = Image.open(io.BytesIO(img_response.content)) - img = img.convert("RGB") # Ensure RGB format - - # Convert to numpy array, normalize to float32 between 0 and 1 - img_array = np.array(img).astype(np.float32) / 255.0 - - # Convert to torch tensor and add batch dimension - img_tensor = torch.from_numpy(img_array)[None,] - - return (img_tensor,) - -# A dictionary that contains all nodes you want to export with their names -# NOTE: names should be globally unique -NODE_CLASS_MAPPINGS = { - "IdeogramTextToImage": IdeogramTextToImage, - "OpenAIDalleTextToImage": OpenAITextToImage, -} - -# A dictionary that contains the friendly/humanly readable titles for the nodes -NODE_DISPLAY_NAME_MAPPINGS = { - "IdeogramTextToImage": "Ideogram Text to Image", - "OpenAIDalleTextToImage": "OpenAI DALL·E 3 Text to Image", -} diff --git a/nodes.py b/nodes.py index 73a62d930..b1ab62aad 100644 --- a/nodes.py +++ b/nodes.py @@ -2260,20 +2260,11 @@ def init_builtin_extra_nodes(): "nodes_fresca.py", ] - api_nodes_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "comfy_api_nodes") - api_nodes_files = [ - "nodes_api.py", - ] - import_failed = [] for node_file in extras_files: if not load_custom_node(os.path.join(extras_dir, node_file), module_parent="comfy_extras"): import_failed.append(node_file) - for node_file in api_nodes_files: - if not load_custom_node(os.path.join(api_nodes_dir, node_file), module_parent="comfy_api_nodes"): - import_failed.append(node_file) - return import_failed