@danhachuel/thunderbolt 0.3.99 → 0.3.100

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
@@ -2726,6 +2726,11 @@ def render_music_creation():
2726
2726
  st.error(str(exc))
2727
2727
 
2728
2728
 
2729
+ def render_custom_music_voices() -> None:
2730
+ """Reserved view for future reusable custom music-voice blueprints."""
2731
+ st.title("Vozes Personalizadas, Funcionará como um Blueprint")
2732
+
2733
+
2729
2734
  def render_scripts():
2730
2735
  st.title("Roteiros")
2731
2736
  st.caption("Produza e guarde roteiros de vídeos ou letras de músicas a partir dos Blueprints do Thunderbolt.")
@@ -6250,6 +6255,21 @@ def render_settings():
6250
6255
  saved_lyria_model = str(settings.get("lyria_model") or lyria_models[0])
6251
6256
  lyria_model = st.selectbox("Modelo Google Lyria", lyria_models, index=lyria_models.index(saved_lyria_model) if saved_lyria_model in lyria_models else 0, key="settings_lyria_model")
6252
6257
 
6258
+ def save_google_lyria() -> None:
6259
+ settings.update({"lyria_api_key": lyria_api_key.strip(), "lyria_model": lyria_model})
6260
+ write_json("settings.json", settings)
6261
+
6262
+ if st.form_submit_button("Guardar Google Lyria", type="primary", use_container_width=True, key="save_google_lyria"):
6263
+ save_google_lyria()
6264
+ st.success("Google Lyria guardado.")
6265
+ _render_api_test_control(
6266
+ settings,
6267
+ "voice:google_lyria",
6268
+ lambda: test_voice_provider("google_lyria", {"lyria_api_key": lyria_api_key, "lyria_model": lyria_model}),
6269
+ widget_key="api_test_voice_google_lyria",
6270
+ persist_callback=save_google_lyria,
6271
+ )
6272
+
6253
6273
  with st.expander("Publicação através do Upload-Post", expanded=False):
6254
6274
  upload_post_enabled = st.checkbox("Activar Upload-Post", bool(settings.get("upload_post_enabled", False)))
6255
6275
  upload_post_api_key = text_setting("Upload-Post API key", "upload_post_api_key", secret=True)
@@ -6968,6 +6988,7 @@ def main():
6968
6988
  music_items = [
6969
6989
  ("Criação de Músicas", ":material/music_note:", "Criação de Músicas"),
6970
6990
  ("Music Backlog", ":material/queue_music:", "Music Backlog"),
6991
+ ("Vozes Personalizadas, Funcionará como um Blueprint", ":material/record_voice_over:", "Vozes Personalizadas, Funcionará como um Blueprint"),
6971
6992
  ("Upload Música", ":material/library_music:", "Upload Música"),
6972
6993
  ]
6973
6994
  models_ai_items = [
@@ -7091,6 +7112,7 @@ def main():
7091
7112
  "Backlog Vídeos": render_videos,
7092
7113
  "Criação de Músicas": render_music_creation,
7093
7114
  "Music Backlog": render_music_backlog,
7115
+ "Vozes Personalizadas, Funcionará como um Blueprint": render_custom_music_voices,
7094
7116
  "Upload Música": render_music_upload,
7095
7117
  "Roteiros": render_scripts,
7096
7118
  "Thumbnails": render_thumbnails,
@@ -128,6 +128,20 @@ def test_nano_banana_credentials(api_key: str, model: str) -> dict[str, Any]:
128
128
  )
129
129
 
130
130
 
131
+ def test_google_lyria_credentials(api_key: str, model: str) -> dict[str, Any]:
132
+ """Validate access to the selected Lyria model without requesting audio generation."""
133
+ api_key = str(api_key or "").strip()
134
+ model = str(model or "").strip()
135
+ if not api_key:
136
+ return _missing("Introduza a Google Lyria API key antes de testar.")
137
+ if not model:
138
+ return _result("missing", "Seleccione o modelo Google Lyria antes de testar.")
139
+ return _get(
140
+ f"https://generativelanguage.googleapis.com/v1beta/models/{quote(model.removeprefix('models/'), safe='')}",
141
+ headers={"x-goog-api-key": api_key},
142
+ )
143
+
144
+
131
145
  def test_media_provider_card(card: Mapping[str, Any]) -> dict[str, Any]:
132
146
  """Run a bounded, non-generative check for an image/video provider card."""
133
147
  source = dict(card) if isinstance(card, Mapping) else {}
@@ -318,6 +332,8 @@ def test_voice_provider(provider: str, settings: dict[str, Any]) -> dict[str, An
318
332
  return test_openai_compatible_voice_credentials("Sonilo", settings.get("sonilo_api_key", ""), settings.get("sonilo_base_url", ""))
319
333
  if provider == "suno":
320
334
  return test_suno_credentials(settings.get("suno_api_key", ""), settings.get("suno_api_base_url", ""), settings.get("suno_api_endpoint", ""))
335
+ if provider == "google_lyria":
336
+ return test_google_lyria_credentials(settings.get("lyria_api_key", ""), settings.get("lyria_model", ""))
321
337
  return _unsupported("Este provider de voz não tem diagnóstico remoto configurado.")
322
338
 
323
339
 
@@ -325,6 +341,7 @@ __all__ = [
325
341
  "test_apify_credentials",
326
342
  "test_azure_speech_credentials",
327
343
  "test_elevenlabs_credentials",
344
+ "test_google_lyria_credentials",
328
345
  "test_innertube_api_key",
329
346
  "test_kaggle_credentials",
330
347
  "test_influencer_database",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.3.99",
3
+ "version": "0.3.100",
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",