dantelabs-agentic-school 1.0.0 → 1.2.0
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.
- package/.claude-plugin/marketplace.json +11 -53
- package/cli/bin/cli.js +31 -8
- package/cli/src/commands/info.js +15 -11
- package/cli/src/commands/install.js +53 -29
- package/cli/src/commands/list.js +28 -22
- package/cli/src/commands/uninstall.js +23 -16
- package/cli/src/i18n/index.js +96 -0
- package/cli/src/i18n/locales/en.js +107 -0
- package/cli/src/i18n/locales/ko.js +107 -0
- package/cli/src/lib/config.js +116 -1
- package/cli/src/lib/installer.js +106 -3
- package/package.json +1 -1
- package/plugins/brand-analytics/plugin.json +9 -0
- package/plugins/campaign-orchestration/plugin.json +9 -0
- package/plugins/common/plugin.json +9 -0
- package/plugins/common/skills/kie-image-generator/.env.example +4 -0
- package/plugins/common/skills/kie-image-generator/SKILL.md +281 -0
- package/plugins/common/skills/kie-image-generator/references/api_docs.md +358 -0
- package/plugins/common/skills/kie-image-generator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/generate_image.py +285 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__init__.py +19 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/__init__.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/flux_kontext.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/gpt4o.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/ideogram.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/imagen.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/nano_banana.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/nano_banana_edit.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/nano_banana_pro.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/seedream.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/seedream_edit.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/flux_kontext.py +36 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/gpt4o.py +36 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/ideogram.py +85 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/imagen.py +48 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/nano_banana.py +40 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/nano_banana_edit.py +55 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/nano_banana_pro.py +47 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/seedream.py +51 -0
- package/plugins/common/skills/kie-image-generator/scripts/models/seedream_edit.py +66 -0
- package/plugins/common/skills/kie-image-generator/scripts/utils.py +706 -0
- package/plugins/common/skills/kie-video-generator/SKILL.md +258 -0
- package/plugins/common/skills/kie-video-generator/references/api_docs.md +202 -0
- package/plugins/common/skills/kie-video-generator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
- package/plugins/common/skills/kie-video-generator/scripts/generate_video.py +356 -0
- package/plugins/common/skills/kie-video-generator/scripts/models/__init__.py +4 -0
- package/plugins/common/skills/kie-video-generator/scripts/utils.py +617 -0
- package/plugins/content-creation/plugin.json +9 -0
- package/plugins/creative-production/plugin.json +9 -0
- package/plugins/customer-segmentation/plugin.json +9 -0
- package/plugins/market-research/plugin.json +9 -0
- package/plugins/persona-builder/plugin.json +9 -0
- package/plugins/social-strategy/plugin.json +9 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Kie.ai Image Generation CLI
|
|
4
|
+
|
|
5
|
+
Generate images using Kie.ai's diverse AI models.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import argparse
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, Any
|
|
12
|
+
|
|
13
|
+
# Add parent directory to path for imports
|
|
14
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
15
|
+
|
|
16
|
+
from utils import (
|
|
17
|
+
load_api_key,
|
|
18
|
+
get_credits,
|
|
19
|
+
print_credits,
|
|
20
|
+
print_models,
|
|
21
|
+
select_model_interactive,
|
|
22
|
+
confirm_generation,
|
|
23
|
+
submit_task,
|
|
24
|
+
poll_task,
|
|
25
|
+
download_image,
|
|
26
|
+
generate_filename,
|
|
27
|
+
MODELS,
|
|
28
|
+
CREDIT_TO_USD,
|
|
29
|
+
GENERATION_ENDPOINTS,
|
|
30
|
+
RECORD_INFO_ENDPOINTS,
|
|
31
|
+
JOBS_API_MODELS
|
|
32
|
+
)
|
|
33
|
+
from models import (
|
|
34
|
+
build_gpt4o_payload,
|
|
35
|
+
build_flux_payload,
|
|
36
|
+
build_nano_payload,
|
|
37
|
+
build_nano_pro_payload,
|
|
38
|
+
build_seedream_payload,
|
|
39
|
+
build_imagen_payload,
|
|
40
|
+
build_ideogram_payload
|
|
41
|
+
)
|
|
42
|
+
from models.seedream_edit import build_seedream_edit_payload
|
|
43
|
+
from models.nano_banana_edit import build_nano_edit_payload
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
AVAILABLE_MODELS = list(GENERATION_ENDPOINTS.keys())
|
|
47
|
+
|
|
48
|
+
MODEL_PAYLOAD_BUILDERS = {
|
|
49
|
+
'gpt4o-image': build_gpt4o_payload,
|
|
50
|
+
'flux-kontext-pro': build_flux_payload,
|
|
51
|
+
'flux-kontext-max': build_flux_payload,
|
|
52
|
+
'nano-banana': build_nano_payload,
|
|
53
|
+
'nano-banana-pro': build_nano_pro_payload,
|
|
54
|
+
'nano-banana-edit': build_nano_edit_payload,
|
|
55
|
+
'seedream-v4': build_seedream_payload,
|
|
56
|
+
'seedream-v4-edit': build_seedream_edit_payload,
|
|
57
|
+
'imagen-4-ultra': build_imagen_payload,
|
|
58
|
+
'imagen-4': build_imagen_payload,
|
|
59
|
+
'imagen-4-fast': build_imagen_payload,
|
|
60
|
+
'ideogram-v3': lambda prompt, **kw: build_ideogram_payload(prompt, 'ideogram-v3', **kw),
|
|
61
|
+
'ideogram-character': lambda prompt, **kw: build_ideogram_payload(prompt, 'ideogram-character', **kw),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def parse_arguments():
|
|
66
|
+
"""Parse command-line arguments"""
|
|
67
|
+
parser = argparse.ArgumentParser(
|
|
68
|
+
description='Generate images using Kie.ai models',
|
|
69
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
70
|
+
epilog="""
|
|
71
|
+
Examples:
|
|
72
|
+
%(prog)s --credits # Check available credits
|
|
73
|
+
%(prog)s --list-models # List all models with pricing
|
|
74
|
+
%(prog)s "a beautiful sunset" # Interactive model selection
|
|
75
|
+
%(prog)s "cyberpunk city" --model flux-kontext-pro
|
|
76
|
+
%(prog)s "abstract art" --model seedream-v4 --resolution 4K
|
|
77
|
+
%(prog)s "portrait" --model imagen-4-ultra --aspect-ratio 3:4
|
|
78
|
+
"""
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Positional argument (optional for info commands)
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
'prompt',
|
|
84
|
+
nargs='?',
|
|
85
|
+
help='Image generation prompt'
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Info commands
|
|
89
|
+
parser.add_argument(
|
|
90
|
+
'--credits', '-c',
|
|
91
|
+
action='store_true',
|
|
92
|
+
help='Show current account credits'
|
|
93
|
+
)
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
'--list-models', '-l',
|
|
96
|
+
action='store_true',
|
|
97
|
+
help='List all available models with pricing'
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Model selection
|
|
101
|
+
parser.add_argument(
|
|
102
|
+
'--model', '-m',
|
|
103
|
+
choices=AVAILABLE_MODELS,
|
|
104
|
+
help='Model to use (interactive selection if not specified)'
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Skip confirmation
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
'--yes', '-y',
|
|
110
|
+
action='store_true',
|
|
111
|
+
help='Skip confirmation prompts'
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# No download
|
|
115
|
+
parser.add_argument(
|
|
116
|
+
'--no-download',
|
|
117
|
+
action='store_true',
|
|
118
|
+
help='Skip image download (print URL only)'
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
'--output', '-o',
|
|
123
|
+
type=Path,
|
|
124
|
+
default=Path.home() / 'Downloads' / 'images',
|
|
125
|
+
help='Output directory (default: ~/Downloads/images/)'
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Common parameters
|
|
129
|
+
parser.add_argument('--size', help='Image size/aspect ratio')
|
|
130
|
+
parser.add_argument('--ratio', help='Image ratio (Flux models)')
|
|
131
|
+
parser.add_argument('--format', help='Output format')
|
|
132
|
+
parser.add_argument('--resolution', help='Image resolution (Seedream)')
|
|
133
|
+
parser.add_argument('--aspect-ratio', help='Aspect ratio (Imagen)')
|
|
134
|
+
parser.add_argument('--rendering', help='Rendering speed (Ideogram)')
|
|
135
|
+
parser.add_argument('--style', help='Style preset (Ideogram)')
|
|
136
|
+
parser.add_argument('--variants', type=int, help='Number of variants (GPT-4O)')
|
|
137
|
+
parser.add_argument('--images', type=int, help='Number of images')
|
|
138
|
+
parser.add_argument('--num-images', type=int, help='Number of images (alias)')
|
|
139
|
+
parser.add_argument('--seed', type=int, help='Random seed')
|
|
140
|
+
parser.add_argument('--negative', help='Negative prompt')
|
|
141
|
+
parser.add_argument('--negative-prompt', help='Negative prompt (alias)')
|
|
142
|
+
parser.add_argument('--expand-prompt', action='store_true', help='Enable prompt enhancement')
|
|
143
|
+
parser.add_argument('--reference', help='Reference image URL (Ideogram Character)')
|
|
144
|
+
parser.add_argument('--reference-images', help='Reference image URLs (Ideogram Character)')
|
|
145
|
+
|
|
146
|
+
return parser.parse_args()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def main():
|
|
150
|
+
"""Main execution function"""
|
|
151
|
+
args = parse_arguments()
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
# Load API key
|
|
155
|
+
api_key = load_api_key()
|
|
156
|
+
|
|
157
|
+
# Handle info commands
|
|
158
|
+
if args.credits:
|
|
159
|
+
print_credits(api_key)
|
|
160
|
+
return 0
|
|
161
|
+
|
|
162
|
+
if args.list_models:
|
|
163
|
+
print_models()
|
|
164
|
+
return 0
|
|
165
|
+
|
|
166
|
+
# Require prompt for generation
|
|
167
|
+
if not args.prompt:
|
|
168
|
+
print("❌ Error: Please provide a prompt or use --credits / --list-models")
|
|
169
|
+
print(" Run with --help for usage information")
|
|
170
|
+
return 1
|
|
171
|
+
|
|
172
|
+
print("🎨 Kie.ai Image Generator")
|
|
173
|
+
print(f"Prompt: {args.prompt}\n")
|
|
174
|
+
|
|
175
|
+
# Get current credits
|
|
176
|
+
credits, usd = get_credits(api_key)
|
|
177
|
+
print(f"💰 Current Balance: {credits:,.1f} credits (${usd:.2f})")
|
|
178
|
+
|
|
179
|
+
# Model selection
|
|
180
|
+
has_image = bool(args.reference or args.reference_images)
|
|
181
|
+
|
|
182
|
+
if args.model:
|
|
183
|
+
model_id = args.model
|
|
184
|
+
# Validate image requirement
|
|
185
|
+
model = MODELS.get(model_id)
|
|
186
|
+
if model and model.get('type') == 'image-to-image' and not has_image:
|
|
187
|
+
print(f"\n⚠️ Model '{model_id}' requires an image input.")
|
|
188
|
+
print(" Use --reference <url> to provide an image.")
|
|
189
|
+
return 1
|
|
190
|
+
else:
|
|
191
|
+
# Interactive selection
|
|
192
|
+
model_id = select_model_interactive(has_image)
|
|
193
|
+
if not model_id:
|
|
194
|
+
print("\n👋 Generation cancelled.")
|
|
195
|
+
return 0
|
|
196
|
+
|
|
197
|
+
# Confirm generation
|
|
198
|
+
if not args.yes:
|
|
199
|
+
if not confirm_generation(model_id, credits):
|
|
200
|
+
print("\n👋 Generation cancelled.")
|
|
201
|
+
return 0
|
|
202
|
+
|
|
203
|
+
print(f"\nModel: {MODELS.get(model_id, {}).get('name', model_id)}")
|
|
204
|
+
|
|
205
|
+
# Get endpoints for model
|
|
206
|
+
generation_endpoint = GENERATION_ENDPOINTS.get(model_id)
|
|
207
|
+
record_info_endpoint = RECORD_INFO_ENDPOINTS.get(model_id)
|
|
208
|
+
|
|
209
|
+
if not generation_endpoint or not record_info_endpoint:
|
|
210
|
+
raise ValueError(f"Unsupported model: {model_id}")
|
|
211
|
+
|
|
212
|
+
# Build payload using model-specific builder
|
|
213
|
+
payload_builder = MODEL_PAYLOAD_BUILDERS.get(model_id)
|
|
214
|
+
if not payload_builder:
|
|
215
|
+
raise ValueError(f"No payload builder for model: {model_id}")
|
|
216
|
+
|
|
217
|
+
# Collect model parameters from args
|
|
218
|
+
params = {}
|
|
219
|
+
for param in ['size', 'ratio', 'format', 'resolution', 'aspect_ratio',
|
|
220
|
+
'rendering', 'style', 'variants', 'images', 'num_images',
|
|
221
|
+
'seed', 'negative', 'negative_prompt', 'expand_prompt',
|
|
222
|
+
'reference', 'reference_images']:
|
|
223
|
+
value = getattr(args, param.replace('-', '_'), None)
|
|
224
|
+
if value is not None:
|
|
225
|
+
params[param.replace('-', '_')] = value
|
|
226
|
+
|
|
227
|
+
# Map reference_images to image_urls for seedream-edit
|
|
228
|
+
if 'reference_images' in params:
|
|
229
|
+
params['image_urls'] = params['reference_images']
|
|
230
|
+
|
|
231
|
+
# Build payload
|
|
232
|
+
payload = payload_builder(args.prompt, **params)
|
|
233
|
+
print(f"\n📋 Payload: {payload}\n")
|
|
234
|
+
|
|
235
|
+
# Submit task (use Jobs API for certain models)
|
|
236
|
+
jobs_model_id = JOBS_API_MODELS.get(model_id)
|
|
237
|
+
task_id = submit_task(api_key, generation_endpoint, payload, model_id=jobs_model_id)
|
|
238
|
+
|
|
239
|
+
# Poll for completion
|
|
240
|
+
image_url = poll_task(
|
|
241
|
+
api_key,
|
|
242
|
+
record_info_endpoint,
|
|
243
|
+
task_id,
|
|
244
|
+
max_attempts=60,
|
|
245
|
+
poll_interval=2
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
print(f"\n🖼️ Image URL: {image_url}")
|
|
249
|
+
|
|
250
|
+
# Download image
|
|
251
|
+
if not args.no_download:
|
|
252
|
+
# Determine output file extension
|
|
253
|
+
if 'jpeg' in image_url.lower() or payload.get('output_format', '').lower() == 'jpeg':
|
|
254
|
+
extension = 'jpg'
|
|
255
|
+
else:
|
|
256
|
+
extension = 'png'
|
|
257
|
+
|
|
258
|
+
# Generate filename
|
|
259
|
+
filename = generate_filename(model_id, args.prompt, extension)
|
|
260
|
+
|
|
261
|
+
# Download image
|
|
262
|
+
output_path = download_image(image_url, args.output, filename)
|
|
263
|
+
print(f"\n✨ Success! Image saved to: {output_path}")
|
|
264
|
+
else:
|
|
265
|
+
print("\n✨ Image generated successfully!")
|
|
266
|
+
|
|
267
|
+
# Report updated credits
|
|
268
|
+
new_credits, new_usd = get_credits(api_key)
|
|
269
|
+
used = credits - new_credits
|
|
270
|
+
print(f"\n💰 Credits used: {used:,.1f} (${used * CREDIT_TO_USD:.2f})")
|
|
271
|
+
print(f" Remaining: {new_credits:,.1f} credits (${new_usd:.2f})")
|
|
272
|
+
|
|
273
|
+
return 0
|
|
274
|
+
|
|
275
|
+
except KeyboardInterrupt:
|
|
276
|
+
print("\n\n⚠️ Operation cancelled by user")
|
|
277
|
+
return 130
|
|
278
|
+
|
|
279
|
+
except Exception as e:
|
|
280
|
+
print(f"\n❌ Error: {e}", file=sys.stderr)
|
|
281
|
+
return 1
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
if __name__ == '__main__':
|
|
285
|
+
sys.exit(main())
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Model-specific parameter handlers"""
|
|
2
|
+
|
|
3
|
+
from .gpt4o import build_gpt4o_payload
|
|
4
|
+
from .flux_kontext import build_flux_payload
|
|
5
|
+
from .nano_banana import build_nano_payload
|
|
6
|
+
from .nano_banana_pro import build_nano_pro_payload
|
|
7
|
+
from .seedream import build_seedream_payload
|
|
8
|
+
from .imagen import build_imagen_payload
|
|
9
|
+
from .ideogram import build_ideogram_payload
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
'build_gpt4o_payload',
|
|
13
|
+
'build_flux_payload',
|
|
14
|
+
'build_nano_payload',
|
|
15
|
+
'build_nano_pro_payload',
|
|
16
|
+
'build_seedream_payload',
|
|
17
|
+
'build_imagen_payload',
|
|
18
|
+
'build_ideogram_payload',
|
|
19
|
+
]
|
|
Binary file
|
|
Binary file
|
package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/gpt4o.cpython-313.pyc
ADDED
|
Binary file
|
|
Binary file
|
package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/imagen.cpython-313.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Flux Kontext parameter handler"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def build_flux_payload(prompt: str, **kwargs) -> Dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Build payload for Flux Kontext Pro/Max models.
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
prompt: Image description
|
|
12
|
+
ratio: Image ratio (16:9, 21:9, 4:3, 1:1, 3:4, 9:16, 16:21) [default: 1:1]
|
|
13
|
+
format: Output format (jpeg, png) [default: png]
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
API request payload
|
|
17
|
+
"""
|
|
18
|
+
payload = {'prompt': prompt}
|
|
19
|
+
|
|
20
|
+
# Image ratio
|
|
21
|
+
ratio = kwargs.get('ratio', '1:1')
|
|
22
|
+
if ratio:
|
|
23
|
+
valid_ratios = ['16:9', '21:9', '4:3', '1:1', '3:4', '9:16', '16:21']
|
|
24
|
+
if ratio not in valid_ratios:
|
|
25
|
+
raise ValueError(f"Invalid ratio. Must be one of: {', '.join(valid_ratios)}")
|
|
26
|
+
payload['image_ratio'] = ratio
|
|
27
|
+
|
|
28
|
+
# Output format
|
|
29
|
+
fmt = kwargs.get('format', 'png')
|
|
30
|
+
if fmt:
|
|
31
|
+
valid_formats = ['jpeg', 'png']
|
|
32
|
+
if fmt.lower() not in valid_formats:
|
|
33
|
+
raise ValueError(f"Invalid format. Must be one of: {', '.join(valid_formats)}")
|
|
34
|
+
payload['output_format'] = fmt.lower()
|
|
35
|
+
|
|
36
|
+
return payload
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""GPT-4O Image parameter handler"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def build_gpt4o_payload(prompt: str, **kwargs) -> Dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Build payload for GPT-4O Image model.
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
prompt: Image description
|
|
12
|
+
size: Aspect ratio (1:1, 3:2, 2:3) [default: 1:1]
|
|
13
|
+
variants: Number of variants (1-4) [default: 1]
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
API request payload
|
|
17
|
+
"""
|
|
18
|
+
payload = {'prompt': prompt}
|
|
19
|
+
|
|
20
|
+
# Size parameter
|
|
21
|
+
size = kwargs.get('size', '1:1')
|
|
22
|
+
if size:
|
|
23
|
+
valid_sizes = ['1:1', '3:2', '2:3']
|
|
24
|
+
if size not in valid_sizes:
|
|
25
|
+
raise ValueError(f"Invalid size. Must be one of: {', '.join(valid_sizes)}")
|
|
26
|
+
payload['size'] = size
|
|
27
|
+
|
|
28
|
+
# Number of variants
|
|
29
|
+
variants = kwargs.get('variants', 1)
|
|
30
|
+
if variants:
|
|
31
|
+
variants = int(variants)
|
|
32
|
+
if not 1 <= variants <= 4:
|
|
33
|
+
raise ValueError("variants must be between 1 and 4")
|
|
34
|
+
payload['nVariants'] = variants
|
|
35
|
+
|
|
36
|
+
return payload
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Ideogram V3 and Character parameter handler"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any, Optional, List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def build_ideogram_payload(prompt: str, model: str, **kwargs) -> Dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Build payload for Ideogram V3 and Ideogram Character models.
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
prompt: Image description
|
|
12
|
+
model: Model ID ('ideogram-v3' or 'ideogram-character')
|
|
13
|
+
rendering: Rendering speed (TURBO, BALANCED, QUALITY) [default: BALANCED]
|
|
14
|
+
style: Style preset (AUTO, GENERAL, REALISTIC, DESIGN, FICTION) [default: AUTO]
|
|
15
|
+
size: Image size/aspect ratio
|
|
16
|
+
num_images: Number of images (1-4) [default: 1]
|
|
17
|
+
expand_prompt: Enable MagicPrompt enhancement [default: False]
|
|
18
|
+
seed: Random seed for reproducibility
|
|
19
|
+
negative_prompt: Elements to exclude
|
|
20
|
+
reference_images: Reference image URLs (for ideogram-character)
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
API request payload
|
|
24
|
+
"""
|
|
25
|
+
payload = {'prompt': prompt}
|
|
26
|
+
|
|
27
|
+
# Rendering speed
|
|
28
|
+
rendering = kwargs.get('rendering', 'BALANCED')
|
|
29
|
+
if rendering:
|
|
30
|
+
valid_speeds = ['TURBO', 'BALANCED', 'QUALITY']
|
|
31
|
+
rendering_upper = rendering.upper()
|
|
32
|
+
if rendering_upper not in valid_speeds:
|
|
33
|
+
raise ValueError(f"Invalid rendering. Must be one of: {', '.join(valid_speeds)}")
|
|
34
|
+
payload['rendering_speed'] = rendering_upper
|
|
35
|
+
|
|
36
|
+
# Style
|
|
37
|
+
style = kwargs.get('style', 'AUTO')
|
|
38
|
+
if style:
|
|
39
|
+
if model == 'ideogram-v3':
|
|
40
|
+
valid_styles = ['AUTO', 'GENERAL', 'REALISTIC', 'DESIGN']
|
|
41
|
+
else: # ideogram-character
|
|
42
|
+
valid_styles = ['AUTO', 'REALISTIC', 'FICTION']
|
|
43
|
+
|
|
44
|
+
style_upper = style.upper()
|
|
45
|
+
if style_upper not in valid_styles:
|
|
46
|
+
raise ValueError(f"Invalid style. Must be one of: {', '.join(valid_styles)}")
|
|
47
|
+
payload['style'] = style_upper
|
|
48
|
+
|
|
49
|
+
# Image size
|
|
50
|
+
size = kwargs.get('size')
|
|
51
|
+
if size:
|
|
52
|
+
payload['image_size'] = size
|
|
53
|
+
|
|
54
|
+
# Number of images (API expects string)
|
|
55
|
+
num_images = kwargs.get('num_images', 1)
|
|
56
|
+
if num_images:
|
|
57
|
+
num_images = int(num_images)
|
|
58
|
+
if not 1 <= num_images <= 4:
|
|
59
|
+
raise ValueError("num_images must be between 1 and 4")
|
|
60
|
+
payload['num_images'] = str(num_images)
|
|
61
|
+
|
|
62
|
+
# Expand prompt (MagicPrompt)
|
|
63
|
+
expand_prompt = kwargs.get('expand_prompt', False)
|
|
64
|
+
if expand_prompt:
|
|
65
|
+
payload['expand_prompt'] = bool(expand_prompt)
|
|
66
|
+
|
|
67
|
+
# Seed
|
|
68
|
+
seed = kwargs.get('seed')
|
|
69
|
+
if seed is not None:
|
|
70
|
+
payload['seed'] = int(seed)
|
|
71
|
+
|
|
72
|
+
# Negative prompt
|
|
73
|
+
negative = kwargs.get('negative_prompt') or kwargs.get('negative')
|
|
74
|
+
if negative:
|
|
75
|
+
payload['negative_prompt'] = negative
|
|
76
|
+
|
|
77
|
+
# Reference images (for ideogram-character)
|
|
78
|
+
if model == 'ideogram-character':
|
|
79
|
+
reference_images = kwargs.get('reference_images') or kwargs.get('reference')
|
|
80
|
+
if reference_images:
|
|
81
|
+
if isinstance(reference_images, str):
|
|
82
|
+
reference_images = [reference_images]
|
|
83
|
+
payload['reference_image_urls'] = reference_images
|
|
84
|
+
|
|
85
|
+
return payload
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Imagen 4 parameter handler"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def build_imagen_payload(prompt: str, **kwargs) -> Dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Build payload for Imagen 4 models (Ultra, Standard, Fast).
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
prompt: Image description
|
|
12
|
+
negative_prompt: Elements to exclude
|
|
13
|
+
aspect_ratio: Aspect ratio (1:1, 16:9, 9:16, 3:4, 4:3) [default: 1:1]
|
|
14
|
+
num_images: Number of images (1-4) [default: 1]
|
|
15
|
+
seed: Random seed for reproducibility
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
API request payload
|
|
19
|
+
"""
|
|
20
|
+
payload = {'prompt': prompt}
|
|
21
|
+
|
|
22
|
+
# Negative prompt
|
|
23
|
+
negative = kwargs.get('negative_prompt') or kwargs.get('negative')
|
|
24
|
+
if negative:
|
|
25
|
+
payload['negative_prompt'] = negative
|
|
26
|
+
|
|
27
|
+
# Aspect ratio
|
|
28
|
+
aspect_ratio = kwargs.get('aspect_ratio', '1:1')
|
|
29
|
+
if aspect_ratio:
|
|
30
|
+
valid_ratios = ['1:1', '16:9', '9:16', '3:4', '4:3']
|
|
31
|
+
if aspect_ratio not in valid_ratios:
|
|
32
|
+
raise ValueError(f"Invalid aspect_ratio. Must be one of: {', '.join(valid_ratios)}")
|
|
33
|
+
payload['aspect_ratio'] = aspect_ratio
|
|
34
|
+
|
|
35
|
+
# Number of images (API expects string)
|
|
36
|
+
num_images = kwargs.get('num_images', 1)
|
|
37
|
+
if num_images:
|
|
38
|
+
num_images = int(num_images)
|
|
39
|
+
if not 1 <= num_images <= 4:
|
|
40
|
+
raise ValueError("num_images must be between 1 and 4")
|
|
41
|
+
payload['num_images'] = str(num_images)
|
|
42
|
+
|
|
43
|
+
# Seed
|
|
44
|
+
seed = kwargs.get('seed')
|
|
45
|
+
if seed is not None:
|
|
46
|
+
payload['seed'] = int(seed)
|
|
47
|
+
|
|
48
|
+
return payload
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Nano Banana (Gemini 2.5 Flash) parameter handler"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def build_nano_payload(prompt: str, **kwargs) -> Dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Build payload for Nano Banana (Gemini 2.5 Flash) model via Jobs API.
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
prompt: Image description (max 5000 chars)
|
|
12
|
+
format: Output format (png, jpeg) [default: png]
|
|
13
|
+
size: Image size (1:1, 9:16, 16:9, 3:4, 4:3, 3:2, 2:3, 5:4, 4:5, 21:9, auto) [default: 1:1]
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
API request payload for Jobs API
|
|
17
|
+
"""
|
|
18
|
+
if len(prompt) > 5000:
|
|
19
|
+
raise ValueError("Prompt must be 5000 characters or less")
|
|
20
|
+
|
|
21
|
+
payload = {'prompt': prompt}
|
|
22
|
+
|
|
23
|
+
# Output format (lowercase for Jobs API)
|
|
24
|
+
fmt = kwargs.get('format', 'png')
|
|
25
|
+
if fmt:
|
|
26
|
+
valid_formats = ['png', 'jpeg']
|
|
27
|
+
fmt_lower = fmt.lower()
|
|
28
|
+
if fmt_lower not in valid_formats:
|
|
29
|
+
raise ValueError(f"Invalid format. Must be one of: {', '.join(valid_formats)}")
|
|
30
|
+
payload['output_format'] = fmt_lower
|
|
31
|
+
|
|
32
|
+
# Image size
|
|
33
|
+
size = kwargs.get('size', '1:1')
|
|
34
|
+
if size:
|
|
35
|
+
valid_sizes = ['1:1', '9:16', '16:9', '3:4', '4:3', '3:2', '2:3', '5:4', '4:5', '21:9', 'auto']
|
|
36
|
+
if size not in valid_sizes:
|
|
37
|
+
raise ValueError(f"Invalid size. Must be one of: {', '.join(valid_sizes)}")
|
|
38
|
+
payload['image_size'] = size
|
|
39
|
+
|
|
40
|
+
return payload
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Nano Banana Edit (Gemini 2.5 Flash) parameter handler"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any, List
|
|
4
|
+
|
|
5
|
+
def build_nano_edit_payload(prompt: str, **kwargs) -> Dict[str, Any]:
|
|
6
|
+
"""
|
|
7
|
+
Build payload for Nano Banana Edit model via Jobs API.
|
|
8
|
+
|
|
9
|
+
Parameters:
|
|
10
|
+
prompt: Image editing instruction (max 5000 chars)
|
|
11
|
+
image_urls: List of input image URLs (required, up to 10 images)
|
|
12
|
+
format: Output format (png, jpeg) [default: png]
|
|
13
|
+
size: Image size (1:1, 9:16, 16:9, 3:4, 4:3, 3:2, 2:3, 5:4, 4:5, 21:9, auto) [default: 1:1]
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
API request payload for Jobs API
|
|
17
|
+
"""
|
|
18
|
+
if len(prompt) > 5000:
|
|
19
|
+
raise ValueError("Prompt must be 5000 characters or less")
|
|
20
|
+
|
|
21
|
+
# image_urls is required for edit model
|
|
22
|
+
image_urls = kwargs.get('image_urls') or kwargs.get('image_url') or kwargs.get('reference') or kwargs.get('reference_images')
|
|
23
|
+
if not image_urls:
|
|
24
|
+
raise ValueError("image_urls parameter is required for nano-banana-edit model. Use --reference or --reference-images")
|
|
25
|
+
|
|
26
|
+
# Convert single URL to list
|
|
27
|
+
if isinstance(image_urls, str):
|
|
28
|
+
image_urls = [image_urls]
|
|
29
|
+
|
|
30
|
+
if len(image_urls) > 10:
|
|
31
|
+
raise ValueError("Maximum 10 input images allowed")
|
|
32
|
+
|
|
33
|
+
payload = {
|
|
34
|
+
'prompt': prompt,
|
|
35
|
+
'image_urls': image_urls
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Output format (lowercase for Jobs API)
|
|
39
|
+
fmt = kwargs.get('format', 'png')
|
|
40
|
+
if fmt:
|
|
41
|
+
valid_formats = ['png', 'jpeg']
|
|
42
|
+
fmt_lower = fmt.lower()
|
|
43
|
+
if fmt_lower not in valid_formats:
|
|
44
|
+
raise ValueError(f"Invalid format. Must be one of: {', '.join(valid_formats)}")
|
|
45
|
+
payload['output_format'] = fmt_lower
|
|
46
|
+
|
|
47
|
+
# Image size
|
|
48
|
+
size = kwargs.get('size', '1:1')
|
|
49
|
+
if size:
|
|
50
|
+
valid_sizes = ['1:1', '9:16', '16:9', '3:4', '4:3', '3:2', '2:3', '5:4', '4:5', '21:9', 'auto']
|
|
51
|
+
if size not in valid_sizes:
|
|
52
|
+
raise ValueError(f"Invalid size. Must be one of: {', '.join(valid_sizes)}")
|
|
53
|
+
payload['image_size'] = size
|
|
54
|
+
|
|
55
|
+
return payload
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Nano Banana Pro (DeepSeed) parameter handler - Jobs API v1"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any, List, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def build_nano_pro_payload(prompt: str, **kwargs) -> Dict[str, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Build payload for Nano Banana Pro model via Jobs API v1.
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
prompt: Image description (required)
|
|
12
|
+
aspect_ratio: Aspect ratio (1:1, 3:2, 2:3, 4:3, 3:4, 16:9, 9:16, 21:9, 9:21) [default: 1:1]
|
|
13
|
+
format: Output format (jpg, png, webp) [default: png]
|
|
14
|
+
image_input: Reference image URLs (up to 4 images)
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
API request payload for Jobs API v1
|
|
18
|
+
"""
|
|
19
|
+
payload = {'prompt': prompt}
|
|
20
|
+
|
|
21
|
+
# Aspect ratio
|
|
22
|
+
aspect_ratio = kwargs.get('aspect_ratio') or kwargs.get('size') or kwargs.get('ratio')
|
|
23
|
+
if aspect_ratio:
|
|
24
|
+
valid_ratios = ['1:1', '3:2', '2:3', '4:3', '3:4', '16:9', '9:16', '21:9', '9:21']
|
|
25
|
+
if aspect_ratio not in valid_ratios:
|
|
26
|
+
raise ValueError(f"Invalid aspect_ratio. Must be one of: {', '.join(valid_ratios)}")
|
|
27
|
+
payload['aspect_ratio'] = aspect_ratio
|
|
28
|
+
|
|
29
|
+
# Output format (only if specified)
|
|
30
|
+
fmt = kwargs.get('format') or kwargs.get('output_format')
|
|
31
|
+
if fmt:
|
|
32
|
+
valid_formats = ['jpg', 'png', 'webp']
|
|
33
|
+
fmt_lower = fmt.lower()
|
|
34
|
+
if fmt_lower not in valid_formats:
|
|
35
|
+
raise ValueError(f"Invalid format. Must be one of: {', '.join(valid_formats)}")
|
|
36
|
+
payload['output_format'] = fmt_lower
|
|
37
|
+
|
|
38
|
+
# Reference images (optional, up to 4)
|
|
39
|
+
image_input = kwargs.get('image_input') or kwargs.get('reference_images')
|
|
40
|
+
if image_input:
|
|
41
|
+
if isinstance(image_input, str):
|
|
42
|
+
image_input = [image_input]
|
|
43
|
+
if len(image_input) > 4:
|
|
44
|
+
raise ValueError("Maximum 4 reference images allowed")
|
|
45
|
+
payload['image_input'] = image_input
|
|
46
|
+
|
|
47
|
+
return payload
|