comfyui-autograph 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- comfyui_autograph-2.0.0/LICENSE +21 -0
- comfyui_autograph-2.0.0/PKG-INFO +403 -0
- comfyui_autograph-2.0.0/README.md +385 -0
- comfyui_autograph-2.0.0/autograph/__init__.py +78 -0
- comfyui_autograph-2.0.0/autograph/__main__.py +6 -0
- comfyui_autograph-2.0.0/autograph/api.py +143 -0
- comfyui_autograph-2.0.0/autograph/cli.py +110 -0
- comfyui_autograph-2.0.0/autograph/comfyproc.py +201 -0
- comfyui_autograph-2.0.0/autograph/connection.py +280 -0
- comfyui_autograph-2.0.0/autograph/convert.py +2048 -0
- comfyui_autograph-2.0.0/autograph/dag.py +375 -0
- comfyui_autograph-2.0.0/autograph/defaults.py +89 -0
- comfyui_autograph-2.0.0/autograph/flowtree.py +3246 -0
- comfyui_autograph-2.0.0/autograph/inprocess.py +973 -0
- comfyui_autograph-2.0.0/autograph/map.py +463 -0
- comfyui_autograph-2.0.0/autograph/model_layer.py +46 -0
- comfyui_autograph-2.0.0/autograph/models.py +2461 -0
- comfyui_autograph-2.0.0/autograph/net.py +75 -0
- comfyui_autograph-2.0.0/autograph/origin.py +40 -0
- comfyui_autograph-2.0.0/autograph/pngmeta.py +107 -0
- comfyui_autograph-2.0.0/autograph/py.typed +0 -0
- comfyui_autograph-2.0.0/autograph/results.py +1399 -0
- comfyui_autograph-2.0.0/autograph/version.py +1 -0
- comfyui_autograph-2.0.0/autograph/ws.py +778 -0
- comfyui_autograph-2.0.0/comfyui_autograph.egg-info/PKG-INFO +403 -0
- comfyui_autograph-2.0.0/comfyui_autograph.egg-info/SOURCES.txt +30 -0
- comfyui_autograph-2.0.0/comfyui_autograph.egg-info/dependency_links.txt +1 -0
- comfyui_autograph-2.0.0/comfyui_autograph.egg-info/entry_points.txt +2 -0
- comfyui_autograph-2.0.0/comfyui_autograph.egg-info/requires.txt +3 -0
- comfyui_autograph-2.0.0/comfyui_autograph.egg-info/top_level.txt +2 -0
- comfyui_autograph-2.0.0/pyproject.toml +54 -0
- comfyui_autograph-2.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 chris
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: comfyui-autograph
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Pure Python automation for ComfyUI: convert workflows, submit jobs, fetch images—no GUI required
|
|
5
|
+
Author: Chris Reid
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/chrisdreid/comfyui-autograph
|
|
8
|
+
Project-URL: Documentation, https://github.com/chrisdreid/comfyui-autograph#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/chrisdreid/comfyui-autograph
|
|
10
|
+
Project-URL: Issues, https://github.com/chrisdreid/comfyui-autograph/issues
|
|
11
|
+
Keywords: comfyui,automation,workflow,workflow.json,workflow-api,workflow-api.json,stable-diffusion,image-generation,nodes,renderables,flow,apiflow,pipeline,ml,ai,api
|
|
12
|
+
Requires-Python: >=3.7
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Provides-Extra: pillow
|
|
16
|
+
Requires-Dist: pillow; extra == "pillow"
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
<!-- Keep version below in sync with autograph/version.py -->
|
|
20
|
+
```text
|
|
21
|
+
$$\ $$\
|
|
22
|
+
$$ | $$ |
|
|
23
|
+
$$$$$$\ $$\ $$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$$$$\
|
|
24
|
+
\____$$\ $$ | $$ |\_$$ _| $$ __$$\ $$ __$$\ $$ __$$\ \____$$\ $$ __$$\ $$ __$$\
|
|
25
|
+
$$$$$$$ |$$ | $$ | $$ | $$ / $$ |$$ / $$ |$$ | \__|$$$$$$$ |$$ / $$ |$$ | $$ |
|
|
26
|
+
$$ __$$ |$$ | $$ | $$ |$$\ $$ | $$ |$$ | $$ |$$ | $$ __$$ |$$ | $$ |$$ | $$ |
|
|
27
|
+
\$$$$$$$ |\$$$$$$ | \$$$$ |\$$$$$$ |\$$$$$$$ |$$ | \$$$$$$$ |$$$$$$$ |$$ | $$ |
|
|
28
|
+
\_______| \______/ \____/ \______/ \____$$ |\__| \_______|$$ ____/ \__| \__|
|
|
29
|
+
$$\ $$ | $$ |
|
|
30
|
+
\$$$$$$ | $$ |
|
|
31
|
+
\______/ \__|
|
|
32
|
+
ComfyUI version: 2.0.0
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/comfyui-autograph/)
|
|
36
|
+
[](https://pypi.org/project/comfyui-autograph/)
|
|
37
|
+
[](https://github.com/chrisdreid/comfyui-autograph/blob/main/LICENSE)
|
|
38
|
+
[](https://github.com/chrisdreid/comfyui-autograph)
|
|
39
|
+
[](https://github.com/chrisdreid/comfyui-autograph/issues)
|
|
40
|
+
[](https://pypi.org/project/comfyui-autograph/)
|
|
41
|
+
|
|
42
|
+
```mermaid
|
|
43
|
+
flowchart LR
|
|
44
|
+
workflowJson["workflow.json"] --> autograph["autograph"]
|
|
45
|
+
--> apiFlow[workflow-api.json]
|
|
46
|
+
```
|
|
47
|
+
---
|
|
48
|
+
# Imagine...
|
|
49
|
+
### What if you could `load, edit, and submit` ComfyUI workflows without ever exporting an API workflow from the GUI?
|
|
50
|
+
|
|
51
|
+
### What if you could `batch-convert and patch workflows offline` No running ComfyUI instance required?
|
|
52
|
+
|
|
53
|
+
### What if you could attach studio `metadata` to your workflow and have it carry through the entire production lifecycle?
|
|
54
|
+
|
|
55
|
+
### What if you could `render` comfyui node workflows with all of the above features, `without ever launching the comfyui server`?
|
|
56
|
+
|
|
57
|
+
- # Let me introduce `comfyui-autograph`
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
# autograph
|
|
61
|
+
|
|
62
|
+
Skip the GUI. `autograph` handles the backend so you can automate/pipeline your ComfyUI renderables with full control through the entire conversion and submission process.
|
|
63
|
+
`autograph` is a small and efficient, pure **Python package** (stdlib-only +extendable) for ComfyUI automation that gives you access to renderable conversion with or without ComfyUI.
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
| Feature | Description |
|
|
68
|
+
|---------|-------------|
|
|
69
|
+
| **Convert workflow.json** | `workflow.json` → renderable API payload, skip the GUI export entirely |
|
|
70
|
+
| **Offline / Online** | Convert without a running ComfyUI server, or fetch live from one |
|
|
71
|
+
| **Submit + Images** | Send to ComfyUI, wait for completion, fetch and save output images |
|
|
72
|
+
| **Progress** | Hook into WebSocket render events for real-time progress control |
|
|
73
|
+
| **Edit + Introspect** | `api.KSampler.seed = 42`, `.find(...)`, `.choices()`, `.tooltip()`. OOP access to every node and widget |
|
|
74
|
+
| **Metadata** | Attach studio metadata to workflows that carries through the entire production lifecycle |
|
|
75
|
+
| **Serverless Execute** | `.execute()` runs ComfyUI nodes in-process, no HTTP server required |
|
|
76
|
+
| **Map** | Sweep seeds, prompts, paths across nodes for batch pipelines |
|
|
77
|
+
| **Save + Load** | `.save()` / `.load()` on Flow, ApiFlow, and NodeInfo for simple serialization of any object |
|
|
78
|
+
| **Extract** | Load workflows directly from ComfyUI PNG outputs (embedded metadata) |
|
|
79
|
+
| **Stdlib-only** | Zero dependencies by default; optional Pillow, ImageMagick, ffmpeg |
|
|
80
|
+
| **Subgraphs** | Flattens nested `definitions.subgraphs` into a normal API payload |
|
|
81
|
+
|
|
82
|
+
## Requirements
|
|
83
|
+
|
|
84
|
+
- Python 3.7+ (dict insertion order preserved)
|
|
85
|
+
- ComfyUI server (optional, for API mode)
|
|
86
|
+
- No additional Python packages required
|
|
87
|
+
|
|
88
|
+
## Tested ComfyUI Versions:
|
|
89
|
+
- ComfyUI `0.8.2`
|
|
90
|
+
- ComfyUI_frontend `v1.35.9`
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
## The Two `ComfyUI Formats` you should know about
|
|
94
|
+
|
|
95
|
+
ComfyUI uses two JSON formats:
|
|
96
|
+
|
|
97
|
+
| Format | File | Description |
|
|
98
|
+
|--------|------|-------------|
|
|
99
|
+
| **Workspace** | `workflow.json` | The UI-editable graph with node positions, colors, widgets. What you save from ComfyUI. |
|
|
100
|
+
| **API Payload** | `workflow-api.json` | The renderable blueprint—just nodes + inputs, ready for `POST /prompt`. This is what `ApiFlow` represents. |
|
|
101
|
+
|
|
102
|
+
**autograph converts Workspace → API Payload** (or loads an existing API Payload directly).
|
|
103
|
+
|
|
104
|
+
```mermaid
|
|
105
|
+
flowchart LR
|
|
106
|
+
workspace["workflow.json (workspace)"] --> convert["autograph"]
|
|
107
|
+
convert --> payload["workflow-api.json (API payload / ApiFlow)"]
|
|
108
|
+
payload --> submit["POST /prompt"]
|
|
109
|
+
submit --> comfy["ComfyUI renders"]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Installation
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install comfyui-autograph
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then use with `python -m autograph ...` or `import autograph` from Python.
|
|
119
|
+
- Optional: set `AUTOGRAPH_COMFYUI_SERVER_URL` once (then `server_url` / `--server-url` become optional):
|
|
120
|
+
- Linux/macOS: `export AUTOGRAPH_COMFYUI_SERVER_URL="http://localhost:8188"`
|
|
121
|
+
- Windows PowerShell: `$env:AUTOGRAPH_COMFYUI_SERVER_URL = "http://localhost:8188"`
|
|
122
|
+
- Windows CMD: `set AUTOGRAPH_COMFYUI_SERVER_URL=http://localhost:8188`
|
|
123
|
+
- Python: `import os; os.environ["AUTOGRAPH_COMFYUI_SERVER_URL"] = "http://localhost:8188"`
|
|
124
|
+
- Optional: set `AUTOGRAPH_NODE_INFO_SOURCE=modules|fetch|server|/path/to/node-info.json` to auto-resolve `node_info`.
|
|
125
|
+
---
|
|
126
|
+
# `autograph` - Quick Start
|
|
127
|
+
|
|
128
|
+
### Get `node-info.json` (optional, one-time)
|
|
129
|
+
|
|
130
|
+
Save `node-info.json` so you can convert offline. You can also convert against a running ComfyUI instance, but for efficiency we recommend pulling a new `node-info.json` per instance (reproducible, no server needed).
|
|
131
|
+
|
|
132
|
+
```mermaid
|
|
133
|
+
flowchart LR
|
|
134
|
+
comfy["ComfyUI server"] --> obj["/object_info"]
|
|
135
|
+
obj --> file["node-info.json"]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
# api — set AUTOGRAPH_COMFYUI_SERVER_URL first (see Installation above)
|
|
140
|
+
from autograph import NodeInfo
|
|
141
|
+
|
|
142
|
+
node_info = NodeInfo('fetch')
|
|
143
|
+
node_info.save('node-info.json')
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# cli
|
|
148
|
+
python -m autograph --download-node-info-path node-info.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- Direct modules (no server): `NodeInfo.from_comfyui_modules()` builds `node_info` from local ComfyUI nodes.
|
|
152
|
+
- Env source (optional): set `AUTOGRAPH_NODE_INFO_SOURCE=modules|fetch|server|/path/to/node-info.json`.
|
|
153
|
+
|
|
154
|
+
- More: [`docs/node-info-and-env.md`](docs/node-info-and-env.md)
|
|
155
|
+
## Convert live (using running ComfyUI)
|
|
156
|
+
|
|
157
|
+
Convert `workflow.json` by fetching `/object_info` from your running ComfyUI server.
|
|
158
|
+
|
|
159
|
+
```mermaid
|
|
160
|
+
flowchart LR
|
|
161
|
+
env["AUTOGRAPH_COMFYUI_SERVER_URL"] --> wf["Flow(...)"]
|
|
162
|
+
wf --> flow["Flow"]
|
|
163
|
+
comfy["ComfyUI server"] --> obj["/object_info"]
|
|
164
|
+
obj --> wf
|
|
165
|
+
```
|
|
166
|
+
If environment variable `AUTOGRAPH_COMFYUI_SERVER_URL` is set, `server_url` becomes optional.
|
|
167
|
+
|
|
168
|
+
If `AUTOGRAPH_NODE_INFO_SOURCE` is set, `Flow(...)` / `ApiFlow(...)` will auto-resolve `node_info` when none is provided.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
# api — use Flow to work with workflow.json natively
|
|
172
|
+
from autograph import Flow
|
|
173
|
+
|
|
174
|
+
flow = Flow("workflow.json") # uses AUTOGRAPH_COMFYUI_SERVER_URL
|
|
175
|
+
flow.save("workflow-out.json") # stays in workspace format
|
|
176
|
+
|
|
177
|
+
# or convert to API payload
|
|
178
|
+
api = flow.convert()
|
|
179
|
+
api.save("workflow-api.json")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
> **Note:** `ApiFlow("workflow.json")` also works and always converts to the API format. `Flow` keeps the workspace format and converts on demand.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# cli
|
|
186
|
+
python -m autograph --input-path workflow.json --output-path workflow-api.json
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
- More: [`docs/convert.md`](docs/convert.md), [`docs/node-info-and-env.md`](docs/node-info-and-env.md)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
## Convert `workflow` to `workflow-api` (offline)
|
|
193
|
+
|
|
194
|
+
Convert using your saved `node-info.json` (no server needed).
|
|
195
|
+
|
|
196
|
+
```mermaid
|
|
197
|
+
flowchart LR
|
|
198
|
+
workflowJson["workflow.json"] --> wf["Flow(...)"]
|
|
199
|
+
objectInfo["node-info.json"] --> wf
|
|
200
|
+
wf --> flow["Flow"]
|
|
201
|
+
flow --> convert["flow.convert()"]
|
|
202
|
+
convert --> apiFlow["ApiFlow"]
|
|
203
|
+
apiFlow --> saveApi["save(workflow-api.json)"]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
# api — Flow-first: load, optionally edit, then convert
|
|
208
|
+
from autograph import Flow
|
|
209
|
+
|
|
210
|
+
flow = Flow("workflow.json", node_info="node-info.json")
|
|
211
|
+
flow.save("workflow-out.json") # save workspace format
|
|
212
|
+
|
|
213
|
+
api = flow.convert() # convert to API payload
|
|
214
|
+
api.save("workflow-api.json") # save API format
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# cli
|
|
219
|
+
# Offline mode (saved node_info)
|
|
220
|
+
python -m autograph --input-path workflow.json --output-path workflow-api.json --node-info-path node-info.json
|
|
221
|
+
|
|
222
|
+
# Short form (flags)
|
|
223
|
+
python -m autograph -i workflow.json -o workflow-api.json -f node-info.json
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- More: [`docs/convert.md`](docs/convert.md)
|
|
227
|
+
|
|
228
|
+
## Build Workflows from Scratch
|
|
229
|
+
|
|
230
|
+
Create and wire ComfyUI workflows entirely from Python — full tab completion, Pythonic dict-like views, and multiple connection syntaxes.
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from autograph import Flow, NodeInfo
|
|
234
|
+
|
|
235
|
+
flow = Flow(node_info="node-info.json")
|
|
236
|
+
|
|
237
|
+
# Add nodes
|
|
238
|
+
ckpt = flow.add_node("CheckpointLoaderSimple")
|
|
239
|
+
pos = flow.add_node("CLIPTextEncode", text="a beautiful landscape")
|
|
240
|
+
neg = flow.add_node("CLIPTextEncode", text="ugly, blurry")
|
|
241
|
+
lat = flow.add_node("EmptyLatentImage", width=1024, height=1024)
|
|
242
|
+
ks = flow.add_node("KSampler", seed=42, steps=20, cfg=7.0)
|
|
243
|
+
vae = flow.add_node("VAEDecode")
|
|
244
|
+
save = flow.add_node("SaveImage", filename_prefix="test")
|
|
245
|
+
|
|
246
|
+
# Wire connections — all equivalent styles:
|
|
247
|
+
ckpt.outputs.MODEL >> ks.inputs.model # explicit push
|
|
248
|
+
ks.inputs.positive << pos # pull (auto-resolve output)
|
|
249
|
+
ckpt.outputs.CLIP >> [pos.inputs.clip, neg.inputs.clip] # fan-out
|
|
250
|
+
ckpt >> vae.vae # shorthand (auto-resolve)
|
|
251
|
+
|
|
252
|
+
# Inspect connections
|
|
253
|
+
ks.inputs # {'model': 'CheckpointLoaderSimple.MODEL', 'positive': None, ...}
|
|
254
|
+
ckpt.outputs # {'MODEL': 'KSampler.model', 'CLIP': '...', 'VAE': None}
|
|
255
|
+
print(ks.inputs.status()) # full ANSI-colored status table
|
|
256
|
+
|
|
257
|
+
# Disconnect
|
|
258
|
+
ks.inputs.model << None # operator
|
|
259
|
+
ckpt.outputs.CLIP.disconnect(pos.inputs.clip) # targeted
|
|
260
|
+
|
|
261
|
+
# Save
|
|
262
|
+
flow.auto_layout()
|
|
263
|
+
flow.save("my-workflow.json")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
- `node.inputs` / `node.outputs` — dict-like views: `[]`, `pop()`, `del`, `keys/values/items`
|
|
267
|
+
- `flow.nodes.KSampler` returns the same `NodeRef` as `flow.add_node()`
|
|
268
|
+
- `.status()` on any view gives a full ANSI-colored connection table
|
|
269
|
+
|
|
270
|
+
## Load from PNG (extract embedded workflow)
|
|
271
|
+
|
|
272
|
+
ComfyUI embeds workflow metadata in PNG outputs. Extract it directly—no external dependencies needed.
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
# api
|
|
276
|
+
from autograph import Flow, ApiFlow
|
|
277
|
+
|
|
278
|
+
# From PNG file
|
|
279
|
+
api_flow = ApiFlow.load("ComfyUI_00001_.png") # extracts API payload
|
|
280
|
+
flow = Flow.load("ComfyUI_00001_.png") # extracts workspace
|
|
281
|
+
|
|
282
|
+
# From bytes (e.g., HTTP upload, database blob)
|
|
283
|
+
with open("output.png", "rb") as f:
|
|
284
|
+
api_flow = ApiFlow.load(f.read())
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
All `.load()` methods accept: `dict`, `bytes`, `str` (JSON or path), `Path`
|
|
288
|
+
|
|
289
|
+
## Submit + images (optional)
|
|
290
|
+
Submit your `ApiFlow` directly to ComfyUI and get images back
|
|
291
|
+
```mermaid
|
|
292
|
+
flowchart LR
|
|
293
|
+
apiFlow["ApiFlow"] ==> submit["submit(wait=True)"]
|
|
294
|
+
submit ==> comfy["ComfyUI server"]
|
|
295
|
+
comfy --> |job handle|apiFlow
|
|
296
|
+
apiFlow ---> |job handle| images["fetch_images().save(...)"]
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
```python
|
|
300
|
+
# api
|
|
301
|
+
from autograph import ApiFlow
|
|
302
|
+
|
|
303
|
+
api = ApiFlow("workflow.json")
|
|
304
|
+
api.saveimage.inputs.filename_prefix='autograph'
|
|
305
|
+
res = api.submit(server_url="http://localhost:8188", wait=True)
|
|
306
|
+
images = res.fetch_images()
|
|
307
|
+
images.save("outputs/frame.###.png")
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
You can also set an output default with env `AUTOGRAPH_OUTPUT_PATH` and then just provide a `filename=` template:
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
# api
|
|
314
|
+
images.save(filename="frame.{src_frame}.png") # or "frame.###.png" for zero-indexed numbering
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# cli
|
|
319
|
+
# Prints prompt_id first, then (if saving) the written file paths. Progress logs go to stderr.
|
|
320
|
+
python -m autograph --submit --input-path workflow.json --server-url http://localhost:8188 \
|
|
321
|
+
--save-images outputs --filepattern "frame.###.png" --index-offset 1001
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
- More: [`docs/submit-and-images.md`](docs/submit-and-images.md), [`docs/progress-events.md`](docs/progress-events.md)
|
|
325
|
+
|
|
326
|
+
## Serverless execute (no ComfyUI HTTP server)
|
|
327
|
+
|
|
328
|
+
If you're running inside a ComfyUI environment (repo + venv), you can run workflows serverlessly:
|
|
329
|
+
|
|
330
|
+
- Details: [`docs/execute.md`](docs/execute.md)
|
|
331
|
+
|
|
332
|
+
## Optional Functionality
|
|
333
|
+
|
|
334
|
+
- **Polymorphic loading** (dict, bytes, JSON string, file path, PNG):
|
|
335
|
+
- all `.load()` methods auto-detect input type: [`docs/load-vs-convert.md`](docs/load-vs-convert.md)
|
|
336
|
+
- extract workflows from ComfyUI PNG outputs (no dependencies)
|
|
337
|
+
- **OOP node access**:
|
|
338
|
+
- `api.KSampler.seed = 42` — attribute-style access by class_type
|
|
339
|
+
- `api.find(class_type="KSampler")[0].seed = 42` — search + then edit (returns NodeProxy objects)
|
|
340
|
+
- `api.KSampler._meta` / `.meta` — access node metadata
|
|
341
|
+
- `api["ksampler/seed"]` — path-style access
|
|
342
|
+
- `api["18:17:3/seed"] = 42` — edit nodes inside flattened subgraph exports (ComfyUI-style path IDs)
|
|
343
|
+
- `flow.nodes.KSampler.type` — explicit via `.nodes` for workspace flows
|
|
344
|
+
- `flow.nodes.find(title="NewSubgraphName")[0].path()` — find renamed subgraph instances; prints a stable path like `18:17:3`
|
|
345
|
+
- `flow.extra.ds.scale` — drill into nested dicts with `DictView`
|
|
346
|
+
- `node.properties.models.url` — single-item list-of-dicts drill via `ListView` (otherwise index first)
|
|
347
|
+
- **Widget-value repr**: `NodeRef`/`NodeSet` display widget values as dicts — `f.nodes.CheckpointLoaderSimple` → `{'nodes.CheckpointLoaderSimple[0]': {'ckpt_name': '...'}}`
|
|
348
|
+
- **Widget introspection**: `.choices()` returns valid combo options, `.tooltip()` shows help text, `.spec()` gives the raw `node_info` spec
|
|
349
|
+
- **Tab completion**: curated `__dir__` on `ApiFlow`, `NodeSet`, `FlowTreeNodesView`, and `WidgetValue` — only shows user-facing attrs
|
|
350
|
+
- **Indexed nodes**: standard Python REPL can't tab-complete `api.KSampler[0].<tab>` — assign to a variable first: `k = api.KSampler[0]` then `k.<tab>`
|
|
351
|
+
- **Mapping** (seeds/paths/prompts):
|
|
352
|
+
- typed callback mapping: [`docs/mapping.md`](docs/mapping.md)
|
|
353
|
+
- declarative string/path mapping: [`docs/map-strings-and-paths.md`](docs/map-strings-and-paths.md)
|
|
354
|
+
- cache-busting repeat runs: [`docs/force-recompute.md`](docs/force-recompute.md)
|
|
355
|
+
- **Filename pattern saving**:
|
|
356
|
+
- `ImagesResult.save("outputs/frame.###.png")`: [`docs/submit-and-images.md`](docs/submit-and-images.md)
|
|
357
|
+
- **Service patterns**:
|
|
358
|
+
- FastAPI integration: [`docs/fastapi.md`](docs/fastapi.md)
|
|
359
|
+
- structured errors: [`docs/error-handling.md`](docs/error-handling.md)
|
|
360
|
+
- **When things break**:
|
|
361
|
+
- troubleshooting: [`docs/troubleshooting.md`](docs/troubleshooting.md)
|
|
362
|
+
- deeper options: [`docs/advanced.md`](docs/advanced.md)
|
|
363
|
+
|
|
364
|
+
## CLI Reference
|
|
365
|
+
|
|
366
|
+
| Argument | Short | Description |
|
|
367
|
+
|----------|-------|-------------|
|
|
368
|
+
| `--input-path` | `-i` | Input workflow JSON file path |
|
|
369
|
+
| `--output-path` | `-o` | Output API format JSON file path |
|
|
370
|
+
| `--server-url` | | ComfyUI server URL (or set `AUTOGRAPH_COMFYUI_SERVER_URL`) |
|
|
371
|
+
| `--node-info-path` | `-f` | Path to saved `node_info.json` file |
|
|
372
|
+
| `--download-node-info-path` | | Download `/object_info` and save to file |
|
|
373
|
+
| `--submit` | | Submit converted API payload to ComfyUI |
|
|
374
|
+
| `--no-wait` | | Submit without waiting for completion (prints `prompt_id` and exits) |
|
|
375
|
+
| `--no-progress` | | Disable progress output during `--submit` when waiting |
|
|
376
|
+
| `--save-images` | | Directory to save fetched images (requires waiting) |
|
|
377
|
+
| `--filepattern` | | Filename pattern used when saving images (default: `frame.###.png`) |
|
|
378
|
+
| `--index-offset` | | Index offset for `#` patterns (default: 0) |
|
|
379
|
+
| `--save-files` | | Directory to save fetched registered files (requires waiting) |
|
|
380
|
+
| `--output-types` | | Comma-separated registered output types when saving files (e.g. `images,files`) |
|
|
381
|
+
|
|
382
|
+
**Note**: The CLI supports submission and saving registered outputs via `--submit` (see [`docs/submit-and-images.md`](docs/submit-and-images.md) and [`docs/progress-events.md`](docs/progress-events.md)).
|
|
383
|
+
|
|
384
|
+
## Contributing
|
|
385
|
+
|
|
386
|
+
This script is designed to be production-ready and maintainable. Key design principles:
|
|
387
|
+
|
|
388
|
+
- **Minimal Dependencies**: Uses only Python standard library
|
|
389
|
+
- **Cross-Platform Compatibility**: Works on Linux, Windows, and macOS
|
|
390
|
+
- **Robust Error Handling**: Graceful degradation and detailed error reporting
|
|
391
|
+
- **Exact Replication**: Matches ComfyUI's internal conversion exactly
|
|
392
|
+
|
|
393
|
+
For development setup, running tests, and code style guidelines, see [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
[`MIT License`](LICENSE)
|
|
398
|
+
|
|
399
|
+
## Related
|
|
400
|
+
|
|
401
|
+
- [ComfyUI](https://github.com/comfyanonymous/ComfyUI) - The main ComfyUI project
|
|
402
|
+
- [ComfyUI API Documentation](https://github.com/comfyanonymous/ComfyUI/wiki/API) - API format specification
|
|
403
|
+
|