@danhachuel/thunderbolt 0.7.44 → 0.7.46

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.
@@ -461,6 +461,7 @@ def generate_image_for_card(
461
461
  lettering_prompt=lettering_prompt,
462
462
  reference_image=reference_image,
463
463
  aspect_ratio=aspect_ratio,
464
+ lock_aspect_ratio=True,
464
465
  )
465
466
  except Exception as exc:
466
467
  raise MediaGenerationError(str(exc)) from exc
@@ -98,6 +98,7 @@ def _generate_pipeline_thumbnail(
98
98
  lettering_text=lettering_text,
99
99
  lettering_prompt=lettering_prompt,
100
100
  aspect_ratio=infer_thumbnail_aspect_ratio(prompt, thumbnail_blueprint),
101
+ lock_aspect_ratio=True,
101
102
  )
102
103
  return generate_image_from_pool(
103
104
  settings,
@@ -1354,8 +1355,10 @@ def _run_task(task: dict[str, Any]) -> dict[str, Any]:
1354
1355
  blueprint = _blueprint_for_channel(channel)
1355
1356
  if not blueprint and (task.get("blueprint_id") or task.get("blueprint_name")):
1356
1357
  blueprint = {"id": str(task.get("blueprint_id") or ""), "name": str(task.get("blueprint_name") or task.get("blueprint_id") or "")}
1357
- visual_format = task.get("format") or ("portrait" if str(task.get("platform") or "").casefold() in {"tiktok", "instagram"} else "wide")
1358
- visual_blueprint = thumbnail_blueprint_for_channel(channel, visual_format)
1358
+ channel_visual_context = {**channel}
1359
+ if not channel_visual_context.get("platform") and task.get("platform"):
1360
+ channel_visual_context["platform"] = task.get("platform")
1361
+ visual_blueprint = thumbnail_blueprint_for_channel(channel_visual_context)
1359
1362
  if visual_blueprint.get("content"):
1360
1363
  blueprint = {**blueprint, "thumbnail_blueprint_rules": visual_blueprint["content"]}
1361
1364
  route = _normalise_video_route(task, settings)
@@ -53,10 +53,12 @@ def resolve_thumbnail_blueprint(identifier: Any) -> dict[str, Any]:
53
53
 
54
54
  def _generic_thumbnail_blueprint_id(format_value: Any = "", platform: Any = "") -> str:
55
55
  raw = str(format_value or "").strip().casefold()
56
- if raw in {"portrait", "portrait 9:16", "vertical", "shorts", "9:16", "tiktok", "reels"}:
57
- return VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
58
56
  platform_raw = str(platform or "").strip().casefold()
59
- if platform_raw in {"tiktok", "instagram", "instagram reels", "shorts"} and not raw:
57
+ if platform_raw in {"tiktok", "instagram", "instagram reels", "instagram_reels", "reels", "shorts"}:
58
+ return VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
59
+ if platform_raw in {"youtube", "youtube channel", "youtube_channels"}:
60
+ return HORIZONTAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
61
+ if raw in {"portrait", "portrait 9:16", "vertical", "shorts", "9:16", "tiktok", "reels"}:
60
62
  return VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
61
63
  return HORIZONTAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
62
64
 
@@ -78,7 +80,6 @@ def thumbnail_blueprint_for_channel(channel: Mapping[str, Any], format_value: An
78
80
 
79
81
  def thumbnail_blueprint_for_task(channel: Mapping[str, Any], task: Mapping[str, Any]) -> dict[str, Any]:
80
82
  """Resolve a task thumbnail, replacing stale generic orientation defaults."""
81
- format_value = task.get("format") or (task.get("generation_settings") or {}).get("video_aspect_ratio")
82
83
  direct = str(task.get("thumbnail_blueprint_id") or "").strip()
83
84
  if direct and direct not in {
84
85
  "Generic_Thumbnail_Blueprint",
@@ -86,7 +87,10 @@ def thumbnail_blueprint_for_task(channel: Mapping[str, Any], task: Mapping[str,
86
87
  VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID,
87
88
  }:
88
89
  return resolve_thumbnail_blueprint(direct)
89
- return thumbnail_blueprint_for_channel({**channel, "thumbnail_blueprint_id": ""}, format_value)
90
+ channel_context = {**channel, "thumbnail_blueprint_id": ""}
91
+ if not channel_context.get("platform") and task.get("platform"):
92
+ channel_context["platform"] = task.get("platform")
93
+ return thumbnail_blueprint_for_channel(channel_context)
90
94
 
91
95
 
92
96
  def thumbnail_blueprint_for_blueprint(blueprint_id: Any, format_value: Any = "") -> dict[str, Any]:
@@ -39,10 +39,14 @@ def infer_thumbnail_aspect_ratio(
39
39
  ) -> str:
40
40
  """Resolve the requested thumbnail orientation without trusting provider defaults."""
41
41
  blueprint_content = str((blueprint or {}).get("content") or "")
42
- source = f"{blueprint_content}\n{str(prompt or '')}"
43
- if re.search(r"\b9\s*:\s*16\b|\bvertical\b|\bportrait\b", source, flags=re.IGNORECASE):
42
+ if re.search(r"\b9\s*:\s*16\b|\bvertical\b|\bportrait\b", blueprint_content, flags=re.IGNORECASE):
44
43
  return "9:16"
45
- if re.search(r"\b16\s*:\s*9\b|\blandscape\b|\bwide\b", source, flags=re.IGNORECASE):
44
+ if re.search(r"\b16\s*:\s*9\b|\blandscape\b|\bwide\b", blueprint_content, flags=re.IGNORECASE):
45
+ return "16:9"
46
+ prompt_text = str(prompt or "")
47
+ if re.search(r"\b9\s*:\s*16\b|\bvertical\b|\bportrait\b", prompt_text, flags=re.IGNORECASE):
48
+ return "9:16"
49
+ if re.search(r"\b16\s*:\s*9\b|\blandscape\b|\bwide\b", prompt_text, flags=re.IGNORECASE):
46
50
  return "16:9"
47
51
  return fallback if fallback in {"16:9", "9:16"} else DEFAULT_ASPECT_RATIO
48
52
 
@@ -191,6 +195,7 @@ def generate_thumbnail_image(
191
195
  lettering_text: str = "",
192
196
  lettering_prompt: str = "",
193
197
  aspect_ratio: str = DEFAULT_ASPECT_RATIO,
198
+ lock_aspect_ratio: bool = False,
194
199
  ) -> Path:
195
200
  api_key = str(settings.get("gemini_image_api_key") or "").strip()
196
201
  if not api_key:
@@ -204,7 +209,10 @@ def generate_thumbnail_image(
204
209
  lettering_text=lettering_text,
205
210
  lettering_prompt=lettering_prompt,
206
211
  )
207
- effective_aspect_ratio = infer_thumbnail_aspect_ratio(clean_prompt, fallback=aspect_ratio)
212
+ effective_aspect_ratio = (
213
+ aspect_ratio if lock_aspect_ratio and aspect_ratio in {"16:9", "9:16"}
214
+ else infer_thumbnail_aspect_ratio(clean_prompt, fallback=aspect_ratio)
215
+ )
208
216
 
209
217
  model = str(settings.get("gemini_image_model") or DEFAULT_GEMINI_IMAGE_MODEL).strip()
210
218
  image_size = DEFAULT_IMAGE_SIZE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.44",
3
+ "version": "0.7.46",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "license": "MIT",
6
6
  "main": "scripts/cli.mjs",