@danhachuel/thunderbolt 0.3.51 → 0.3.52

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.
@@ -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.51
5
+ > **Versão deste manual:** 0.3.52
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 --prefer-online @danhachuel/thunderbolt@0.3.51 install
103
+ npx.cmd --yes --prefer-online @danhachuel/thunderbolt@0.3.52 install
104
104
  ```
105
105
 
106
106
  Linux/macOS:
107
107
 
108
108
  ```bash
109
- npx --yes --prefer-online @danhachuel/thunderbolt@0.3.51 install
109
+ npx --yes --prefer-online @danhachuel/thunderbolt@0.3.52 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.
@@ -114,7 +114,7 @@ A instalação normal é **segura para actualizações**: preserva `storage`, Bl
114
114
  Se quiser apagar absolutamente tudo de forma intencional, use o comando destrutivo separado:
115
115
 
116
116
  ```powershell
117
- npx.cmd --yes --prefer-online @danhachuel/thunderbolt@0.3.51 install --purge-data
117
+ npx.cmd --yes --prefer-online @danhachuel/thunderbolt@0.3.52 install --purge-data
118
118
  ```
119
119
 
120
120
  O parâmetro `--purge-data` apaga Blueprints, Brandings, configurações, storage e artefactos locais. Não o use numa actualização normal.
@@ -369,6 +369,8 @@ A área **Voz, TTS e música — Azure Speech, restantes serviços e Suno** est
369
369
 
370
370
  Na criação de vídeo, abra **Configurações de áudio** e escolha **Upload** em **Modo de narração**. Use **Ficheiro de narração** para seleccionar o áudio, clique em **Guardar áudio de narração** e confirme a pré-visualização. O Thunderbolt valida que o ficheiro existe antes de criar a tarefa e encaminha o caminho ao MoneyPrinterTurbo com `--custom-audio-file`; este argumento é necessário porque o motor não persiste automaticamente o caminho carregado. São aceites ficheiros `.mp3`, `.wav`, `.m4a`, `.aac`, `.flac` e `.ogg`, guardados no storage local em `voiceovers`.
371
371
 
372
+ As notificações novas são verificadas automaticamente na sessão activa e aparecem como pop-ups no canto inferior direito, mesmo quando está aberta outra página. O pop-up não marca o registo como lido: a aba **Notificações** continua a ser o centro persistente para consultar o histórico, gerir preferências e marcar eventos como lidos. Cada ID é apresentado no máximo uma vez por sessão do navegador.
373
+
372
374
  | Provider | Configuração mínima | Pool suportado |
373
375
  |---|---|---|
374
376
  | Nano Banana | API key e modelo Gemini; composição aplicada internamente | Imagem |
@@ -526,7 +528,7 @@ Ao abrir a página, o Thunderbolt não prepara dados públicos, não descarrega
526
528
 
527
529
  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.
528
530
 
529
- 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 --prefer-online @danhachuel/thunderbolt@0.3.51 install`; o instalador detecta e reutiliza o que já estiver válido.
531
+ 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 --prefer-online @danhachuel/thunderbolt@0.3.52 install`; o instalador detecta e reutiliza o que já estiver válido.
530
532
 
531
533
  ### Niche Finder Apify
532
534
 
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.51
72
+ ## Navegação da UI 0.3.52
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
 
@@ -97,7 +97,7 @@ No bloco **Limite LLM NVIDIA NIM**, a opção **Activar limitador NVIDIA NIM —
97
97
 
98
98
  A correcção da integração Nano Banana remove o campo de entrega `inline` rejeitado pelo contrato actual da Interactions API e mantém a edição de lettering com imagem de referência quando suportada pelo provider.
99
99
 
