Metadata-Version: 2.1
Name: comfyui-xy
Version: 0.3.0
Summary: A Python client library for interacting with ComfyUI API
Author-email: 小云 <3483421977@qq.com>
Project-URL: Homepage, https://github.com/xy200303/ComfyUiApi
Project-URL: Bug Tracker, https://github.com/xy200303/ComfyUiApi/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Requires-Dist: requests
Requires-Dist: Pillow
Requires-Dist: aiohttp

# ComfyUI API Client

[EN](README.md) | [CN](README_CN.md)

A Python client library for interacting with [ComfyUI](https://github.com/comfyanonymous/ComfyUI) API. 
This library provides a convenient wrapper to queue workflows, upload images/masks, and retrieve generated results (images, videos, audio, etc.) programmatically.

## Features

- **Workflow Management**: Queue workflows easily and wait for results.
- **File Management**: Upload input images and masks directly to ComfyUI.
- **Generic Output Handling**: Automatically handles various output types (Images, Videos/GIFs, Audio).
- **Execution Control**: Interrupt running tasks, check queue status, and view history.
- **Node Info**: Retrieve definitions for ComfyUI nodes.

## Installation

```bash
pip install comfyui_xy
```

## How to Get Workflow JSON

To use this API, you need the workflow in **API Format**, which is different from the standard JSON saved by ComfyUI.

1. **Enable Dev Mode Options**:
   - In ComfyUI web interface, click the **Settings** (gear icon) in the menu.
   - Check the option **"Enable Dev mode Options"**.

2. **Save as API Format**:
   - Once Dev Mode is enabled, you will see a new button in the menu: **"Save (API Format)"**.
   - Click this button to save your workflow as a JSON file (e.g., `workflow_api.json`).
   - Use this JSON file with the `ComfyUiClient`.

## Quick Start

```python
import json
from comfyui_xy import ComfyUiClient

# 1. Initialize Client
client = ComfyUiClient(url="http://127.0.0.1:8188")

# 2. Load Workflow
# You should export the workflow in "API Format" from ComfyUI
with open("workflow_api.json", "r", encoding="utf-8") as f:
    workflow = json.load(f)

# 3. Modify Parameters (Optional)
# e.g., Change the seed in KSampler (Node ID "3")
import random
workflow["3"]["inputs"]["seed"] = random.randint(1, 1000000000)

# 4. Run Workflow
print("Queueing workflow...")
responses = client.process_workflow(workflow)

# 5. Handle Unified Responses
for i, response in enumerate(responses):
    if response.is_file:
        print(f"Received file: {response.filename} ({response.file_type})")
        response.save(f"output_{i}_{response.filename}")

        if response.file_type == "image":
            response.show()
    elif response.is_text:
        print(f"Received text from node {response.node_id}: {response.text}")
```

## Detailed Usage

### 1. Initialization

```python
from comfyui_xy import ComfyUiClient

# Default local server (http://127.0.0.1:8188)
client = ComfyUiClient() 

# Specify URL
client = ComfyUiClient(url="http://127.0.0.1:8188")

# Remote server with HTTPS
client = ComfyUiClient(url="https://my-comfyui-server.com:8188")

# Recommended for production scripts: explicit request timeout and strict errors
client = ComfyUiClient(timeout=30, execution_timeout=300, raise_on_error=True)
```

### 2. Uploading Files

You can upload images or masks before running a workflow. These files are saved in the `input` directory of ComfyUI.

```python
# Upload an image
# Returns the filename used by ComfyUI (useful for setting node inputs)
image_name = client.upload_image("path/to/my_image.png")

# Upload a mask
mask_name = client.upload_mask("path/to/my_mask.png")

# Example: Set the uploaded image in a LoadImage node (e.g., Node ID "10")
workflow["10"]["inputs"]["image"] = image_name
```

### 3. Processing Workflows

The `process_workflow` method is a high-level helper that:
1. Queues the prompt.
2. Waits for execution to finish.
3. Returns unified response objects for downloaded files and discovered text outputs.

```python
responses = client.process_workflow(workflow)
```

**Return Value:**
It returns a list of `ComfyResponse` objects. Each response has `output_type`
set to either `"file"` or `"text"`.

If your workflow produces text instead of files, return the raw ComfyUI
`outputs` data and extract the strings directly:

```python
outputs = client.process_workflow(workflow, return_raw=True)
texts = client.extract_text_outputs(outputs)

print(outputs)
print(texts)
```

If you want explicit response objects from raw outputs, use:

```python
file_responses = client.extract_file_responses(outputs)
text_responses = client.extract_text_responses(outputs)
responses = client.extract_outputs(outputs)
```

If you want failures to be explicit instead of silently returning `None` / `{}` / `[]`,
initialize the client with `raise_on_error=True`. Request failures raise
`ComfyUiError`, `ComfyUiHttpError`, or `ComfyUiTimeoutError`.

### 4. Handling Responses (`ComfyResponse`)

The `ComfyResponse` object wraps the raw data returned by ComfyUI.

- **Attributes**:
  - `output_type`: `"file"` or `"text"`.
  - `data`: Raw bytes of the file for file responses.
  - `text`: Extracted text for text responses.
  - `filename`: Original filename on server for file responses.
  - `node_id`: Source node ID in ComfyUI outputs.
  - `output_name`: Output field name such as `images` or `text`.
  - `file_type`: Type of file (e.g., `'image'`, `'video'`, `'audio'`, `'text'`).
  - `image`: A `PIL.Image` object (if the response is a valid image file).

- **Methods**:
  - `save(path=None)`: Save file bytes or text content to disk.
  - `show()`: Opens the image in the default viewer (only for images).

### 5. Advanced Controls

**Interrupt Execution:**
```python
client.interrupt()
```

**Get System Status:**
```python
# Get Queue Status (Pending/Running tasks)
queue_info = client.get_queue()

# Get Full History
history = client.get_history_all()

# Get Node Information
node_info = client.get_object_info("KSampler")
```

## Async Support

You can use `AsyncComfyUiClient` for asynchronous operations using `aiohttp`.

```python
import asyncio
from comfyui_xy import AsyncComfyUiClient

async def main():
    async with AsyncComfyUiClient(url="http://127.0.0.1:8188") as client:
        # Most methods are awaitable
        results = await client.process_workflow(workflow)

if __name__ == "__main__":
    asyncio.run(main())
```

## Examples

Check the [examples/](examples/) directory for more complete scripts:
- `basic_workflow.py`: Simple Text-to-Image generation.
- `image_to_image.py`: Uploading an image and processing it.
- `advanced_control.py`: Inspecting queue and system info.

## Changelog

### 0.3.0

- Added unified `ComfyResponse` outputs. `process_workflow()` now returns both file and text responses by default.
- Kept `return_raw=True` support for callers that need the original ComfyUI `outputs` structure.
- Added `extract_file_responses()`, `extract_text_responses()`, `extract_outputs()`, and `extract_text_outputs()` helpers for explicit post-processing.
- Added request timeout, workflow execution timeout, and strict error mode via `raise_on_error=True`.
- Added `ComfyUiError`, `ComfyUiHttpError`, and `ComfyUiTimeoutError`.
- Added sync and async test coverage for raw outputs, unified responses, HTTP errors, and timeouts.

**Compatibility note:**
- Older code that assumed every item returned by `process_workflow()` was a file should now check `response.is_file` before calling file-specific logic.

## License

MIT
