@danhachuel/thunderbolt 0.2.30 → 0.2.32

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.2.30
5
+ > **Versão deste manual:** 0.2.31
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.2.30 install
103
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.31 install
104
104
  ```
105
105
 
106
106
  Linux/macOS:
107
107
 
108
108
  ```bash
109
- npx --yes @danhachuel/thunderbolt@0.2.30 install
109
+ npx --yes @danhachuel/thunderbolt@0.2.31 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.
@@ -351,8 +351,11 @@ Na primeira execução, a barra lateral apresenta **Início**, **Pipeline**, **A
351
351
  | YouTube upload principal | Lógica do `youtube-automation-agent` adaptada e executada dentro do Thunderbolt |
352
352
  | OAuth directo de redundância | Caminho alternativo accionado automaticamente se o agente falhar |
353
353
  | TikTok Client ID/Secret | Credenciais da aplicação; Redirect URI, scopes e autorização ficam no TikTok for Developers Playground |
354
+ | Kaggle Username | Nome da conta Kaggle usada para publicar e executar a kernel remota |
355
+ | Kaggle API Key | Chave da conta Kaggle, guardada mascarada apenas em `storage/state/settings.json` |
356
+ | Slug da kernel Kaggle | Identificador da kernel remota, por padrão `thunderbolt-niche-finder` |
354
357
 
355
- As credenciais devem ser inseridas apenas na configuração local. A Data API Key, o OAuth Client ID e o OAuth Client Secret são valores diferentes; Client ID + Secret não geram uma API Key nem um token OAuth até a conta ser autorizada. Não coloque nenhum deles no GitHub, no `package.json`, em blueprints ou em ficheiros de estado versionados.
358
+ As credenciais devem ser inseridas apenas na configuração local. A Kaggle API Key é usada somente pelo executor remoto para publicar a kernel, consultar o estado e obter os resultados pequenos; o dataset não é descarregado para `storage/data/niches`. A Data API Key, o OAuth Client ID e o OAuth Client Secret são valores diferentes; Client ID + Secret não geram uma API Key nem um token OAuth até a conta ser autorizada. Não coloque nenhum deles no GitHub, no `package.json`, em blueprints ou em ficheiros de estado versionados.
356
359
 
357
360
  ## 9. Testar as áreas principais
358
361
 
@@ -384,7 +387,7 @@ Ao abrir a página, o Thunderbolt prepara automaticamente os dados públicos atr
384
387
 
385
388
  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. 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. A análise inicial é automática; o botão **Analisar Nichos** recalcula os resultados depois de alterar os 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.
386
389
 
387
- 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.2.30 install`; o instalador detecta e reutiliza o que já estiver válido.
390
+ 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.2.31 install`; o instalador detecta e reutiliza o que já estiver válido.
388
391
 
389
392
  ## Pipeline: Criação de Vídeos, Criação de Músicas e Automação
390
393
 
package/README.md CHANGED
@@ -21,12 +21,12 @@ A primeira versão implementa a camada UI independente com:
21
21
  | Upload | YouTube via `youtube-automation-agent` adaptado internamente, OAuth directo de redundância, Upload directo experimental, TikTok, Instagram e Facebook Pages no front end |
22
22
  | MCP | Catálogo local opcional de Short Video Maker, AutoVio, OpenMontage e OpenCut, com portas editáveis e activação |
23
23
  | Limpador de Metadados | Upload isolado de vídeos terceiros, limpeza FFmpeg, edição de título/descrição/tags e manifesto JSON |
24
- | Configurações Técnicas | Provedores LLM, TTS/voz, preview de vozes, Suno, materiais, Whisper, FFmpeg, OAuth YouTube, Data API Key opcional, Upload directo, TikTok Client ID/Secret e Upload-Post |
24
+ | Configurações Técnicas | Provedores LLM, TTS/voz, preview de vozes, Suno, materiais, Whisper, FFmpeg, OAuth YouTube, Data API Key opcional, Kaggle Username/API Key, Upload directo, TikTok Client ID/Secret e Upload-Post |
25
25
  | Launcher | Execução via `npx`, instalação assistida, diagnóstico e preparação para distribuição |
26
26
 
27
27
  Os adaptadores do MoneyPrinterTurbo e de publicação nas plataformas são ligados pelas configurações locais e pelos pontos de integração em `integrations/`. A UI não inventa dados quando um serviço externo ou credencial não está disponível.
28
28
 
29
- ## Navegação da UI 0.2.30
29
+ ## Navegação da UI 0.2.32
30
30
 
31
31
  A barra lateral mantém apenas os cinco níveis principais, nesta ordem: **Início**, **Pipeline**, **Automação**, **Niche Finder** e **Configurações**. **Pipeline** é expansível e contém **Criação de Vídeos**, **Criação de Músicas**, **Upload** e **Limpador de Metadados**. **Configurações** é expansível e contém **Canais**, **Blueprints**, **MCP** e **Configurações Técnicas**. O Início reúne o dashboard e as filas do Pipeline, sem botões de acções rápidas.