100
- A página **AI Influencers > Tutorial Meta** apresenta o guia de configuração de uma conta Instagram profissional e das credenciais Meta para automações com n8n, distribuído localmente em `seed/references/guide-instagram.md` e com ligação para a [fonte original no GitHub](https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-instagram.md). A página **Configurações > Notificações** mantém um histórico persistente de conclusões e falhas, reconcilia estados escritos por componentes locais e disponibiliza um checkbox independente para cada operação mapeada. A subaba **Geral** mantém esse centro local; a subaba **Telegram** permite configurar Bot Token, Chat ID e proxy opcional e envia as mesmas notificações pela Bot API oficial, sem polling ou mensagens recebidas. A página **Configurações > Logs**, colocada imediatamente abaixo de Notificações e acima de Configuração API, apresenta o histórico unificado de tarefas e notificações, com filtro livre por operação, filtros adicionais por operação e estado, e as colunas Operação, Estado, Data, Hora, Registo, Origem, Progresso e Detalhes. A tabela mantém uma barra vertical e, quando a soma das colunas excede a largura disponível, disponibiliza também uma barra de rolagem horizontal na parte inferior para consultar integralmente células longas, sobretudo em **Detalhes**.
100
+ A página **AI Influencers > Tutorial Meta** apresenta o guia de configuração de uma conta Instagram profissional e das credenciais Meta para automações com n8n, distribuído localmente em `seed/references/guide-instagram.md` e com ligação para a [fonte original no GitHub](https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-instagram.md). A página **Configurações > Notificações** mantém um histórico persistente de conclusões e falhas, reconcilia estados escritos por componentes locais e disponibiliza um checkbox independente para cada operação mapeada. A subaba **Geral** mantém esse centro local; a subaba **Telegram** permite configurar Bot Token, Chat ID e proxy opcional e envia as mesmas notificações pela Bot API oficial, sem polling ou mensagens recebidas. As notificações novas também aparecem automaticamente como pop-ups no canto inferior direito enquanto o utilizador está noutra página, sem precisar de abrir Notificações; cada aviso é mostrado uma vez por sessão e o histórico continua a controlar o estado de leitura. A página **Configurações > Logs**, colocada imediatamente abaixo de Notificações e acima de Configuração API, apresenta o histórico unificado de tarefas e notificações, com filtro livre por operação, filtros adicionais por operação e estado, e as colunas Operação, Estado, Data, Hora, Registo, Origem, Progresso e Detalhes. A tabela mantém uma barra vertical e, quando a soma das colunas excede a largura disponível, disponibiliza também uma barra de rolagem horizontal na parte inferior para consultar integralmente células longas, sobretudo em **Detalhes**.
101
101
 
