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.
Files changed (53) hide show
  1. package/.claude-plugin/marketplace.json +11 -53
  2. package/cli/bin/cli.js +31 -8
  3. package/cli/src/commands/info.js +15 -11
  4. package/cli/src/commands/install.js +53 -29
  5. package/cli/src/commands/list.js +28 -22
  6. package/cli/src/commands/uninstall.js +23 -16
  7. package/cli/src/i18n/index.js +96 -0
  8. package/cli/src/i18n/locales/en.js +107 -0
  9. package/cli/src/i18n/locales/ko.js +107 -0
  10. package/cli/src/lib/config.js +116 -1
  11. package/cli/src/lib/installer.js +106 -3
  12. package/package.json +1 -1
  13. package/plugins/brand-analytics/plugin.json +9 -0
  14. package/plugins/campaign-orchestration/plugin.json +9 -0
  15. package/plugins/common/plugin.json +9 -0
  16. package/plugins/common/skills/kie-image-generator/.env.example +4 -0
  17. package/plugins/common/skills/kie-image-generator/SKILL.md +281 -0
  18. package/plugins/common/skills/kie-image-generator/references/api_docs.md +358 -0
  19. package/plugins/common/skills/kie-image-generator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
  20. package/plugins/common/skills/kie-image-generator/scripts/generate_image.py +285 -0
  21. package/plugins/common/skills/kie-image-generator/scripts/models/__init__.py +19 -0
  22. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/__init__.cpython-313.pyc +0 -0
  23. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/flux_kontext.cpython-313.pyc +0 -0
  24. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/gpt4o.cpython-313.pyc +0 -0
  25. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/ideogram.cpython-313.pyc +0 -0
  26. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/imagen.cpython-313.pyc +0 -0
  27. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/nano_banana.cpython-313.pyc +0 -0
  28. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/nano_banana_edit.cpython-313.pyc +0 -0
  29. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/nano_banana_pro.cpython-313.pyc +0 -0
  30. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/seedream.cpython-313.pyc +0 -0
  31. package/plugins/common/skills/kie-image-generator/scripts/models/__pycache__/seedream_edit.cpython-313.pyc +0 -0
  32. package/plugins/common/skills/kie-image-generator/scripts/models/flux_kontext.py +36 -0
  33. package/plugins/common/skills/kie-image-generator/scripts/models/gpt4o.py +36 -0
  34. package/plugins/common/skills/kie-image-generator/scripts/models/ideogram.py +85 -0
  35. package/plugins/common/skills/kie-image-generator/scripts/models/imagen.py +48 -0
  36. package/plugins/common/skills/kie-image-generator/scripts/models/nano_banana.py +40 -0
  37. package/plugins/common/skills/kie-image-generator/scripts/models/nano_banana_edit.py +55 -0
  38. package/plugins/common/skills/kie-image-generator/scripts/models/nano_banana_pro.py +47 -0
  39. package/plugins/common/skills/kie-image-generator/scripts/models/seedream.py +51 -0
  40. package/plugins/common/skills/kie-image-generator/scripts/models/seedream_edit.py +66 -0
  41. package/plugins/common/skills/kie-image-generator/scripts/utils.py +706 -0
  42. package/plugins/common/skills/kie-video-generator/SKILL.md +258 -0
  43. package/plugins/common/skills/kie-video-generator/references/api_docs.md +202 -0
  44. package/plugins/common/skills/kie-video-generator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
  45. package/plugins/common/skills/kie-video-generator/scripts/generate_video.py +356 -0
  46. package/plugins/common/skills/kie-video-generator/scripts/models/__init__.py +4 -0
  47. package/plugins/common/skills/kie-video-generator/scripts/utils.py +617 -0
  48. package/plugins/content-creation/plugin.json +9 -0
  49. package/plugins/creative-production/plugin.json +9 -0
  50. package/plugins/customer-segmentation/plugin.json +9 -0
  51. package/plugins/market-research/plugin.json +9 -0
  52. package/plugins/persona-builder/plugin.json +9 -0
  53. 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
+ ]
@@ -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