@danhachuel/thunderbolt 0.3.99 → 0.4.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/app/main.py +37 -4
- package/hermes_ui/api_key_tests.py +17 -0
- package/package.json +1 -1
package/app/main.py
CHANGED
|
@@ -23,6 +23,17 @@ try:
|
|
|
23
23
|
except (OSError, json.JSONDecodeError):
|
|
24
24
|
APP_VERSION = ""
|
|
25
25
|
|
|
26
|
+
|
|
27
|
+
def display_version(version: str) -> str:
|
|
28
|
+
"""Keep the project version label in the two-digit patch convention."""
|
|
29
|
+
parts = str(version or "").strip().split(".")
|
|
30
|
+
if len(parts) == 3 and all(part.isdigit() for part in parts):
|
|
31
|
+
return f"{int(parts[0])}.{int(parts[1])}.{int(parts[2]):02d}"
|
|
32
|
+
return str(version or "")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
APP_VERSION_LABEL = display_version(APP_VERSION)
|
|
36
|
+
|
|
26
37
|
from hermes_ui.domain import STAGES, create_batch, create_channel, create_tasks_for_batch, delete_channel, delete_task, pipeline_summary, retry_task_with_current_settings, set_channel_defaults, transition_task, update_channel, update_channel_video
|
|
27
38
|
from hermes_ui.drafts import list_drafts, save_draft
|
|
28
39
|
from hermes_ui.automation_worker import load_worker_status
|
|
@@ -1303,11 +1314,11 @@ def render_dashboard():
|
|
|
1303
1314
|
st.session_state[checked_at_key] = time.monotonic()
|
|
1304
1315
|
version_status = st.session_state[cache_key]
|
|
1305
1316
|
if version_status.update_available:
|
|
1306
|
-
st.info(f"Nova versão disponível: {version_status.latest_version}. A versão actual é {
|
|
1317
|
+
st.info(f"Nova versão disponível: {display_version(version_status.latest_version)}. A versão actual é {APP_VERSION_LABEL or 'desconhecida'}.")
|
|
1307
1318
|
elif version_status.error:
|
|
1308
|
-
st.caption(f"Versão actual: {
|
|
1319
|
+
st.caption(f"Versão actual: {APP_VERSION_LABEL or 'desconhecida'} · verificação de actualização indisponível.")
|
|
1309
1320
|
else:
|
|
1310
|
-
st.caption(f"Versão actual: {
|
|
1321
|
+
st.caption(f"Versão actual: {APP_VERSION_LABEL or 'desconhecida'} · já está actualizada ({display_version(version_status.latest_version)}).")
|
|
1311
1322
|
update_result = st.session_state.get("home_update_result")
|
|
1312
1323
|
if update_result is not None:
|
|
1313
1324
|
if update_result.ok:
|
|
@@ -2726,6 +2737,11 @@ def render_music_creation():
|
|
|
2726
2737
|
st.error(str(exc))
|
|
2727
2738
|
|
|
2728
2739
|
|
|
2740
|
+
def render_custom_music_voices() -> None:
|
|
2741
|
+
"""Reserved view for future reusable custom music-voice blueprints."""
|
|
2742
|
+
st.title("Vozes Personalizadas, Funcionará como um Blueprint")
|
|
2743
|
+
|
|
2744
|
+
|
|
2729
2745
|
def render_scripts():
|
|
2730
2746
|
st.title("Roteiros")
|
|
2731
2747
|
st.caption("Produza e guarde roteiros de vídeos ou letras de músicas a partir dos Blueprints do Thunderbolt.")
|
|
@@ -6250,6 +6266,21 @@ def render_settings():
|
|
|
6250
6266
|
saved_lyria_model = str(settings.get("lyria_model") or lyria_models[0])
|
|
6251
6267
|
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
6268
|
|
|
6269
|
+
def save_google_lyria() -> None:
|
|
6270
|
+
settings.update({"lyria_api_key": lyria_api_key.strip(), "lyria_model": lyria_model})
|
|
6271
|
+
write_json("settings.json", settings)
|
|
6272
|
+
|
|
6273
|
+
if st.form_submit_button("Guardar Google Lyria", type="primary", use_container_width=True, key="save_google_lyria"):
|
|
6274
|
+
save_google_lyria()
|
|
6275
|
+
st.success("Google Lyria guardado.")
|
|
6276
|
+
_render_api_test_control(
|
|
6277
|
+
settings,
|
|
6278
|
+
"voice:google_lyria",
|
|
6279
|
+
lambda: test_voice_provider("google_lyria", {"lyria_api_key": lyria_api_key, "lyria_model": lyria_model}),
|
|
6280
|
+
widget_key="api_test_voice_google_lyria",
|
|
6281
|
+
persist_callback=save_google_lyria,
|
|
6282
|
+
)
|
|
6283
|
+
|
|
6253
6284
|
with st.expander("Publicação através do Upload-Post", expanded=False):
|
|
6254
6285
|
upload_post_enabled = st.checkbox("Activar Upload-Post", bool(settings.get("upload_post_enabled", False)))
|
|
6255
6286
|
upload_post_api_key = text_setting("Upload-Post API key", "upload_post_api_key", secret=True)
|
|
@@ -6968,6 +6999,7 @@ def main():
|
|
|
6968
6999
|
music_items = [
|
|
6969
7000
|
("Criação de Músicas", ":material/music_note:", "Criação de Músicas"),
|
|
6970
7001
|
("Music Backlog", ":material/queue_music:", "Music Backlog"),
|
|
7002
|
+
("Vozes Personalizadas, Funcionará como um Blueprint", ":material/record_voice_over:", "Vozes Personalizadas, Funcionará como um Blueprint"),
|
|
6971
7003
|
("Upload Música", ":material/library_music:", "Upload Música"),
|
|
6972
7004
|
]
|
|
6973
7005
|
models_ai_items = [
|
|
@@ -7072,7 +7104,7 @@ def main():
|
|
|
7072
7104
|
navigate(target)
|
|
7073
7105
|
|
|
7074
7106
|
with st.sidebar:
|
|
7075
|
-
version_markup = f'<span class="tb-brand-version">{
|
|
7107
|
+
version_markup = f'<span class="tb-brand-version">{APP_VERSION_LABEL}</span>' if APP_VERSION_LABEL else ""
|
|
7076
7108
|
st.markdown(f'<div class="tb-brand"><span class="tb-brand-name">Thunderbolt</span>{version_markup}</div>', unsafe_allow_html=True)
|
|
7077
7109
|
for target, icon, label in top_pages:
|
|
7078
7110
|
children = groups.get(target)
|
|
@@ -7091,6 +7123,7 @@ def main():
|
|
|
7091
7123
|
"Backlog Vídeos": render_videos,
|
|
7092
7124
|
"Criação de Músicas": render_music_creation,
|
|
7093
7125
|
"Music Backlog": render_music_backlog,
|
|
7126
|
+
"Vozes Personalizadas, Funcionará como um Blueprint": render_custom_music_voices,
|
|
7094
7127
|
"Upload Música": render_music_upload,
|
|
7095
7128
|
"Roteiros": render_scripts,
|
|
7096
7129
|
"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