flux-pro-cli 2026.4.5.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.
- flux_pro_cli-2026.4.5.0/.env.example +9 -0
- flux_pro_cli-2026.4.5.0/CHANGELOG.md +22 -0
- flux_pro_cli-2026.4.5.0/LICENSE +21 -0
- flux_pro_cli-2026.4.5.0/PKG-INFO +167 -0
- flux_pro_cli-2026.4.5.0/README.md +121 -0
- flux_pro_cli-2026.4.5.0/flux_cli/__init__.py +1 -0
- flux_pro_cli-2026.4.5.0/flux_cli/__main__.py +5 -0
- flux_pro_cli-2026.4.5.0/flux_cli/commands/__init__.py +0 -0
- flux_pro_cli-2026.4.5.0/flux_cli/commands/image.py +165 -0
- flux_pro_cli-2026.4.5.0/flux_cli/commands/info.py +31 -0
- flux_pro_cli-2026.4.5.0/flux_cli/commands/task.py +141 -0
- flux_pro_cli-2026.4.5.0/flux_cli/core/__init__.py +0 -0
- flux_pro_cli-2026.4.5.0/flux_cli/core/client.py +112 -0
- flux_pro_cli-2026.4.5.0/flux_cli/core/config.py +39 -0
- flux_pro_cli-2026.4.5.0/flux_cli/core/exceptions.py +37 -0
- flux_pro_cli-2026.4.5.0/flux_cli/core/output.py +141 -0
- flux_pro_cli-2026.4.5.0/flux_cli/main.py +70 -0
- flux_pro_cli-2026.4.5.0/pyproject.toml +118 -0
- flux_pro_cli-2026.4.5.0/tests/conftest.py +99 -0
- flux_pro_cli-2026.4.5.0/tests/test_client.py +152 -0
- flux_pro_cli-2026.4.5.0/tests/test_commands.py +292 -0
- flux_pro_cli-2026.4.5.0/tests/test_config.py +52 -0
- flux_pro_cli-2026.4.5.0/tests/test_integration.py +62 -0
- flux_pro_cli-2026.4.5.0/tests/test_output.py +129 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# AceDataCloud API Token
|
|
2
|
+
# Get yours at https://platform.acedata.cloud
|
|
3
|
+
ACEDATACLOUD_API_TOKEN=
|
|
4
|
+
|
|
5
|
+
# Optional: Custom API base URL (default: https://api.acedata.cloud)
|
|
6
|
+
# ACEDATACLOUD_API_BASE_URL=https://api.acedata.cloud
|
|
7
|
+
|
|
8
|
+
# Optional: Request timeout in seconds (default: 1800)
|
|
9
|
+
# FLUX_REQUEST_TIMEOUT=1800
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2025-01-21
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Initial release of Flux CLI
|
|
10
|
+
- `generate` command for text-to-image generation
|
|
11
|
+
- `edit` command for image editing with text prompts
|
|
12
|
+
- `task` command for querying task status
|
|
13
|
+
- `tasks` command for batch task queries
|
|
14
|
+
- `wait` command for polling task completion
|
|
15
|
+
- `models` command to list available Flux models
|
|
16
|
+
- `aspect-ratios` command to list available aspect ratios
|
|
17
|
+
- `config` command to show current configuration
|
|
18
|
+
- Support for all Flux models: flux-dev, flux-pro, flux-pro-1.1, flux-pro-1.1-ultra, flux-kontext-pro, flux-kontext-max
|
|
19
|
+
- `--json` flag for machine-readable output on all commands
|
|
20
|
+
- `--token` option and `ACEDATACLOUD_API_TOKEN` env var for authentication
|
|
21
|
+
- Rich terminal formatting for human-readable output
|
|
22
|
+
- Docker support via Dockerfile and docker-compose.yaml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 AceDataCloud
|
|
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,167 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: flux-pro-cli
|
|
3
|
+
Version: 2026.4.5.0
|
|
4
|
+
Summary: CLI tool for Flux AI Image Generation via AceDataCloud API
|
|
5
|
+
Project-URL: Homepage, https://github.com/AceDataCloud/FluxCli
|
|
6
|
+
Project-URL: Repository, https://github.com/AceDataCloud/FluxCli
|
|
7
|
+
Project-URL: Issues, https://github.com/AceDataCloud/FluxCli/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/AceDataCloud/FluxCli/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: AceDataCloud <support@acedata.cloud>
|
|
10
|
+
Maintainer-email: AceDataCloud <support@acedata.cloud>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: acedata,ai,cli,command-line,flux,generation,image
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: click>=8.1.0
|
|
27
|
+
Requires-Dist: httpx>=0.27.0
|
|
28
|
+
Requires-Dist: pydantic>=2.0.0
|
|
29
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Provides-Extra: all
|
|
32
|
+
Requires-Dist: flux-pro-cli[dev,release,test]; extra == 'all'
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pre-commit>=3.7.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
37
|
+
Provides-Extra: release
|
|
38
|
+
Requires-Dist: build>=1.2.0; extra == 'release'
|
|
39
|
+
Requires-Dist: twine>=6.1.0; extra == 'release'
|
|
40
|
+
Provides-Extra: test
|
|
41
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
|
|
42
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
|
|
43
|
+
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
44
|
+
Requires-Dist: respx>=0.21.0; extra == 'test'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# Flux CLI
|
|
48
|
+
|
|
49
|
+
A command-line tool for AI image generation and editing using [Flux](https://blackforestlabs.ai/) through the [AceDataCloud](https://platform.acedata.cloud) platform.
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **Text-to-Image Generation** — Generate images from text prompts with multiple Flux models
|
|
54
|
+
- **Image Editing** — Edit existing images using text descriptions (kontext models)
|
|
55
|
+
- **Task Management** — Query status, batch check, and poll for completion
|
|
56
|
+
- **Multiple Models** — flux-dev, flux-pro, flux-pro-1.1, flux-pro-1.1-ultra, flux-kontext-pro, flux-kontext-max
|
|
57
|
+
- **Rich Output** — Beautiful terminal formatting with `--json` for scripting
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install flux-pro-cli
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Set your API token
|
|
69
|
+
export ACEDATACLOUD_API_TOKEN=your_token_here
|
|
70
|
+
|
|
71
|
+
# Generate an image
|
|
72
|
+
flux generate "A majestic mountain landscape at golden hour, photorealistic"
|
|
73
|
+
|
|
74
|
+
# Generate with a specific model
|
|
75
|
+
flux generate "Cyberpunk city with neon lights" -m flux-pro-1.1
|
|
76
|
+
|
|
77
|
+
# Generate with aspect ratio (ultra/kontext models)
|
|
78
|
+
flux generate "Minimalist logo of a phoenix" -m flux-pro-1.1-ultra -s 16:9
|
|
79
|
+
|
|
80
|
+
# Edit an existing image
|
|
81
|
+
flux edit "Add sunglasses to the person" --image-url https://example.com/photo.jpg
|
|
82
|
+
|
|
83
|
+
# Edit with max context model
|
|
84
|
+
flux edit "Change background to sunset beach" --image-url https://example.com/img.png -m flux-kontext-max
|
|
85
|
+
|
|
86
|
+
# Check task status
|
|
87
|
+
flux task abc123-def456
|
|
88
|
+
|
|
89
|
+
# Wait for task completion
|
|
90
|
+
flux wait abc123 --interval 5 --timeout 300
|
|
91
|
+
|
|
92
|
+
# Batch check multiple tasks
|
|
93
|
+
flux tasks task-1 task-2 task-3
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Commands
|
|
97
|
+
|
|
98
|
+
| Command | Description |
|
|
99
|
+
|---------|-------------|
|
|
100
|
+
| `generate` | Generate an image from a text prompt |
|
|
101
|
+
| `edit` | Edit an existing image with a text prompt |
|
|
102
|
+
| `task` | Query a single task status |
|
|
103
|
+
| `tasks` | Query multiple tasks at once |
|
|
104
|
+
| `wait` | Wait for a task to complete |
|
|
105
|
+
| `models` | List available Flux models |
|
|
106
|
+
| `aspect-ratios` | List available aspect ratios |
|
|
107
|
+
| `config` | Show current configuration |
|
|
108
|
+
|
|
109
|
+
## Models
|
|
110
|
+
|
|
111
|
+
| Model | Type | Size Input | Notes |
|
|
112
|
+
|-------|------|-----------|-------|
|
|
113
|
+
| `flux-dev` | Dev | Pixels | Fast, good balance (default) |
|
|
114
|
+
| `flux-pro` | Pro | Pixels | Higher quality |
|
|
115
|
+
| `flux-pro-1.1` | Pro | Pixels | Better prompt following |
|
|
116
|
+
| `flux-pro-1.1-ultra` | Ultra | Aspect ratio | Highest quality |
|
|
117
|
+
| `flux-kontext-pro` | Kontext | Aspect ratio | Best for editing/style transfer |
|
|
118
|
+
| `flux-kontext-max` | Kontext | Aspect ratio | Max context for complex edits |
|
|
119
|
+
|
|
120
|
+
## JSON Output
|
|
121
|
+
|
|
122
|
+
All commands support `--json` for machine-readable output:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
flux generate "A red car" --json | jq '.task_id'
|
|
126
|
+
flux task abc123 --json | jq '.data[0].image_url'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Configuration
|
|
130
|
+
|
|
131
|
+
| Environment Variable | Description | Default |
|
|
132
|
+
|---------------------|-------------|---------|
|
|
133
|
+
| `ACEDATACLOUD_API_TOKEN` | API authentication token | (required) |
|
|
134
|
+
| `ACEDATACLOUD_API_BASE_URL` | API base URL | `https://api.acedata.cloud` |
|
|
135
|
+
| `FLUX_REQUEST_TIMEOUT` | Request timeout in seconds | `1800` |
|
|
136
|
+
|
|
137
|
+
You can also use a `.env` file or pass `--token` directly.
|
|
138
|
+
|
|
139
|
+
## Docker
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
docker compose run flux-cli generate "A beautiful sunset"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Install with dev dependencies
|
|
149
|
+
pip install -e ".[all]"
|
|
150
|
+
|
|
151
|
+
# Run tests
|
|
152
|
+
pytest
|
|
153
|
+
|
|
154
|
+
# Run linter
|
|
155
|
+
ruff check .
|
|
156
|
+
ruff format --check .
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
162
|
+
|
|
163
|
+
## Links
|
|
164
|
+
|
|
165
|
+
- [AceDataCloud Platform](https://platform.acedata.cloud)
|
|
166
|
+
- [API Documentation](https://docs.acedata.cloud)
|
|
167
|
+
- [Flux by Black Forest Labs](https://blackforestlabs.ai/)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Flux CLI
|
|
2
|
+
|
|
3
|
+
A command-line tool for AI image generation and editing using [Flux](https://blackforestlabs.ai/) through the [AceDataCloud](https://platform.acedata.cloud) platform.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Text-to-Image Generation** — Generate images from text prompts with multiple Flux models
|
|
8
|
+
- **Image Editing** — Edit existing images using text descriptions (kontext models)
|
|
9
|
+
- **Task Management** — Query status, batch check, and poll for completion
|
|
10
|
+
- **Multiple Models** — flux-dev, flux-pro, flux-pro-1.1, flux-pro-1.1-ultra, flux-kontext-pro, flux-kontext-max
|
|
11
|
+
- **Rich Output** — Beautiful terminal formatting with `--json` for scripting
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install flux-pro-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Set your API token
|
|
23
|
+
export ACEDATACLOUD_API_TOKEN=your_token_here
|
|
24
|
+
|
|
25
|
+
# Generate an image
|
|
26
|
+
flux generate "A majestic mountain landscape at golden hour, photorealistic"
|
|
27
|
+
|
|
28
|
+
# Generate with a specific model
|
|
29
|
+
flux generate "Cyberpunk city with neon lights" -m flux-pro-1.1
|
|
30
|
+
|
|
31
|
+
# Generate with aspect ratio (ultra/kontext models)
|
|
32
|
+
flux generate "Minimalist logo of a phoenix" -m flux-pro-1.1-ultra -s 16:9
|
|
33
|
+
|
|
34
|
+
# Edit an existing image
|
|
35
|
+
flux edit "Add sunglasses to the person" --image-url https://example.com/photo.jpg
|
|
36
|
+
|
|
37
|
+
# Edit with max context model
|
|
38
|
+
flux edit "Change background to sunset beach" --image-url https://example.com/img.png -m flux-kontext-max
|
|
39
|
+
|
|
40
|
+
# Check task status
|
|
41
|
+
flux task abc123-def456
|
|
42
|
+
|
|
43
|
+
# Wait for task completion
|
|
44
|
+
flux wait abc123 --interval 5 --timeout 300
|
|
45
|
+
|
|
46
|
+
# Batch check multiple tasks
|
|
47
|
+
flux tasks task-1 task-2 task-3
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Commands
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
|---------|-------------|
|
|
54
|
+
| `generate` | Generate an image from a text prompt |
|
|
55
|
+
| `edit` | Edit an existing image with a text prompt |
|
|
56
|
+
| `task` | Query a single task status |
|
|
57
|
+
| `tasks` | Query multiple tasks at once |
|
|
58
|
+
| `wait` | Wait for a task to complete |
|
|
59
|
+
| `models` | List available Flux models |
|
|
60
|
+
| `aspect-ratios` | List available aspect ratios |
|
|
61
|
+
| `config` | Show current configuration |
|
|
62
|
+
|
|
63
|
+
## Models
|
|
64
|
+
|
|
65
|
+
| Model | Type | Size Input | Notes |
|
|
66
|
+
|-------|------|-----------|-------|
|
|
67
|
+
| `flux-dev` | Dev | Pixels | Fast, good balance (default) |
|
|
68
|
+
| `flux-pro` | Pro | Pixels | Higher quality |
|
|
69
|
+
| `flux-pro-1.1` | Pro | Pixels | Better prompt following |
|
|
70
|
+
| `flux-pro-1.1-ultra` | Ultra | Aspect ratio | Highest quality |
|
|
71
|
+
| `flux-kontext-pro` | Kontext | Aspect ratio | Best for editing/style transfer |
|
|
72
|
+
| `flux-kontext-max` | Kontext | Aspect ratio | Max context for complex edits |
|
|
73
|
+
|
|
74
|
+
## JSON Output
|
|
75
|
+
|
|
76
|
+
All commands support `--json` for machine-readable output:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
flux generate "A red car" --json | jq '.task_id'
|
|
80
|
+
flux task abc123 --json | jq '.data[0].image_url'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
| Environment Variable | Description | Default |
|
|
86
|
+
|---------------------|-------------|---------|
|
|
87
|
+
| `ACEDATACLOUD_API_TOKEN` | API authentication token | (required) |
|
|
88
|
+
| `ACEDATACLOUD_API_BASE_URL` | API base URL | `https://api.acedata.cloud` |
|
|
89
|
+
| `FLUX_REQUEST_TIMEOUT` | Request timeout in seconds | `1800` |
|
|
90
|
+
|
|
91
|
+
You can also use a `.env` file or pass `--token` directly.
|
|
92
|
+
|
|
93
|
+
## Docker
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
docker compose run flux-cli generate "A beautiful sunset"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Install with dev dependencies
|
|
103
|
+
pip install -e ".[all]"
|
|
104
|
+
|
|
105
|
+
# Run tests
|
|
106
|
+
pytest
|
|
107
|
+
|
|
108
|
+
# Run linter
|
|
109
|
+
ruff check .
|
|
110
|
+
ruff format --check .
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
116
|
+
|
|
117
|
+
## Links
|
|
118
|
+
|
|
119
|
+
- [AceDataCloud Platform](https://platform.acedata.cloud)
|
|
120
|
+
- [API Documentation](https://docs.acedata.cloud)
|
|
121
|
+
- [Flux by Black Forest Labs](https://blackforestlabs.ai/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Flux CLI - AI Image Generation via AceDataCloud API."""
|
|
File without changes
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Image generation and editing commands."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from flux_cli.core.client import get_client
|
|
6
|
+
from flux_cli.core.exceptions import FluxError
|
|
7
|
+
from flux_cli.core.output import (
|
|
8
|
+
ASPECT_RATIOS,
|
|
9
|
+
DEFAULT_MODEL,
|
|
10
|
+
FLUX_MODELS,
|
|
11
|
+
print_error,
|
|
12
|
+
print_image_result,
|
|
13
|
+
print_json,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command()
|
|
18
|
+
@click.argument("prompt")
|
|
19
|
+
@click.option(
|
|
20
|
+
"-m",
|
|
21
|
+
"--model",
|
|
22
|
+
type=click.Choice(FLUX_MODELS),
|
|
23
|
+
default=DEFAULT_MODEL,
|
|
24
|
+
help="Flux model to use.",
|
|
25
|
+
)
|
|
26
|
+
@click.option(
|
|
27
|
+
"-s",
|
|
28
|
+
"--size",
|
|
29
|
+
default=None,
|
|
30
|
+
help="Image size: pixels (e.g. 1024x1024) or aspect ratio (e.g. 16:9).",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"-n",
|
|
34
|
+
"--count",
|
|
35
|
+
default=None,
|
|
36
|
+
type=int,
|
|
37
|
+
help="Number of images to generate.",
|
|
38
|
+
)
|
|
39
|
+
@click.option("--callback-url", default=None, help="Webhook callback URL.")
|
|
40
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
41
|
+
@click.pass_context
|
|
42
|
+
def generate(
|
|
43
|
+
ctx: click.Context,
|
|
44
|
+
prompt: str,
|
|
45
|
+
model: str,
|
|
46
|
+
size: str | None,
|
|
47
|
+
count: int | None,
|
|
48
|
+
callback_url: str | None,
|
|
49
|
+
output_json: bool,
|
|
50
|
+
) -> None:
|
|
51
|
+
"""Generate an image from a text prompt.
|
|
52
|
+
|
|
53
|
+
PROMPT is a detailed description of the image to generate.
|
|
54
|
+
|
|
55
|
+
\b
|
|
56
|
+
Examples:
|
|
57
|
+
flux generate "A majestic mountain at golden hour, photorealistic"
|
|
58
|
+
flux generate "Cyberpunk city with neon lights" -m flux-pro-1.1
|
|
59
|
+
flux generate "Minimalist logo of a phoenix" -m flux-pro-1.1-ultra -s 16:9
|
|
60
|
+
"""
|
|
61
|
+
client = get_client(ctx.obj.get("token"))
|
|
62
|
+
try:
|
|
63
|
+
payload: dict[str, object] = {
|
|
64
|
+
"action": "generate",
|
|
65
|
+
"prompt": prompt,
|
|
66
|
+
"model": model,
|
|
67
|
+
"size": size,
|
|
68
|
+
"count": count,
|
|
69
|
+
"callback_url": callback_url,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
result = client.generate_image(**payload) # type: ignore[arg-type]
|
|
73
|
+
if output_json:
|
|
74
|
+
print_json(result)
|
|
75
|
+
else:
|
|
76
|
+
print_image_result(result)
|
|
77
|
+
except FluxError as e:
|
|
78
|
+
print_error(e.message)
|
|
79
|
+
raise SystemExit(1) from e
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@click.command()
|
|
83
|
+
@click.argument("prompt")
|
|
84
|
+
@click.option(
|
|
85
|
+
"--image-url",
|
|
86
|
+
required=True,
|
|
87
|
+
help="URL of the image to edit.",
|
|
88
|
+
)
|
|
89
|
+
@click.option(
|
|
90
|
+
"-m",
|
|
91
|
+
"--model",
|
|
92
|
+
type=click.Choice(FLUX_MODELS),
|
|
93
|
+
default="flux-kontext-pro",
|
|
94
|
+
help="Flux model to use (default: flux-kontext-pro).",
|
|
95
|
+
)
|
|
96
|
+
@click.option(
|
|
97
|
+
"-s",
|
|
98
|
+
"--size",
|
|
99
|
+
default=None,
|
|
100
|
+
help="Output size: pixels or aspect ratio.",
|
|
101
|
+
)
|
|
102
|
+
@click.option("--callback-url", default=None, help="Webhook callback URL.")
|
|
103
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
104
|
+
@click.pass_context
|
|
105
|
+
def edit(
|
|
106
|
+
ctx: click.Context,
|
|
107
|
+
prompt: str,
|
|
108
|
+
image_url: str,
|
|
109
|
+
model: str,
|
|
110
|
+
size: str | None,
|
|
111
|
+
callback_url: str | None,
|
|
112
|
+
output_json: bool,
|
|
113
|
+
) -> None:
|
|
114
|
+
"""Edit an existing image with a text prompt.
|
|
115
|
+
|
|
116
|
+
PROMPT describes the desired changes to the image.
|
|
117
|
+
|
|
118
|
+
\b
|
|
119
|
+
Examples:
|
|
120
|
+
flux edit "Add sunglasses" --image-url https://example.com/photo.jpg
|
|
121
|
+
flux edit "Change background to sunset" --image-url https://example.com/img.png -m flux-kontext-max
|
|
122
|
+
"""
|
|
123
|
+
client = get_client(ctx.obj.get("token"))
|
|
124
|
+
try:
|
|
125
|
+
payload: dict[str, object] = {
|
|
126
|
+
"action": "edit",
|
|
127
|
+
"prompt": prompt,
|
|
128
|
+
"image_url": image_url,
|
|
129
|
+
"model": model,
|
|
130
|
+
"size": size,
|
|
131
|
+
"callback_url": callback_url,
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
result = client.edit_image(**payload) # type: ignore[arg-type]
|
|
135
|
+
if output_json:
|
|
136
|
+
print_json(result)
|
|
137
|
+
else:
|
|
138
|
+
print_image_result(result)
|
|
139
|
+
except FluxError as e:
|
|
140
|
+
print_error(e.message)
|
|
141
|
+
raise SystemExit(1) from e
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@click.command("aspect-ratios")
|
|
145
|
+
def aspect_ratios() -> None:
|
|
146
|
+
"""List available aspect ratios for ultra/kontext models."""
|
|
147
|
+
from rich.table import Table
|
|
148
|
+
|
|
149
|
+
from flux_cli.core.output import console
|
|
150
|
+
|
|
151
|
+
table = Table(title="Available Aspect Ratios")
|
|
152
|
+
table.add_column("Ratio", style="bold cyan")
|
|
153
|
+
table.add_column("Orientation")
|
|
154
|
+
|
|
155
|
+
for ratio in ASPECT_RATIOS:
|
|
156
|
+
w, h = ratio.split(":")
|
|
157
|
+
if int(w) > int(h):
|
|
158
|
+
orientation = "Landscape"
|
|
159
|
+
elif int(w) < int(h):
|
|
160
|
+
orientation = "Portrait"
|
|
161
|
+
else:
|
|
162
|
+
orientation = "Square"
|
|
163
|
+
table.add_row(ratio, orientation)
|
|
164
|
+
|
|
165
|
+
console.print(table)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Info and utility commands."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from flux_cli.core.config import settings
|
|
6
|
+
from flux_cli.core.output import console, print_models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
def models() -> None:
|
|
11
|
+
"""List available Flux models."""
|
|
12
|
+
print_models()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.command()
|
|
16
|
+
def config() -> None:
|
|
17
|
+
"""Show current configuration."""
|
|
18
|
+
from rich.table import Table
|
|
19
|
+
|
|
20
|
+
table = Table(title="Flux CLI Configuration")
|
|
21
|
+
table.add_column("Setting", style="bold cyan")
|
|
22
|
+
table.add_column("Value")
|
|
23
|
+
|
|
24
|
+
table.add_row("API Base URL", settings.api_base_url)
|
|
25
|
+
table.add_row(
|
|
26
|
+
"API Token",
|
|
27
|
+
f"{settings.api_token[:8]}..." if settings.api_token else "[red]Not set[/red]",
|
|
28
|
+
)
|
|
29
|
+
table.add_row("Request Timeout", f"{settings.request_timeout}s")
|
|
30
|
+
|
|
31
|
+
console.print(table)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Task management commands."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from flux_cli.core.client import get_client
|
|
8
|
+
from flux_cli.core.exceptions import FluxError
|
|
9
|
+
from flux_cli.core.output import print_error, print_json, print_success, print_task_result
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.command()
|
|
13
|
+
@click.argument("task_id")
|
|
14
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
15
|
+
@click.pass_context
|
|
16
|
+
def task(
|
|
17
|
+
ctx: click.Context,
|
|
18
|
+
task_id: str,
|
|
19
|
+
output_json: bool,
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Query a single task status.
|
|
22
|
+
|
|
23
|
+
TASK_ID is the task ID returned from generate/edit commands.
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
|
|
27
|
+
flux task abc123-def456
|
|
28
|
+
"""
|
|
29
|
+
client = get_client(ctx.obj.get("token"))
|
|
30
|
+
try:
|
|
31
|
+
result = client.query_task(id=task_id, action="retrieve")
|
|
32
|
+
if output_json:
|
|
33
|
+
print_json(result)
|
|
34
|
+
else:
|
|
35
|
+
print_task_result(result)
|
|
36
|
+
except FluxError as e:
|
|
37
|
+
print_error(e.message)
|
|
38
|
+
raise SystemExit(1) from e
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@click.command("tasks")
|
|
42
|
+
@click.argument("task_ids", nargs=-1, required=True)
|
|
43
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
44
|
+
@click.pass_context
|
|
45
|
+
def tasks_batch(
|
|
46
|
+
ctx: click.Context,
|
|
47
|
+
task_ids: tuple[str, ...],
|
|
48
|
+
output_json: bool,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""Query multiple tasks at once.
|
|
51
|
+
|
|
52
|
+
TASK_IDS are space-separated task IDs.
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
|
|
56
|
+
flux tasks abc123 def456 ghi789
|
|
57
|
+
"""
|
|
58
|
+
client = get_client(ctx.obj.get("token"))
|
|
59
|
+
try:
|
|
60
|
+
result = client.query_task(ids=list(task_ids), action="retrieve_batch")
|
|
61
|
+
if output_json:
|
|
62
|
+
print_json(result)
|
|
63
|
+
else:
|
|
64
|
+
print_task_result(result)
|
|
65
|
+
except FluxError as e:
|
|
66
|
+
print_error(e.message)
|
|
67
|
+
raise SystemExit(1) from e
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@click.command()
|
|
71
|
+
@click.argument("task_id")
|
|
72
|
+
@click.option(
|
|
73
|
+
"--interval",
|
|
74
|
+
type=int,
|
|
75
|
+
default=5,
|
|
76
|
+
help="Polling interval in seconds (default: 5).",
|
|
77
|
+
)
|
|
78
|
+
@click.option(
|
|
79
|
+
"--timeout",
|
|
80
|
+
"max_timeout",
|
|
81
|
+
type=int,
|
|
82
|
+
default=600,
|
|
83
|
+
help="Maximum wait time in seconds (default: 600).",
|
|
84
|
+
)
|
|
85
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
86
|
+
@click.pass_context
|
|
87
|
+
def wait(
|
|
88
|
+
ctx: click.Context,
|
|
89
|
+
task_id: str,
|
|
90
|
+
interval: int,
|
|
91
|
+
max_timeout: int,
|
|
92
|
+
output_json: bool,
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Wait for a task to complete, polling periodically.
|
|
95
|
+
|
|
96
|
+
TASK_ID is the task ID to monitor.
|
|
97
|
+
|
|
98
|
+
Examples:
|
|
99
|
+
|
|
100
|
+
flux wait abc123
|
|
101
|
+
|
|
102
|
+
flux wait abc123 --interval 10 --timeout 300
|
|
103
|
+
"""
|
|
104
|
+
client = get_client(ctx.obj.get("token"))
|
|
105
|
+
elapsed = 0
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
while elapsed < max_timeout:
|
|
109
|
+
result = client.query_task(id=task_id, action="retrieve")
|
|
110
|
+
data = result.get("data", {})
|
|
111
|
+
|
|
112
|
+
if isinstance(data, list) and data:
|
|
113
|
+
item = data[0]
|
|
114
|
+
elif isinstance(data, dict):
|
|
115
|
+
item = data
|
|
116
|
+
else:
|
|
117
|
+
item = {}
|
|
118
|
+
|
|
119
|
+
state = item.get("state", item.get("status", ""))
|
|
120
|
+
if state in ("succeeded", "completed", "complete", "failed", "error"):
|
|
121
|
+
if output_json:
|
|
122
|
+
print_json(result)
|
|
123
|
+
else:
|
|
124
|
+
if state in ("failed", "error"):
|
|
125
|
+
print_error(f"Task {task_id} failed.")
|
|
126
|
+
else:
|
|
127
|
+
print_success(f"Task {task_id} completed!")
|
|
128
|
+
print_task_result(result)
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
if not output_json:
|
|
132
|
+
click.echo(f"Status: {state or 'pending'} (waited {elapsed}s)...", err=True)
|
|
133
|
+
|
|
134
|
+
time.sleep(interval)
|
|
135
|
+
elapsed += interval
|
|
136
|
+
|
|
137
|
+
print_error(f"Timeout: task {task_id} did not complete within {max_timeout}s")
|
|
138
|
+
raise SystemExit(1)
|
|
139
|
+
except FluxError as e:
|
|
140
|
+
print_error(e.message)
|
|
141
|
+
raise SystemExit(1) from e
|
|
File without changes
|