@danhachuel/thunderbolt 0.2.98 → 0.2.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 +14 -10
- package/package.json +1 -1
package/app/main.py
CHANGED
|
@@ -38,6 +38,7 @@ from hermes_ui.music import list_music_files, materialize_suno_audio, request_su
|
|
|
38
38
|
from hermes_ui.media_downloader import AUDIO_FORMATS, VIDEO_CONTAINERS, VIDEO_QUALITY_OPTIONS, MediaDownloadError, build_download_options, clear_media_download_history, dependency_status, download_media, list_media_downloads, media_download_file
|
|
39
39
|
from hermes_ui.notifications import clear_notifications, list_notifications, mark_all_notifications_read, mark_notification_read, notification_event_catalog, notification_preferences, record_notification, reconcile_persisted_notifications, save_notification_preferences, unread_notification_count
|
|
40
40
|
from hermes_ui.languages import LANGUAGE_CODES, LANGUAGE_FLAG_DATA_URIS, language_code, language_label, ui_language_menu_label, ui_text, video_language_label, video_language_options
|
|
41
|
+
|
|
41
42
|
from hermes_ui.script_documents import list_script_documents, read_script_document, save_script_document, script_storage_path
|
|
42
43
|
from hermes_ui.script_generation import generate_script_document
|
|
43
44
|
from hermes_ui.voice_preview import DEFAULT_SAMPLE, load_preview_file, synthesize_preview
|
|
@@ -55,6 +56,8 @@ from integrations.local_runtime import MoneyPrinterRuntime
|
|
|
55
56
|
from integrations.moneyprinter_config import sync_moneyprinter_config
|
|
56
57
|
from integrations.openai_model_discovery import DEFAULT_NVIDIA_NIM_BASE_URL, ModelDiscoveryError, fetch_openai_compatible_models
|
|
57
58
|
|
|
59
|
+
DEFAULT_UI_LANGUAGE = "en"
|
|
60
|
+
|
|
58
61
|
AI_STYLE_OPTIONS = [
|
|
59
62
|
"Natural Realista",
|
|
60
63
|
"Cocomelon style",
|
|
@@ -229,8 +232,9 @@ def current_ui_language() -> str:
|
|
|
229
232
|
if requested:
|
|
230
233
|
normalized = language_code(requested)
|
|
231
234
|
else:
|
|
232
|
-
|
|
233
|
-
|
|
235
|
+
# A raiz do launcher é o idioma padrão do sistema. A mudança explícita
|
|
236
|
+
# de idioma continua a chegar por ?lang=..., incluindo a rota /en.
|
|
237
|
+
normalized = DEFAULT_UI_LANGUAGE
|
|
234
238
|
st.session_state["ui_language"] = normalized
|
|
235
239
|
return normalized
|
|
236
240
|
|
|
@@ -3579,7 +3583,7 @@ def render_settings():
|
|
|
3579
3583
|
st.subheader("API Keys")
|
|
3580
3584
|
port = st.number_input("Porta Streamlit", 1, 65535, int(settings.get("port", 3030)))
|
|
3581
3585
|
moneyprinter_path = st.text_input("Pasta do motor de vídeo", settings.get("moneyprinter_path", ""), key="settings_moneyprinter_path")
|
|
3582
|
-
with st.expander("Niche Finder — execução remota no Kaggle", expanded=
|
|
3586
|
+
with st.expander("Niche Finder — execução remota no Kaggle", expanded=False):
|
|
3583
3587
|
st.caption("O dataset permanece no Kaggle. O Thunderbolt usa estas credenciais apenas para publicar/executar a kernel e obter os resultados pequenos da análise.")
|
|
3584
3588
|
kaggle_cols = st.columns(3)
|
|
3585
3589
|
with kaggle_cols[0]:
|
|
@@ -3589,7 +3593,7 @@ def render_settings():
|
|
|
3589
3593
|
with kaggle_cols[2]:
|
|
3590
3594
|
kaggle_kernel_slug = text_setting("Slug da kernel", "kaggle_kernel_slug", help_text="Identificador da kernel remota, por exemplo thunderbolt-niche-finder.")
|
|
3591
3595
|
|
|
3592
|
-
with st.expander("Niche Finder — execução através da Apify", expanded=
|
|
3596
|
+
with st.expander("Niche Finder — execução através da Apify", expanded=False):
|
|
3593
3597
|
st.caption("O token fica guardado apenas no storage local. A aba Niche Finder Apify só usa este serviço depois de clicar no botão de pesquisa.")
|
|
3594
3598
|
apify_cols = st.columns(4)
|
|
3595
3599
|
with apify_cols[0]:
|
|
@@ -3601,7 +3605,7 @@ def render_settings():
|
|
|
3601
3605
|
with apify_cols[3]:
|
|
3602
3606
|
apify_run_timeout = st.number_input("Limite da execução (s)", min_value=30, max_value=7200, value=int(settings.get("apify_run_timeout_seconds", 900)), step=30)
|
|
3603
3607
|
|
|
3604
|
-
with st.expander("Nano Banana — geração de thumbnails", expanded=
|
|
3608
|
+
with st.expander("Nano Banana — geração de thumbnails", expanded=False):
|
|
3605
3609
|
st.caption("A Nano Banana gera a imagem final das thumbnails a partir da variante escolhida. A chave é guardada apenas no storage local e é distinta da chave do Gemini usado como LLM textual.")
|
|
3606
3610
|
nano_cols = st.columns(2)
|
|
3607
3611
|
with nano_cols[0]:
|
|
@@ -3611,7 +3615,7 @@ def render_settings():
|
|
|
3611
3615
|
gemini_image_aspect_ratio = st.selectbox("Proporção da thumbnail", ["16:9", "9:16", "1:1", "4:5"], index=["16:9", "9:16", "1:1", "4:5"].index(str(settings.get("gemini_image_aspect_ratio") or "16:9")) if str(settings.get("gemini_image_aspect_ratio") or "16:9") in {"16:9", "9:16", "1:1", "4:5"} else 0)
|
|
3612
3616
|
gemini_image_size = st.selectbox("Tamanho da imagem", ["1K", "2K", "4K"], index=["1K", "2K", "4K"].index(str(settings.get("gemini_image_size") or "1K")) if str(settings.get("gemini_image_size") or "1K") in {"1K", "2K", "4K"} else 0)
|
|
3613
3617
|
|
|
3614
|
-
with st.expander("LLM — providers e modelos", expanded=
|
|
3618
|
+
with st.expander("LLM — providers e modelos", expanded=False):
|
|
3615
3619
|
provider_options = ["openai", "moonshot", "shengsuanyun", "gemini", "deepseek", "qwen", "azure", "volcengine", "grok", "minimax", "mimo", "cloudflare", "modelscope", "aihubmix", "aimlapi", "evolink", "ollama", "oneapi", "litellm", "groq", "pollinations"]
|
|
3616
3620
|
current_llm_provider = str(settings.get("llm_provider") or DEFAULT_LLM_PROVIDER).strip().lower()
|
|
3617
3621
|
llm_provider = st.selectbox("LLM provider", provider_options, index=provider_options.index(current_llm_provider) if current_llm_provider in provider_options else 0)
|
|
@@ -3667,7 +3671,7 @@ def render_settings():
|
|
|
3667
3671
|
with cols[2]:
|
|
3668
3672
|
settings[f"{prefix}_model_name"] = text_setting("Model", f"{prefix}_model_name")
|
|
3669
3673
|
|
|
3670
|
-
with st.expander("Voz, TTS e música — Azure Speech, restantes serviços e Suno", expanded=
|
|
3674
|
+
with st.expander("Voz, TTS e música — Azure Speech, restantes serviços e Suno", expanded=False):
|
|
3671
3675
|
cols = st.columns(2)
|
|
3672
3676
|
with cols[0]:
|
|
3673
3677
|
azure_speech_key = text_setting("Azure Speech key", "azure_speech_key", secret=True)
|
|
@@ -3690,19 +3694,19 @@ def render_settings():
|
|
|
3690
3694
|
suno_api_base_url = text_setting("Suno API Base URL", "suno_api_base_url", help_text="Use o endpoint compatível fornecido pelo seu acesso Suno; não é inventado pelo Thunderbolt.")
|
|
3691
3695
|
suno_api_endpoint = text_setting("Suno API endpoint", "suno_api_endpoint", help_text="Ex.: /api/generate")
|
|
3692
3696
|
|
|
3693
|
-
with st.expander("TikTok for Developers — Client ID e Client Secret", expanded=
|
|
3697
|
+
with st.expander("TikTok for Developers — Client ID e Client Secret", expanded=False):
|
|
3694
3698
|
st.caption("Apenas as credenciais da aplicação ficam nesta UI. Redirect URI, scopes, autorização e tokens são geridos no TikTok for Developers Playground.")
|
|
3695
3699
|
tiktok_client_key = text_setting("TikTok Client ID", "tiktok_client_key", secret=True)
|
|
3696
3700
|
tiktok_client_secret = text_setting("TikTok Client Secret", "tiktok_client_secret", secret=True)
|
|
3697
3701
|
|
|
3698
|
-
with st.expander("Publicação através do Upload-Post"):
|
|
3702
|
+
with st.expander("Publicação através do Upload-Post", expanded=False):
|
|
3699
3703
|
upload_post_enabled = st.checkbox("Activar Upload-Post", bool(settings.get("upload_post_enabled", False)))
|
|
3700
3704
|
upload_post_api_key = text_setting("Upload-Post API key", "upload_post_api_key", secret=True)
|
|
3701
3705
|
upload_post_username = text_setting("Upload-Post username", "upload_post_username")
|
|
3702
3706
|
upload_post_platforms = text_setting("Plataformas Upload-Post", "upload_post_platforms")
|
|
3703
3707
|
upload_post_auto_upload = st.checkbox("Publicar automaticamente após gerar", bool(settings.get("upload_post_auto_upload", False)))
|
|
3704
3708
|
|
|
3705
|
-
with st.expander("Postiz — API key, integração e MCP", expanded=
|
|
3709
|
+
with st.expander("Postiz — API key, integração e MCP", expanded=False):
|
|
3706
3710
|
st.caption("O Thunderbolt é o cliente. A API key é enviada exclusivamente ao servidor Postiz configurado; não é colocada em URLs, logs ou repositório.")
|
|
3707
3711
|
postiz_enabled = st.checkbox("Activar Postiz como fallback final", bool(settings.get("postiz_enabled", False)))
|
|
3708
3712
|
postiz_mode = st.selectbox("Modo de ligação", ["api", "mcp"], index=0 if settings.get("postiz_mode", "api") != "mcp" else 1, help="API é o modo determinístico de upload. MCP fica disponível para uma ligação compatível com Streamable HTTP.")
|
package/package.json
CHANGED