@danhachuel/thunderbolt 0.7.46 → 0.7.47

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/app/main.py CHANGED
@@ -5924,6 +5924,8 @@ def render_thumbnails():
5924
5924
  )
5925
5925
  st.success("Thumbnail gerada com sucesso.")
5926
5926
  st.rerun()
5927
+ except MediaGenerationError as exc:
5928
+ st.error(format_media_generation_error(exc, operation="gerar a imagem da thumbnail"))
5927
5929
  except ThumbnailGenerationError as exc:
5928
5930
  st.error(str(exc))
5929
5931
 
@@ -5955,6 +5957,8 @@ def render_thumbnails():
5955
5957
  )
5956
5958
  st.success("Prompt da thumbnail e imagem actualizados.")
5957
5959
  st.rerun()
5960
+ except MediaGenerationError as exc:
5961
+ st.error(format_media_generation_error(exc, operation="refazer o prompt e gerar a imagem da thumbnail"))
5958
5962
  except (CreativeGenerationError, ThumbnailGenerationError) as exc:
5959
5963
  st.error(str(exc))
5960
5964
 
@@ -461,7 +461,6 @@ 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,
465
464
  )
466
465
  except Exception as exc:
467
466
  raise MediaGenerationError(str(exc)) from exc
@@ -98,7 +98,6 @@ 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,
102
101
  )
103
102
  return generate_image_from_pool(
104
103
  settings,
@@ -1355,10 +1354,8 @@ def _run_task(task: dict[str, Any]) -> dict[str, Any]:
1355
1354
  blueprint = _blueprint_for_channel(channel)
1356
1355
  if not blueprint and (task.get("blueprint_id") or task.get("blueprint_name")):
1357
1356
  blueprint = {"id": str(task.get("blueprint_id") or ""), "name": str(task.get("blueprint_name") or task.get("blueprint_id") or "")}
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)
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)
1362
1359
  if visual_blueprint.get("content"):
1363
1360
  blueprint = {**blueprint, "thumbnail_blueprint_rules": visual_blueprint["content"]}
1364
1361
  route = _normalise_video_route(task, settings)
@@ -53,13 +53,11 @@ 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
- platform_raw = str(platform or "").strip().casefold()
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
56
  if raw in {"portrait", "portrait 9:16", "vertical", "shorts", "9:16", "tiktok", "reels"}:
62
57
  return VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
58
+ platform_raw = str(platform or "").strip().casefold()
59
+ if platform_raw in {"tiktok", "instagram", "instagram reels", "shorts"} and not raw:
60
+ return VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
63
61
  return HORIZONTAL_GENERIC_THUMBNAIL_BLUEPRINT_ID
64
62
 
65
63
 
@@ -80,6 +78,7 @@ def thumbnail_blueprint_for_channel(channel: Mapping[str, Any], format_value: An
80
78
 
81
79
  def thumbnail_blueprint_for_task(channel: Mapping[str, Any], task: Mapping[str, Any]) -> dict[str, Any]:
82
80
  """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")
83
82
  direct = str(task.get("thumbnail_blueprint_id") or "").strip()
84
83
  if direct and direct not in {
85
84
  "Generic_Thumbnail_Blueprint",
@@ -87,10 +86,7 @@ def thumbnail_blueprint_for_task(channel: Mapping[str, Any], task: Mapping[str,
87
86
  VERTICAL_GENERIC_THUMBNAIL_BLUEPRINT_ID,
88
87
  }:
89
88
  return resolve_thumbnail_blueprint(direct)
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)
89
+ return thumbnail_blueprint_for_channel({**channel, "thumbnail_blueprint_id": ""}, format_value)
94
90
 
95
91
 
96
92
  def thumbnail_blueprint_for_blueprint(blueprint_id: Any, format_value: Any = "") -> dict[str, Any]:
@@ -39,14 +39,10 @@ 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
- if re.search(r"\b9\s*:\s*16\b|\bvertical\b|\bportrait\b", blueprint_content, flags=re.IGNORECASE):
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):
43
44
  return "9:16"
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):
45
+ if re.search(r"\b16\s*:\s*9\b|\blandscape\b|\bwide\b", source, flags=re.IGNORECASE):
50
46
  return "16:9"
51
47
  return fallback if fallback in {"16:9", "9:16"} else DEFAULT_ASPECT_RATIO
52
48
 
@@ -195,7 +191,6 @@ def generate_thumbnail_image(
195
191
  lettering_text: str = "",
196
192
  lettering_prompt: str = "",
197
193
  aspect_ratio: str = DEFAULT_ASPECT_RATIO,
198
- lock_aspect_ratio: bool = False,
199
194
  ) -> Path:
200
195
  api_key = str(settings.get("gemini_image_api_key") or "").strip()
201
196
  if not api_key:
@@ -209,10 +204,7 @@ def generate_thumbnail_image(
209
204
  lettering_text=lettering_text,
210
205
  lettering_prompt=lettering_prompt,
211
206
  )
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
- )
207
+ effective_aspect_ratio = infer_thumbnail_aspect_ratio(clean_prompt, fallback=aspect_ratio)
216
208
 
217
209
  model = str(settings.get("gemini_image_model") or DEFAULT_GEMINI_IMAGE_MODEL).strip()
218
210
  image_size = DEFAULT_IMAGE_SIZE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.46",
3
+ "version": "0.7.47",
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",