hailuo-cli 2026.7.31.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.
- hailuo_cli-2026.7.31.0/.env.example +4 -0
- hailuo_cli-2026.7.31.0/.gitignore +32 -0
- hailuo_cli-2026.7.31.0/CHANGELOG.md +17 -0
- hailuo_cli-2026.7.31.0/LICENSE +21 -0
- hailuo_cli-2026.7.31.0/PKG-INFO +162 -0
- hailuo_cli-2026.7.31.0/README.md +116 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/__init__.py +1 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/__main__.py +5 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/commands/__init__.py +1 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/commands/info.py +30 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/commands/task.py +160 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/commands/video.py +128 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/core/__init__.py +1 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/core/client.py +107 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/core/config.py +39 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/core/exceptions.py +37 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/core/output.py +116 -0
- hailuo_cli-2026.7.31.0/hailuo_cli/main.py +69 -0
- hailuo_cli-2026.7.31.0/pyproject.toml +119 -0
- hailuo_cli-2026.7.31.0/tests/__init__.py +0 -0
- hailuo_cli-2026.7.31.0/tests/conftest.py +92 -0
- hailuo_cli-2026.7.31.0/tests/test_client.py +74 -0
- hailuo_cli-2026.7.31.0/tests/test_commands.py +230 -0
- hailuo_cli-2026.7.31.0/tests/test_config.py +39 -0
- hailuo_cli-2026.7.31.0/tests/test_integration.py +35 -0
- hailuo_cli-2026.7.31.0/tests/test_output.py +85 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
ENV/
|
|
16
|
+
|
|
17
|
+
# Environment variables
|
|
18
|
+
.env
|
|
19
|
+
|
|
20
|
+
# IDE
|
|
21
|
+
.vscode/
|
|
22
|
+
.idea/
|
|
23
|
+
*.swp
|
|
24
|
+
*.swo
|
|
25
|
+
|
|
26
|
+
# Testing
|
|
27
|
+
.coverage
|
|
28
|
+
htmlcov/
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
|
|
31
|
+
# mypy
|
|
32
|
+
.mypy_cache/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Calendar Versioning](https://calver.org/) (YYYY.MM.DD.BUILD).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-04-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release
|
|
12
|
+
- Hailuo video generation from text prompts (minimax-t2v)
|
|
13
|
+
- Image-to-video generation (minimax-i2v, minimax-i2v-director)
|
|
14
|
+
- Task management with polling
|
|
15
|
+
- Rich terminal output with tables and panels
|
|
16
|
+
- JSON output mode (`--json` flag)
|
|
17
|
+
- Multiple model support
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 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,162 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: hailuo-cli
|
|
3
|
+
Version: 2026.7.31.0
|
|
4
|
+
Summary: CLI tool for Hailuo AI Video Generation via AceDataCloud API
|
|
5
|
+
Project-URL: Homepage, https://github.com/AceDataCloud/HailuoCli
|
|
6
|
+
Project-URL: Repository, https://github.com/AceDataCloud/HailuoCli
|
|
7
|
+
Project-URL: Issues, https://github.com/AceDataCloud/HailuoCli/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/AceDataCloud/HailuoCli/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,generation,hailuo,minimax,video
|
|
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 :: Video
|
|
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: hailuo-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
|
+
# Hailuo CLI
|
|
48
|
+
|
|
49
|
+
A command-line tool for generating AI videos using [Hailuo (MiniMax)](https://platform.acedata.cloud) through the AceDataCloud platform.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install hailuo-cli
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Configuration
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
export ACEDATACLOUD_API_TOKEN=your_token
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or copy `.env.example` to `.env` and fill in your token.
|
|
64
|
+
|
|
65
|
+
## Commands
|
|
66
|
+
|
|
67
|
+
### Video Generation
|
|
68
|
+
|
|
69
|
+
| Command | Description |
|
|
70
|
+
|---------|-------------|
|
|
71
|
+
| `hailuo generate <prompt>` | Generate a video from text (minimax-t2v) |
|
|
72
|
+
| `hailuo image-to-video <prompt> --image-url <url>` | Generate video from image + text |
|
|
73
|
+
|
|
74
|
+
### Task Management
|
|
75
|
+
|
|
76
|
+
| Command | Description |
|
|
77
|
+
|---------|-------------|
|
|
78
|
+
| `hailuo task <task_id>` | Query a single task status |
|
|
79
|
+
| `hailuo tasks <id1> <id2> [...]` | Query multiple tasks at once |
|
|
80
|
+
| `hailuo wait <task_id>` | Wait for task completion with polling |
|
|
81
|
+
|
|
82
|
+
### Utilities
|
|
83
|
+
|
|
84
|
+
| Command | Description |
|
|
85
|
+
|---------|-------------|
|
|
86
|
+
| `hailuo models` | List available Hailuo models |
|
|
87
|
+
| `hailuo config` | Show current configuration |
|
|
88
|
+
|
|
89
|
+
## Global Options
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
--token TEXT API token (or set ACEDATACLOUD_API_TOKEN env var)
|
|
93
|
+
--version Show version
|
|
94
|
+
--help Show help message
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Most commands support:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
--json Output raw JSON (for piping/scripting)
|
|
101
|
+
--callback-url Webhook URL for async notifications
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Examples
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Generate a video from a text prompt
|
|
108
|
+
hailuo generate "A cat playing in the snow"
|
|
109
|
+
|
|
110
|
+
# Generate from image reference
|
|
111
|
+
hailuo image-to-video "Animate the scene" --image-url https://example.com/photo.jpg
|
|
112
|
+
|
|
113
|
+
# Use a specific model
|
|
114
|
+
hailuo generate "Ocean waves" --model minimax-t2v
|
|
115
|
+
|
|
116
|
+
# Director model with image reference
|
|
117
|
+
hailuo image-to-video "Cinematic pan" --image-url img.jpg --model minimax-i2v-director
|
|
118
|
+
|
|
119
|
+
# Check task status
|
|
120
|
+
hailuo task abc123-def456
|
|
121
|
+
|
|
122
|
+
# Wait for completion
|
|
123
|
+
hailuo wait abc123 --timeout 300
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Docker
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Pull the image
|
|
130
|
+
docker pull ghcr.io/acedatacloud/hailuo-cli:latest
|
|
131
|
+
|
|
132
|
+
# Run a command
|
|
133
|
+
docker run --rm -e ACEDATACLOUD_API_TOKEN=your_token \
|
|
134
|
+
ghcr.io/acedatacloud/hailuo-cli generate "A happy scene"
|
|
135
|
+
|
|
136
|
+
# Or use docker-compose
|
|
137
|
+
docker compose run --rm hailuo-cli generate "A happy scene"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Project Structure
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
HailuoCli/
|
|
144
|
+
├── hailuo_cli/ # Main package
|
|
145
|
+
│ ├── __init__.py
|
|
146
|
+
│ ├── __main__.py # python -m hailuo_cli entry point
|
|
147
|
+
│ ├── main.py # CLI entry point
|
|
148
|
+
│ ├── core/ # Core modules
|
|
149
|
+
│ │ ├── client.py # HTTP client for Hailuo API
|
|
150
|
+
│ │ ├── config.py # Configuration management
|
|
151
|
+
│ │ ├── exceptions.py # Custom exceptions
|
|
152
|
+
│ │ └── output.py # Rich terminal formatting
|
|
153
|
+
│ └── commands/ # CLI command groups
|
|
154
|
+
│ ├── video.py # Video generation commands
|
|
155
|
+
│ ├── task.py # Task management commands
|
|
156
|
+
│ └── info.py # Info and utility commands
|
|
157
|
+
└── tests/ # Test suite
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Hailuo CLI
|
|
2
|
+
|
|
3
|
+
A command-line tool for generating AI videos using [Hailuo (MiniMax)](https://platform.acedata.cloud) through the AceDataCloud platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install hailuo-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
export ACEDATACLOUD_API_TOKEN=your_token
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or copy `.env.example` to `.env` and fill in your token.
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### Video Generation
|
|
22
|
+
|
|
23
|
+
| Command | Description |
|
|
24
|
+
|---------|-------------|
|
|
25
|
+
| `hailuo generate <prompt>` | Generate a video from text (minimax-t2v) |
|
|
26
|
+
| `hailuo image-to-video <prompt> --image-url <url>` | Generate video from image + text |
|
|
27
|
+
|
|
28
|
+
### Task Management
|
|
29
|
+
|
|
30
|
+
| Command | Description |
|
|
31
|
+
|---------|-------------|
|
|
32
|
+
| `hailuo task <task_id>` | Query a single task status |
|
|
33
|
+
| `hailuo tasks <id1> <id2> [...]` | Query multiple tasks at once |
|
|
34
|
+
| `hailuo wait <task_id>` | Wait for task completion with polling |
|
|
35
|
+
|
|
36
|
+
### Utilities
|
|
37
|
+
|
|
38
|
+
| Command | Description |
|
|
39
|
+
|---------|-------------|
|
|
40
|
+
| `hailuo models` | List available Hailuo models |
|
|
41
|
+
| `hailuo config` | Show current configuration |
|
|
42
|
+
|
|
43
|
+
## Global Options
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
--token TEXT API token (or set ACEDATACLOUD_API_TOKEN env var)
|
|
47
|
+
--version Show version
|
|
48
|
+
--help Show help message
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Most commands support:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
--json Output raw JSON (for piping/scripting)
|
|
55
|
+
--callback-url Webhook URL for async notifications
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Generate a video from a text prompt
|
|
62
|
+
hailuo generate "A cat playing in the snow"
|
|
63
|
+
|
|
64
|
+
# Generate from image reference
|
|
65
|
+
hailuo image-to-video "Animate the scene" --image-url https://example.com/photo.jpg
|
|
66
|
+
|
|
67
|
+
# Use a specific model
|
|
68
|
+
hailuo generate "Ocean waves" --model minimax-t2v
|
|
69
|
+
|
|
70
|
+
# Director model with image reference
|
|
71
|
+
hailuo image-to-video "Cinematic pan" --image-url img.jpg --model minimax-i2v-director
|
|
72
|
+
|
|
73
|
+
# Check task status
|
|
74
|
+
hailuo task abc123-def456
|
|
75
|
+
|
|
76
|
+
# Wait for completion
|
|
77
|
+
hailuo wait abc123 --timeout 300
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Docker
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Pull the image
|
|
84
|
+
docker pull ghcr.io/acedatacloud/hailuo-cli:latest
|
|
85
|
+
|
|
86
|
+
# Run a command
|
|
87
|
+
docker run --rm -e ACEDATACLOUD_API_TOKEN=your_token \
|
|
88
|
+
ghcr.io/acedatacloud/hailuo-cli generate "A happy scene"
|
|
89
|
+
|
|
90
|
+
# Or use docker-compose
|
|
91
|
+
docker compose run --rm hailuo-cli generate "A happy scene"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Project Structure
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
HailuoCli/
|
|
98
|
+
├── hailuo_cli/ # Main package
|
|
99
|
+
│ ├── __init__.py
|
|
100
|
+
│ ├── __main__.py # python -m hailuo_cli entry point
|
|
101
|
+
│ ├── main.py # CLI entry point
|
|
102
|
+
│ ├── core/ # Core modules
|
|
103
|
+
│ │ ├── client.py # HTTP client for Hailuo API
|
|
104
|
+
│ │ ├── config.py # Configuration management
|
|
105
|
+
│ │ ├── exceptions.py # Custom exceptions
|
|
106
|
+
│ │ └── output.py # Rich terminal formatting
|
|
107
|
+
│ └── commands/ # CLI command groups
|
|
108
|
+
│ ├── video.py # Video generation commands
|
|
109
|
+
│ ├── task.py # Task management commands
|
|
110
|
+
│ └── info.py # Info and utility commands
|
|
111
|
+
└── tests/ # Test suite
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Hailuo CLI - AI Video Generation via AceDataCloud API."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Commands package for Hailuo CLI."""
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Info and utility commands."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from hailuo_cli.core.config import settings
|
|
6
|
+
from hailuo_cli.core.output import console, print_models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
def models() -> None:
|
|
11
|
+
"""List available Hailuo 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="Hailuo 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", f"{settings.api_token[:8]}..." if settings.api_token else "[red]Not set[/red]"
|
|
27
|
+
)
|
|
28
|
+
table.add_row("Request Timeout", f"{settings.request_timeout}s")
|
|
29
|
+
|
|
30
|
+
console.print(table)
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Task management commands."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from hailuo_cli.core.client import get_client
|
|
8
|
+
from hailuo_cli.core.exceptions import HailuoError
|
|
9
|
+
from hailuo_cli.core.output import (
|
|
10
|
+
print_error,
|
|
11
|
+
print_json,
|
|
12
|
+
print_success,
|
|
13
|
+
print_task_result,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command()
|
|
18
|
+
@click.argument("task_id")
|
|
19
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
20
|
+
@click.pass_context
|
|
21
|
+
def task(
|
|
22
|
+
ctx: click.Context,
|
|
23
|
+
task_id: str,
|
|
24
|
+
output_json: bool,
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Query a single task status.
|
|
27
|
+
|
|
28
|
+
TASK_ID is the task ID returned from generate commands.
|
|
29
|
+
|
|
30
|
+
\b
|
|
31
|
+
Examples:
|
|
32
|
+
hailuo task abc123-def456
|
|
33
|
+
"""
|
|
34
|
+
client = get_client(ctx.obj.get("token"))
|
|
35
|
+
try:
|
|
36
|
+
result = client.query_task(id=task_id, action="retrieve")
|
|
37
|
+
if output_json:
|
|
38
|
+
print_json(result)
|
|
39
|
+
else:
|
|
40
|
+
print_task_result(result)
|
|
41
|
+
except HailuoError as e:
|
|
42
|
+
print_error(e.message)
|
|
43
|
+
raise SystemExit(1) from e
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@click.command("tasks")
|
|
47
|
+
@click.argument("task_ids", nargs=-1, required=True)
|
|
48
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
49
|
+
@click.pass_context
|
|
50
|
+
def tasks_batch(
|
|
51
|
+
ctx: click.Context,
|
|
52
|
+
task_ids: tuple[str, ...],
|
|
53
|
+
output_json: bool,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Query multiple tasks at once.
|
|
56
|
+
|
|
57
|
+
TASK_IDS are space-separated task IDs.
|
|
58
|
+
|
|
59
|
+
\b
|
|
60
|
+
Examples:
|
|
61
|
+
hailuo tasks abc123 def456 ghi789
|
|
62
|
+
"""
|
|
63
|
+
client = get_client(ctx.obj.get("token"))
|
|
64
|
+
try:
|
|
65
|
+
result = client.query_task(ids=list(task_ids), action="retrieve_batch")
|
|
66
|
+
if output_json:
|
|
67
|
+
print_json(result)
|
|
68
|
+
else:
|
|
69
|
+
print_task_result(result)
|
|
70
|
+
except HailuoError as e:
|
|
71
|
+
print_error(e.message)
|
|
72
|
+
raise SystemExit(1) from e
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@click.command()
|
|
76
|
+
@click.argument("task_id")
|
|
77
|
+
@click.option(
|
|
78
|
+
"--interval",
|
|
79
|
+
type=int,
|
|
80
|
+
default=5,
|
|
81
|
+
help="Polling interval in seconds (default: 5).",
|
|
82
|
+
)
|
|
83
|
+
@click.option(
|
|
84
|
+
"--timeout",
|
|
85
|
+
"max_timeout",
|
|
86
|
+
type=int,
|
|
87
|
+
default=600,
|
|
88
|
+
help="Maximum wait time in seconds (default: 600).",
|
|
89
|
+
)
|
|
90
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
91
|
+
@click.pass_context
|
|
92
|
+
def wait(
|
|
93
|
+
ctx: click.Context,
|
|
94
|
+
task_id: str,
|
|
95
|
+
interval: int,
|
|
96
|
+
max_timeout: int,
|
|
97
|
+
output_json: bool,
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Wait for a task to complete, polling periodically.
|
|
100
|
+
|
|
101
|
+
TASK_ID is the task ID to monitor.
|
|
102
|
+
|
|
103
|
+
\b
|
|
104
|
+
Examples:
|
|
105
|
+
hailuo wait abc123
|
|
106
|
+
hailuo wait abc123 --interval 10 --timeout 300
|
|
107
|
+
"""
|
|
108
|
+
client = get_client(ctx.obj.get("token"))
|
|
109
|
+
elapsed = 0
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
while elapsed < max_timeout:
|
|
113
|
+
result = client.query_task(id=task_id, action="retrieve")
|
|
114
|
+
|
|
115
|
+
# Check for completion signals
|
|
116
|
+
data = result.get("data", result)
|
|
117
|
+
if isinstance(data, dict):
|
|
118
|
+
item = data
|
|
119
|
+
elif isinstance(data, list) and data:
|
|
120
|
+
item = data[0]
|
|
121
|
+
else:
|
|
122
|
+
item = result
|
|
123
|
+
|
|
124
|
+
state = item.get("state", item.get("status", ""))
|
|
125
|
+
video_url = item.get("video_url") or result.get("video_url")
|
|
126
|
+
error = item.get("error") or result.get("error")
|
|
127
|
+
|
|
128
|
+
if error:
|
|
129
|
+
if output_json:
|
|
130
|
+
print_json(result)
|
|
131
|
+
else:
|
|
132
|
+
print_error(f"Task {task_id} failed: {error}")
|
|
133
|
+
raise SystemExit(1)
|
|
134
|
+
|
|
135
|
+
if state in ("succeeded", "completed", "complete") or video_url:
|
|
136
|
+
if output_json:
|
|
137
|
+
print_json(result)
|
|
138
|
+
else:
|
|
139
|
+
print_success(f"Task {task_id} completed!")
|
|
140
|
+
print_task_result(result)
|
|
141
|
+
return
|
|
142
|
+
|
|
143
|
+
if state in ("failed", "error"):
|
|
144
|
+
if output_json:
|
|
145
|
+
print_json(result)
|
|
146
|
+
else:
|
|
147
|
+
print_error(f"Task {task_id} failed.")
|
|
148
|
+
raise SystemExit(1)
|
|
149
|
+
|
|
150
|
+
if not output_json:
|
|
151
|
+
click.echo(f"Status: {state or 'pending'} (waited {elapsed}s)...", err=True)
|
|
152
|
+
|
|
153
|
+
time.sleep(interval)
|
|
154
|
+
elapsed += interval
|
|
155
|
+
|
|
156
|
+
print_error(f"Timeout: task {task_id} did not complete within {max_timeout}s")
|
|
157
|
+
raise SystemExit(1)
|
|
158
|
+
except HailuoError as e:
|
|
159
|
+
print_error(e.message)
|
|
160
|
+
raise SystemExit(1) from e
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Video generation commands."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from hailuo_cli.core.client import get_client
|
|
6
|
+
from hailuo_cli.core.exceptions import HailuoError
|
|
7
|
+
from hailuo_cli.core.output import (
|
|
8
|
+
DEFAULT_MODEL,
|
|
9
|
+
HAILUO_MODELS,
|
|
10
|
+
print_error,
|
|
11
|
+
print_json,
|
|
12
|
+
print_video_result,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.command()
|
|
17
|
+
@click.argument("prompt")
|
|
18
|
+
@click.option(
|
|
19
|
+
"-m",
|
|
20
|
+
"--model",
|
|
21
|
+
type=click.Choice(HAILUO_MODELS),
|
|
22
|
+
default=DEFAULT_MODEL,
|
|
23
|
+
help="Hailuo model to use (default: minimax-t2v).",
|
|
24
|
+
)
|
|
25
|
+
@click.option("--callback-url", default=None, help="Webhook callback URL.")
|
|
26
|
+
@click.option(
|
|
27
|
+
"--async",
|
|
28
|
+
"async_mode",
|
|
29
|
+
is_flag=True,
|
|
30
|
+
default=False,
|
|
31
|
+
help="Submit asynchronously; returns a task_id to poll instead of waiting.",
|
|
32
|
+
)
|
|
33
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
34
|
+
@click.pass_context
|
|
35
|
+
def generate(
|
|
36
|
+
ctx: click.Context,
|
|
37
|
+
prompt: str,
|
|
38
|
+
model: str,
|
|
39
|
+
callback_url: str | None,
|
|
40
|
+
async_mode: bool,
|
|
41
|
+
output_json: bool,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Generate a video from a text prompt.
|
|
44
|
+
|
|
45
|
+
PROMPT is a detailed description of what to generate.
|
|
46
|
+
|
|
47
|
+
\b
|
|
48
|
+
Examples:
|
|
49
|
+
hailuo generate "A cat playing in the snow"
|
|
50
|
+
hailuo generate "Ocean waves at sunset" --model minimax-t2v
|
|
51
|
+
"""
|
|
52
|
+
client = get_client(ctx.obj.get("token"))
|
|
53
|
+
try:
|
|
54
|
+
payload: dict[str, object] = {
|
|
55
|
+
"action": "generate",
|
|
56
|
+
"prompt": prompt,
|
|
57
|
+
"model": model,
|
|
58
|
+
"callback_url": callback_url,
|
|
59
|
+
"async": async_mode,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
result = client.generate_video(**payload) # type: ignore[arg-type]
|
|
63
|
+
if output_json:
|
|
64
|
+
print_json(result)
|
|
65
|
+
else:
|
|
66
|
+
print_video_result(result)
|
|
67
|
+
except HailuoError as e:
|
|
68
|
+
print_error(e.message)
|
|
69
|
+
raise SystemExit(1) from e
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@click.command("image-to-video")
|
|
73
|
+
@click.argument("prompt")
|
|
74
|
+
@click.option("--image-url", required=True, help="URL of the first frame reference image.")
|
|
75
|
+
@click.option(
|
|
76
|
+
"-m",
|
|
77
|
+
"--model",
|
|
78
|
+
type=click.Choice(["minimax-i2v", "minimax-t2v", "minimax-i2v-director"]),
|
|
79
|
+
default="minimax-i2v",
|
|
80
|
+
help="Hailuo image-to-video model (default: minimax-i2v).",
|
|
81
|
+
)
|
|
82
|
+
@click.option("--callback-url", default=None, help="Webhook callback URL.")
|
|
83
|
+
@click.option(
|
|
84
|
+
"--async",
|
|
85
|
+
"async_mode",
|
|
86
|
+
is_flag=True,
|
|
87
|
+
default=False,
|
|
88
|
+
help="Submit asynchronously; returns a task_id to poll instead of waiting.",
|
|
89
|
+
)
|
|
90
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
91
|
+
@click.pass_context
|
|
92
|
+
def image_to_video(
|
|
93
|
+
ctx: click.Context,
|
|
94
|
+
prompt: str,
|
|
95
|
+
image_url: str,
|
|
96
|
+
model: str,
|
|
97
|
+
callback_url: str | None,
|
|
98
|
+
async_mode: bool,
|
|
99
|
+
output_json: bool,
|
|
100
|
+
) -> None:
|
|
101
|
+
"""Generate a video from an image and text prompt.
|
|
102
|
+
|
|
103
|
+
PROMPT describes the desired video content.
|
|
104
|
+
|
|
105
|
+
\b
|
|
106
|
+
Examples:
|
|
107
|
+
hailuo image-to-video "Animate this scene" --image-url https://example.com/photo.jpg
|
|
108
|
+
hailuo image-to-video "Cinematic pan" --image-url img.jpg --model minimax-i2v-director
|
|
109
|
+
"""
|
|
110
|
+
client = get_client(ctx.obj.get("token"))
|
|
111
|
+
try:
|
|
112
|
+
payload: dict[str, object] = {
|
|
113
|
+
"action": "generate",
|
|
114
|
+
"prompt": prompt,
|
|
115
|
+
"model": model,
|
|
116
|
+
"first_image_url": image_url,
|
|
117
|
+
"callback_url": callback_url,
|
|
118
|
+
"async": async_mode,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
result = client.generate_video(**payload) # type: ignore[arg-type]
|
|
122
|
+
if output_json:
|
|
123
|
+
print_json(result)
|
|
124
|
+
else:
|
|
125
|
+
print_video_result(result)
|
|
126
|
+
except HailuoError as e:
|
|
127
|
+
print_error(e.message)
|
|
128
|
+
raise SystemExit(1) from e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Core package for Hailuo CLI."""
|