102
102
  A página **Edição > Download Mídia** utiliza a API Python do [yt-dlp](https://github.com/yt-dlp/yt-dlp) para descarregar vídeos e áudio de URLs públicas, com qualidade, contentor, formato de áudio, legendas, metadados, playlists, progresso e histórico local em `storage/downloads/` e `storage/state/media_downloads.json`. Conversão e combinação de streams podem exigir FFmpeg.
103
103
 
package/app/main.py CHANGED
@@ -256,6 +256,9 @@ st.markdown("""
256
256
  [data-testid="stMultiSelect"] [data-baseweb="tag"]:has(button[aria-label*="Instagram"]) { background:#e1306c !important; }
257
257
  [data-testid="stMultiSelect"] [data-baseweb="tag"]:has(button[aria-label*="Facebook Pages"]) { background:#1877f2 !important; }
258
258
  [data-testid="stMultiSelect"] [data-baseweb="tag"] svg { color:#ffffff !important; fill:#ffffff !important; }
259
+ /* Notificações globais: o histórico continua persistente, mas os avisos surgem sem abrir a aba. */
260
+ [data-testid="stToastContainer"] { top:auto !important; right:1rem !important; bottom:1rem !important; left:auto !important; z-index:100000 !important; }
261
+ [data-testid="stToast"] { max-width:min(28rem, calc(100vw - 2rem)); }
259
262
  </style>
260
263
  """, unsafe_allow_html=True)
261
264
 
@@ -338,6 +341,66 @@ def install_streamlit_content_translation() -> None:
338
341
  install_streamlit_content_translation()
339
342
 
340
343
 
344
+ NOTIFICATION_TOAST_INTERVAL = "3s"
345
+ NOTIFICATION_TOAST_MAX_PER_CYCLE = 3
346
+ NOTIFICATION_TOAST_SEEN_KEY = "_thunderbolt_notification_toast_seen_ids"
347
+ NOTIFICATION_TOAST_INITIALISED_KEY = "_thunderbolt_notification_toast_initialised"
348
+
349
+
350
+ def _notification_toast_seen_ids() -> set[str]:
351
+ raw = st.session_state.get(NOTIFICATION_TOAST_SEEN_KEY, [])
352
+ if isinstance(raw, (list, tuple, set)):
353
+ return {str(item) for item in raw if str(item).strip()}
354
+ return set()
355
+
356
+
357
+ def _save_notification_toast_seen_ids(notification_ids: set[str]) -> None:
358
+ # Limitar o estado evita crescimento indefinido numa sessão longa.
359
+ st.session_state[NOTIFICATION_TOAST_SEEN_KEY] = sorted(notification_ids)[-500:]
360
+
361
+
362
+ def _render_notification_toast_cycle() -> None:
363
+ """Reconcile completions and display only new unread notifications in this session."""
364
+ try:
365
+ reconcile_persisted_notifications()
366
+ except Exception:
367
+ # A camada visual nunca deve interromper o pipeline ou os workers.
368
+ return
369
+ entries = list_notifications(limit=500, unread_only=True)
370
+ current_ids = {str(item.get("id") or "") for item in entries if str(item.get("id") or "")}
371
+ seen_ids = _notification_toast_seen_ids()
372
+ if not st.session_state.get(NOTIFICATION_TOAST_INITIALISED_KEY, False):
373
+ # Não transformar o histórico antigo numa avalanche de pop-ups ao abrir a UI.
374
+ seen_ids.update(current_ids)
375
+ _save_notification_toast_seen_ids(seen_ids)
376
+ st.session_state[NOTIFICATION_TOAST_INITIALISED_KEY] = True
377
+ return
378
+
379
+ pending = [item for item in reversed(entries) if str(item.get("id") or "") not in seen_ids]
380
+ for item in pending[:NOTIFICATION_TOAST_MAX_PER_CYCLE]:
381
+ notification_id = str(item.get("id") or "")
382
+ if not notification_id:
383
+ continue
384
+ title = str(item.get("title") or item.get("label") or "Notificação").strip()
385
+ message = str(item.get("message") or "").strip()
386
+ body = f"**{title}**"
387
+ if message:
388
+ body = f"{body}\n\n{message}"
389
+ if hasattr(st, "toast"):
390
+ st.toast(body)
391
+ seen_ids.add(notification_id)
392
+ _save_notification_toast_seen_ids(seen_ids)
393
+
394
+
395
+ if hasattr(st, "fragment"):
396
+ @st.fragment(run_every=NOTIFICATION_TOAST_INTERVAL)
397
+ def render_global_notification_toasts() -> None:
398
+ _render_notification_toast_cycle()
399
+ else:
400
+ def render_global_notification_toasts() -> None:
401
+ _render_notification_toast_cycle()
402
+
403
+
341
404
  def localized_tab_labels(labels: list[str], language: str | None = None) -> list[str]:
342
405
  """Translate Streamlit tab labels while keeping widget keys and behaviour stable."""
343
406
  selected_language = language_code(language or current_ui_language())
@@ -6295,10 +6358,7 @@ def main():
6295
6358
  "Notificações": render_notifications,
6296
6359
  "Logs": render_logs,
6297
6360
  }
6298
- try:
6299
- reconcile_persisted_notifications()
6300
- except Exception:
6301
- pass
6361
+ render_global_notification_toasts()
6302
6362
  renderers.get(current_page, render_dashboard)()
6303
6363
 
6304
6364
  if __name__ == "__main__":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.3.51",
3
+ "version": "0.3.52",
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",