32
32
 
@@ -109,9 +109,9 @@ thunderbolt
109
109
  No Windows PowerShell, se `npx` for bloqueado por `npx.ps1`, use directamente `npx.cmd`:
110
110
 
111
111
  ```powershell
112
- npx.cmd --yes @danhachuel/thunderbolt@0.2.30 install
113
- npx.cmd --yes @danhachuel/thunderbolt@0.2.30 doctor
114
- npx.cmd --yes @danhachuel/thunderbolt@0.2.30
112
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.32 install
113
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.32 doctor
114
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.32
115
115
  ```
116
116
 
117
117
  Como alternativa, pode permitir scripts para o seu utilizador:
@@ -135,7 +135,7 @@ A página **Niche Finder** integra a lógica do projecto open source [johanfortu
135
135
 
136
136
  A interface apresenta directamente os parâmetros da busca: número de clusters entre 2 e 10, suporte mínimo entre 0,01 e 0,50, país, categoria de engagement, intervalo de datas e tags. A análise inicial é executada automaticamente e **Analisar Nichos** permite recalcular os resultados depois de alterar os filtros. O núcleo aplica normalização, filtros, `log1p`, `StandardScaler`, K-Means e FP-Growth. Os resultados aparecem em DataFrames para clusters, itemsets frequentes, regras de associação e dados analisados, acompanhados por uma visualização Plotly nativa e pesquisa de palavras nos clusters.
137
137
 
138
- As dependências adicionais são instaladas pelo fluxo normal do pacote: `scikit-learn`, `mlxtend`, `plotly`, `seaborn`, `matplotlib` e `kagglehub`. Em instalações existentes, execute novamente `npx.cmd --yes @danhachuel/thunderbolt@0.2.30 install`; o instalador detecta e reutiliza componentes já válidos.
138
+ As dependências adicionais são instaladas pelo fluxo normal do pacote: `scikit-learn`, `mlxtend`, `plotly`, `seaborn`, `matplotlib` e `kagglehub`. Em instalações existentes, execute novamente `npx.cmd --yes @danhachuel/thunderbolt@0.2.31 install`; o instalador detecta e reutiliza componentes já válidos.
139
139
 
140
140
  ## Armazenamento local
141
141
 
package/app/main.py CHANGED
@@ -1028,6 +1028,17 @@ def render_settings():
1028
1028
  youtube_client_id = text_setting("YouTube OAuth Client ID", "youtube_client_id", help_text="Client ID do OAuth 2.0 criado no Google Cloud. É usado para iniciar a autorização da conta YouTube.")
1029
1029
  with youtube_cols[1]:
1030
1030
  youtube_client_secret = text_setting("YouTube OAuth Client Secret", "youtube_client_secret", secret=True, help_text="Client Secret do mesmo cliente OAuth 2.0. Não é uma API Key.")
1031
+
1032
+ with st.expander("Niche Finder — execução remota no Kaggle", expanded=True):
1033
+ 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.")
1034
+ kaggle_cols = st.columns(3)
1035
+ with kaggle_cols[0]:
1036
+ kaggle_username = text_setting("Kaggle Username", "kaggle_username", help_text="Nome de utilizador da sua conta Kaggle, sem @ e sem URL.")
1037
+ with kaggle_cols[1]:
1038
+ kaggle_api_key = text_setting("Kaggle API Key", "kaggle_api_key", secret=True, help_text="Chave criada em Kaggle > Settings > API. Nunca é incluída no notebook ou no GitHub.")
1039
+ with kaggle_cols[2]:
1040
+ kaggle_kernel_slug = text_setting("Slug da kernel", "kaggle_kernel_slug", help_text="Identificador da kernel remota, por exemplo thunderbolt-niche-finder.")
1041
+
1031
1042
  with st.expander("Consulta oficial de métricas — opcional"):
1032
1043
  st.caption("A YouTube Data API Key é uma credencial Google Cloud separada do OAuth. Só é necessária se escolher o método YouTube Data API para consultar métricas oficiais. Não é necessária para Página pública — sem API Key, para autorizar OAuth ou para fazer upload.")
1033
1044
  youtube_api_key = text_setting("YouTube Data API Key (opcional)", "youtube_api_key", secret=True, help_text="Credencial separada, criada em Google Cloud > APIs e serviços > Credenciais > Chave de API. Não cole aqui o Client ID nem o Client Secret.")
@@ -1148,6 +1159,7 @@ def render_settings():
1148
1159
  settings.update({
1149
1160
  "port": port, "moneyprinter_path": moneyprinter_path, "youtube_api_key": youtube_api_key,
1150
1161
  "youtube_client_id": youtube_client_id, "youtube_client_secret": youtube_client_secret,
1162
+ "kaggle_username": kaggle_username.strip(), "kaggle_api_key": kaggle_api_key.strip(), "kaggle_kernel_slug": kaggle_kernel_slug.strip() or "thunderbolt-niche-finder",
1151
1163
  "direct_cookie_sid": direct_cookie_sid, "direct_cookie_ssid": direct_cookie_ssid, "direct_cookie_hsid": direct_cookie_hsid, "direct_cookie_apisid": direct_cookie_apisid, "direct_cookie_sapisid": direct_cookie_sapisid, "direct_session_info": direct_session_info, "direct_innertube_api_key": direct_innertube_api_key, "direct_chunk_size": direct_chunk_size,
1152
1164
  "log_level": log_level, "listen_host": listen_host, "listen_port": listen_port, "video_source": video_source,
1153
1165
  "endpoint": endpoint, "proxy_http": proxy_http, "proxy_https": proxy_https, "match_materials_to_script": match_materials_to_script,
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import shutil
4
+ import tempfile
4
5
  from pathlib import Path
5
6
 
6
7
  import pandas as pd
@@ -61,26 +62,50 @@ def _copy_csv(source: Path, destination: Path) -> Path:
61
62
  return destination
62
63
 
63
64
 
65
+ def _has_usable_cached_dataset() -> bool:
66
+ """Check only the header so a valid multi-gigabyte cache is not read twice."""
67
+ if not DEFAULT_DATASET_PATH.exists() or DEFAULT_DATASET_PATH.stat().st_size <= 0:
68
+ return False
69
+ try:
70
+ columns = set(pd.read_csv(DEFAULT_DATASET_PATH, nrows=0).columns)
71
+ except (OSError, UnicodeDecodeError, pd.errors.ParserError, pd.errors.EmptyDataError):
72
+ return False
73
+ return set(REQUIRED_COLUMNS).issubset(columns)
74
+
75
+
64
76
  def _download_with_kagglehub() -> Path | None:
65
77
  if kagglehub is None:
66
78
  return None
67
- data_dir = ensure_data_dir()
68
- try:
69
- downloaded = kagglehub.dataset_download(DEFAULT_DATASET_SLUG, output_dir=str(data_dir))
70
- except TypeError:
71
- downloaded = kagglehub.dataset_download(DEFAULT_DATASET_SLUG)
72
- except Exception as exc: # pragma: no cover - depends on network/provider state
73
- raise DatasetError(f"O Thunderbolt não conseguiu preparar os dados automáticos: {exc}") from exc
74
- source = _find_csv(Path(downloaded))
75
- if source is None:
76
- raise DatasetError("A preparação automática terminou sem encontrar dados compatíveis.")
77
- return _copy_csv(source, DEFAULT_DATASET_PATH)
79
+ ensure_data_dir()
80
+ # KaggleHub rejects a non-empty output_dir on Windows. Use a new temporary
81
+ # directory for every download, then copy only the validated CSV into the
82
+ # persistent Thunderbolt cache. This also isolates partial downloads.
83
+ with tempfile.TemporaryDirectory(prefix=".niche-kaggle-", dir=str(DATA_DIR.parent)) as temporary_root:
84
+ temporary_path = Path(temporary_root)
85
+ try:
86
+ try:
87
+ downloaded = kagglehub.dataset_download(
88
+ DEFAULT_DATASET_SLUG,
89
+ output_dir=str(temporary_path),
90
+ force_download=True,
91
+ )
92
+ except TypeError: # compatibility with older KaggleHub releases
93
+ downloaded = kagglehub.dataset_download(
94
+ DEFAULT_DATASET_SLUG,
95
+ output_dir=str(temporary_path),
96
+ )
97
+ except Exception as exc: # pragma: no cover - depends on network/provider state
98
+ raise DatasetError(f"O Thunderbolt não conseguiu preparar os dados automáticos: {exc}") from exc
99
+ source = _find_csv(Path(downloaded))
100
+ if source is None:
101
+ raise DatasetError("A preparação automática terminou sem encontrar dados compatíveis.")
102
+ return _copy_csv(source, DEFAULT_DATASET_PATH)
78
103
 
79
104
 
80
105
  def download_kaggle_dataset() -> Path:
81
106
  """Prepare and cache the public Niche-Finder dataset without user interaction."""
82
107
  ensure_data_dir()
83
- if DEFAULT_DATASET_PATH.exists() and DEFAULT_DATASET_PATH.stat().st_size > 0:
108
+ if _has_usable_cached_dataset():
84
109
  return DEFAULT_DATASET_PATH
85
110
  if kagglehub is None:
86
111
  raise DatasetError("O componente automático de dados não está disponível nesta instalação.")
@@ -81,6 +81,9 @@ DEFAULTS: dict[str, Any] = {
81
81
  "youtube_api_key": "",
82
82
  "youtube_client_id": "",
83
83
  "youtube_client_secret": "",
84
+ "kaggle_username": "",
85
+ "kaggle_api_key": "",
86
+ "kaggle_kernel_slug": "thunderbolt-niche-finder",
84
87
  "llm_provider": "moonshot",
85
88
  "moonshot_api_key": "",
86
89
  "moonshot_base_url": "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.2.30",
3
+ "version": "0.2.32",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "main": "scripts/cli.mjs",
6
6
  "type": "module",