@danhachuel/thunderbolt 0.3.40 → 0.3.41
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/MANUAL-INSTALACAO.md +4 -4
- package/README.md +2 -2
- package/app/main.py +26 -5
- package/package.json +1 -1
package/MANUAL-INSTALACAO.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Este manual descreve a instalação local da UI Thunderbolt, baseada no MoneyPrinterTurbo, utilizando o pacote npm `@danhachuel/thunderbolt`. O fluxo recomendado instala automaticamente o ambiente Python, as dependências da aplicação, as dependências do MoneyPrinterTurbo, o Streamlit e o suporte FFmpeg através de `imageio-ffmpeg`.
|
|
4
4
|
|
|
5
|
-
> **Versão deste manual:** 0.3.
|
|
5
|
+
> **Versão deste manual:** 0.3.41
|
|
6
6
|
> **Pacote npm:** `@danhachuel/thunderbolt`
|
|
7
7
|
> **Porta padrão da UI:** `localhost:3030`
|
|
8
8
|
> **Repositório:** [github.com/DanHachuel/thunderbolt](https://github.com/DanHachuel/thunderbolt)
|
|
@@ -100,13 +100,13 @@ Execute:
|
|
|
100
100
|
Windows PowerShell ou MobaXterm:
|
|
101
101
|
|
|
102
102
|
```powershell
|
|
103
|
-
npx.cmd --yes @danhachuel/thunderbolt@0.3.
|
|
103
|
+
npx.cmd --yes @danhachuel/thunderbolt@0.3.41 install
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
Linux/macOS:
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
|
-
npx --yes @danhachuel/thunderbolt@0.3.
|
|
109
|
+
npx --yes @danhachuel/thunderbolt@0.3.41 install
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
A instalação normal é **segura para actualizações**: preserva `storage`, Blueprints, Brandings, configurações e artefactos do utilizador. Remove apenas `.venv`, o clone técnico do MoneyPrinterTurbo e dependências que serão recriadas. Uma pasta antiga sem dados do utilizador, como `C:\Users\<utilizador>\AppData\Local\hermes` da tentativa incompleta, pode ser removida; uma pasta antiga que contenha Blueprints, Brandings ou storage é preservada e apenas avisada no terminal. Feche processos Python, Node, Streamlit e MobaXterm que estejam a usar as pastas antes de executar.
|
|
@@ -487,7 +487,7 @@ Ao abrir a página, o Thunderbolt não prepara dados públicos, não descarrega
|
|
|
487
487
|
|
|
488
488
|
Os parâmetros da UI são número de clusters entre 2 e 10, suporte mínimo entre 0,01 e 0,50, país, engagement, intervalo de datas e tags, todos dentro da área principal da aba. O núcleo normaliza os dados, calcula engagement, aplica filtros, faz transformação logarítmica e standardização, executa K-Means e calcula itemsets/regras com FP-Growth. Não são apresentados resultados até ao primeiro clique em **Analisar Nichos**; o mesmo botão aplica alterações posteriores aos filtros. Os resultados são DataFrames de clusters, itemsets frequentes, regras de associação e dados analisados; o gráfico de dispersão é criado nativamente com Plotly.
|
|
489
489
|
|
|
490
|
-
As dependências adicionais — `scikit-learn`, `mlxtend`, `plotly`, `seaborn`, `matplotlib` e `kagglehub` — são instaladas pelo procedimento normal de `npx`. Em instalações existentes, execute novamente `npx.cmd --yes @danhachuel/thunderbolt@0.3.
|
|
490
|
+
As dependências adicionais — `scikit-learn`, `mlxtend`, `plotly`, `seaborn`, `matplotlib` e `kagglehub` — são instaladas pelo procedimento normal de `npx`. Em instalações existentes, execute novamente `npx.cmd --yes @danhachuel/thunderbolt@0.3.41 install`; o instalador detecta e reutiliza o que já estiver válido.
|
|
491
491
|
|
|
492
492
|
### Niche Finder Apify
|
|
493
493
|
|
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ No topo da área principal da aplicação existe o menu nativo de idioma no padr
|
|
|
69
69
|
|
|
70
70
|
A UI suporta os temas **Dark** e **Light** através do menu nativo de três pontos do Streamlit, no local original do toolbar. Não existe um selector Theme adicional dentro da página. A configuração distribuída em `.streamlit/config.toml` disponibiliza as variantes nomeadas **Dark** e **Light**, e o menu nativo continua responsável por alternar entre os modos, seguindo o padrão do [MoneyPrinterTurbo](https://github.com/harry0703/MoneyPrinterTurbo). O CSS próprio do Thunderbolt usa cores semânticas, `currentColor` e `color-mix` para acompanhar o tema activo, sem alterar a posição nem a funcionalidade do toolbar, do botão Deploy e do menu principal.
|
|
71
71
|
|
|
72
|
-
## Navegação da UI 0.3.
|
|
72
|
+
## Navegação da UI 0.3.41
|
|
73
73
|
|
|
74
74
|
A barra lateral mantém os níveis principais, nesta ordem: **Início**, **Niche Finder**, **Pipeline**, **Pipeline TikTok**, **Automação**, **Edição**, **AI Influencers** e **Configurações**. **Pipeline Vídeos** é expansível e contém **Criação de Vídeos**, **Backlog Vídeos**, **Roteiros**, **Thumbnails** e **Upload**. **Pipeline Música** é expansível e contém **Criação de Músicas** e **Upload Música**. **Automação** também é expansível e contém **Automação Youtube**. **Edição** é expansível e contém **Limpador de Metadados**, **Cortes**, **Editor Python** e **Download Mídia**, nessa ordem. **AI Influencers** é expansível e contém **Personagens**, **Redes Sociais**, **Tutorial Meta** e **Tutorial Supabase**, nessa ordem. **Niche Finder** é expansível e contém **Niche Finder Kaggle** e **Niche Finder Apify**. **Configurações** é expansível e contém **Canais Youtube**, **Blueprints Youtube**, **MCP**, **Contas Google**, **Notificações**, **Logs** e **Configuração API**, nessa ordem. O Início reúne o dashboard e as filas do Pipeline, sem botões de acções rápidas.
|
|
75
75
|
|
|
@@ -107,7 +107,7 @@ Abaixo do cartão, a secção **Últimos 10 vídeos publicados** fica num expand
|
|
|
107
107
|
|
|
108
108
|
A aba **Criação de Vídeos** permite escrever manualmente o **Tópico ou briefing** ou usar **Gerar tópico/briefing com IA**. A geração usa o provider LLM configurado localmente em **Configuração API > API Keys > Serviços e modelos**, incorpora o Blueprint, a descrição, o idioma e a voz do canal e só ocorre depois do clique do utilizador. Se não houver credenciais ou modelo, a UI mostra uma mensagem accionável e não inventa conteúdo.
|
|
109
109
|
|
|
110
|
-
Entre **Canal** e **Estilo wide**, a UI mostra o Blueprint padrão resolvido do canal
|
|
110
|
+
Entre **Canal** e **Estilo wide**, a UI mostra o Blueprint padrão resolvido do canal, a voz associada e o **Idioma** configurado nesse canal. Ao trocar o canal, o selector **Script Language** é sincronizado automaticamente com o código canónico do novo canal, incluindo a conversão de rótulos legados como `Português` ou `36 – Português (Brasil)`. O valor sincronizado é usado no roteiro, keywords, geração criativa e payload da tarefa; o idioma global só serve como fallback quando não existe canal seleccionado. Quando não existe configuração, apresenta **SEM BLUEPRINT CONFIGURADO** e mantém o idioma do canal visível. Depois do briefing, **Gerar títulos e thumbnails com IA** cria pelo menos 20 candidatos de título e 3–5 variantes de thumbnail. Os títulos seguem as fórmulas e regras de curiosidade, especificidade, emoção, keyword inicial e humanização fornecidas nas referências empacotadas; as thumbnails guardam conceito, overlay de até quatro palavras, composição, cores, prompt e sinergia com o título.
|
|
111
111
|
|
|
112
112
|
O pacote criativo é persistido na task. O título escolhido fica pré-preenchido no Upload e a thumbnail é usada quando existe um ficheiro em `artifacts.thumbnail`. Sem provider de imagem configurado, a aplicação conserva o prompt e apresenta **Prompt de thumbnail pronto — imagem pendente de provider de imagem**, sem criar um PNG falso.
|
|
113
113
|
|
package/app/main.py
CHANGED
|
@@ -362,8 +362,13 @@ def save_ui_language(value: str) -> str:
|
|
|
362
362
|
return normalized
|
|
363
363
|
|
|
364
364
|
|
|
365
|
+
def normalize_video_language(value: Any, default: str = "pt") -> str:
|
|
366
|
+
raw = str(value or "").strip()
|
|
367
|
+
return "music" if raw.casefold() == "music" else language_code(raw, default=default)
|
|
368
|
+
|
|
369
|
+
|
|
365
370
|
def save_video_language(value: str) -> str:
|
|
366
|
-
normalized =
|
|
371
|
+
normalized = normalize_video_language(value)
|
|
367
372
|
settings = read_json("settings.json", {})
|
|
368
373
|
settings["video_language"] = normalized
|
|
369
374
|
write_json("settings.json", settings)
|
|
@@ -486,6 +491,13 @@ def blueprint_for_channel(channel: dict) -> dict[str, Any]:
|
|
|
486
491
|
return {"id": blueprint_id, "name": blueprint_id}
|
|
487
492
|
|
|
488
493
|
|
|
494
|
+
def channel_video_language(channel: dict[str, Any] | None, fallback: str = "pt") -> str:
|
|
495
|
+
"""Return the channel's canonical video language, preserving legacy labels."""
|
|
496
|
+
if not isinstance(channel, dict):
|
|
497
|
+
return normalize_video_language(fallback)
|
|
498
|
+
return normalize_video_language(channel.get("language") or fallback)
|
|
499
|
+
|
|
500
|
+
|
|
489
501
|
def channel_blueprint_summary(channel: dict) -> dict[str, str]:
|
|
490
502
|
blueprint = blueprint_for_channel(channel)
|
|
491
503
|
configured_id = str(channel.get("default_blueprint_id") or channel.get("blueprint_id") or "").strip()
|
|
@@ -501,12 +513,13 @@ def channel_blueprint_summary(channel: dict) -> dict[str, str]:
|
|
|
501
513
|
def render_channel_blueprint_panel(channel: dict, *, compact: bool = False) -> None:
|
|
502
514
|
summary = channel_blueprint_summary(channel)
|
|
503
515
|
voice = summary["voice"] or "Sem voz padrão"
|
|
516
|
+
video_language = language_label(channel_video_language(channel))
|
|
504
517
|
if summary["name"] == "SEM BLUEPRINT CONFIGURADO":
|
|
505
|
-
st.warning("**SEM BLUEPRINT CONFIGURADO** · configure um Blueprint padrão na aba Canais.")
|
|
518
|
+
st.warning(f"**SEM BLUEPRINT CONFIGURADO** · configure um Blueprint padrão na aba Canais. · **Idioma:** {video_language}")
|
|
506
519
|
elif compact:
|
|
507
|
-
st.caption(f"**Blueprint:** {summary['name']} · **Voz:** {voice}")
|
|
520
|
+
st.caption(f"**Blueprint:** {summary['name']} · **Voz:** {voice} · **Idioma:** {video_language}")
|
|
508
521
|
else:
|
|
509
|
-
st.info(f"**Blueprint utilizado pelo canal:** {summary['name']} · `{summary['id']}` · **Voz:** {voice}")
|
|
522
|
+
st.info(f"**Blueprint utilizado pelo canal:** {summary['name']} · `{summary['id']}` · **Voz:** {voice} · **Idioma:** {video_language}")
|
|
510
523
|
|
|
511
524
|
|
|
512
525
|
def creative_payload_from_result(channel: dict, topic: str, creative: dict, topic_source: str = "manual") -> dict[str, Any]:
|
|
@@ -746,7 +759,15 @@ def render_video_generation_settings(
|
|
|
746
759
|
key=f"{prefix}_video_subject",
|
|
747
760
|
placeholder="Ex.: How AI is changing everyday life",
|
|
748
761
|
)
|
|
749
|
-
normalized_current_language =
|
|
762
|
+
normalized_current_language = normalize_video_language(current_language)
|
|
763
|
+
if channel is not None:
|
|
764
|
+
channel_id = str(channel.get("id") or channel.get("name") or "")
|
|
765
|
+
channel_language_state_key = f"{prefix}_language_channel_id"
|
|
766
|
+
if st.session_state.get(channel_language_state_key) != channel_id:
|
|
767
|
+
channel_language = channel_video_language(channel, fallback=normalized_current_language)
|
|
768
|
+
st.session_state[f"{prefix}_script_language"] = channel_language
|
|
769
|
+
st.session_state[channel_language_state_key] = channel_id
|
|
770
|
+
normalized_current_language = normalize_video_language(st.session_state.get(f"{prefix}_script_language") or normalized_current_language)
|
|
750
771
|
settings["script_language"] = st.selectbox(
|
|
751
772
|
"Script Language",
|
|
752
773
|
VIDEO_LANGUAGE_SELECTION_OPTIONS,
|
package/package.json
CHANGED