@danhachuel/thunderbolt 0.2.15 → 0.2.17

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.15
5
+ > **Versão deste manual:** 0.2.17
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.15 install
103
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.17 install
104
104
  ```
105
105
 
106
106
  Linux/macOS:
107
107
 
108
108
  ```bash
109
- npx --yes @danhachuel/thunderbolt@0.2.15 install
109
+ npx --yes @danhachuel/thunderbolt@0.2.17 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.
@@ -345,7 +345,9 @@ Na primeira execução, abra **Configurações** e reveja:
345
345
  |---|---|
346
346
  | Porta Streamlit | Definir a porta local da UI |
347
347
  | Pasta MoneyPrinterTurbo | Indicar o clone local que será sincronizado com `config.toml` |
348
- | YouTube Data API key | Permitir importar nome, handle e métricas de canais |
348
+ | YouTube Data API Key | Permitir importar nome, handle e métricas públicas de canais |
349
+ | YouTube OAuth Client ID | Identificar a aplicação OAuth 2.0 do Google para operações autenticadas |
350
+ | YouTube OAuth Client Secret | Secret do mesmo cliente OAuth 2.0; não é a Data API Key |
349
351
  | TikTok Client ID/Secret | Credenciais da aplicação; Redirect URI, scopes e autorização ficam no TikTok for Developers Playground |
350
352
 
351
353
  As chaves devem ser inseridas apenas na configuração local. Não as coloque no GitHub, no `package.json`, em blueprints ou em ficheiros de estado versionados.
package/README.md CHANGED
@@ -103,9 +103,9 @@ thunderbolt
103
103
  No Windows PowerShell, se `npx` for bloqueado por `npx.ps1`, use directamente `npx.cmd`:
104
104
 
105
105
  ```powershell
106
- npx.cmd --yes @danhachuel/thunderbolt@0.2.15 install
107
- npx.cmd --yes @danhachuel/thunderbolt@0.2.15 doctor
108
- npx.cmd --yes @danhachuel/thunderbolt@0.2.15
106
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.17 install
107
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.17 doctor
108
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.17
109
109
  ```
110
110
 
111
111
  Como alternativa, pode permitir scripts para o seu utilizador:
package/app/main.py CHANGED
@@ -9,6 +9,10 @@ import streamlit as st
9
9
  ROOT = Path(__file__).resolve().parents[1]
10
10
  if str(ROOT) not in sys.path:
11
11
  sys.path.insert(0, str(ROOT))
12
+ try:
13
+ APP_VERSION = json.loads((ROOT / "package.json").read_text(encoding="utf-8")).get("version", "")
14
+ except (OSError, json.JSONDecodeError):
15
+ APP_VERSION = ""
12
16
 
13
17
  from hermes_ui.domain import STAGES, create_batch, create_channel, create_tasks_for_batch, pipeline_summary, transition_task, update_channel
14
18
  from hermes_ui.storage import BLUEPRINTS, ensure_storage, list_blueprint_files, load_blueprint_file, now, read_json, write_json
@@ -26,9 +30,14 @@ st.markdown("""
26
30
  :root { --accent:#35a7ff; --bg:#0b1118; --card:#121b26; }
27
31
  [data-testid="stAppViewContainer"] { background: radial-gradient(circle at top right, #13283b 0, #0b1118 42%); }
28
32
  [data-testid="stSidebar"] { background:#091018; border-right:1px solid #1d3448; }
29
- [data-testid="stSidebar"] [data-testid="stButton"] { margin:0.03rem 0; }
30
- [data-testid="stSidebar"] [data-testid="stButton"] button { min-height:2.05rem; height:2.05rem; justify-content:flex-start; text-align:left; padding:0.28rem 0.7rem; border-radius:8px; border:1px solid transparent; font-weight:600; }
31
- [data-testid="stSidebar"] [data-testid="stButton"] p { margin:0; line-height:1.1; }
33
+ [data-testid="stSidebar"] .block-container { padding-top:0.28rem; padding-bottom:0.45rem; }
34
+ [data-testid="stSidebar"] > div:first-child { padding-top:0.28rem; }
35
+ [data-testid="stSidebar"] .tb-brand { display:flex; align-items:baseline; gap:0.42rem; margin:0 0 0.68rem 0; white-space:nowrap; }
36
+ [data-testid="stSidebar"] .tb-brand-name { color:#f4f8fb; font-size:1.38rem; line-height:1.15; font-weight:750; letter-spacing:-0.02em; }
37
+ [data-testid="stSidebar"] .tb-brand-version { color:#8ba6bb; font-size:0.92rem; line-height:1; font-weight:500; }
38
+ [data-testid="stSidebar"] [data-testid="stButton"] { margin:0.025rem 0 !important; }
39
+ [data-testid="stSidebar"] [data-testid="stButton"] button { min-height:1.72rem; height:1.72rem; justify-content:flex-start; text-align:left; padding:0.10rem 0.52rem; border-radius:7px; border:1px solid transparent; font-size:0.86rem; font-weight:550; }
40
+ [data-testid="stSidebar"] [data-testid="stButton"] p { margin:0; line-height:1; }
32
41
  [data-testid="stSidebar"] [data-testid="stBaseButton-secondary"] { background:transparent; color:#e7edf2; }
33
42
  [data-testid="stSidebar"] [data-testid="stBaseButton-secondary"]:hover { background:#1c252e; border-color:#2d3944; color:#ffffff; }
34
43
  [data-testid="stSidebar"] [data-testid="stBaseButton-primary"] { background:#292929; color:#ffffff; border-color:#3a3a3a; }
@@ -341,7 +350,15 @@ def render_settings():
341
350
  st.subheader("Execução local")
342
351
  port = st.number_input("Porta Streamlit", 1, 65535, int(settings.get("port", 3030)))
343
352
  moneyprinter_path = st.text_input("Pasta do motor de vídeo", settings.get("moneyprinter_path", ""), key="settings_moneyprinter_path")
344
- youtube_api_key = st.text_input("YouTube Data API key", settings.get("youtube_api_key", ""), type="password")
353
+ st.markdown("**YouTube API pública e OAuth 2.0**")
354
+ st.caption("A Data API Key consulta canais e estatísticas públicas. O Client ID e o Client Secret são credenciais OAuth 2.0 separadas, usadas para autorizar operações na conta, como upload.")
355
+ youtube_cols = st.columns(3)
356
+ with youtube_cols[0]:
357
+ youtube_api_key = text_setting("YouTube Data API Key", "youtube_api_key", secret=True, help_text="Chave criada em Google Cloud > APIs e serviços > Credenciais > Chave de API.")
358
+ with youtube_cols[1]:
359
+ youtube_client_id = text_setting("YouTube OAuth Client ID", "youtube_client_id", help_text="Client ID do OAuth 2.0 criado no Google Cloud.")
360
+ with youtube_cols[2]:
361
+ youtube_client_secret = text_setting("YouTube OAuth Client Secret", "youtube_client_secret", secret=True, help_text="Client Secret do mesmo cliente OAuth 2.0.")
345
362
 
346
363
  with st.expander("Serviço, materiais e rede"):
347
364
  cols = st.columns(2)
@@ -439,6 +456,7 @@ def render_settings():
439
456
  if st.form_submit_button("Guardar configurações do Thunderbolt", type="primary"):
440
457
  settings.update({
441
458
  "port": port, "moneyprinter_path": moneyprinter_path, "youtube_api_key": youtube_api_key,
459
+ "youtube_client_id": youtube_client_id, "youtube_client_secret": youtube_client_secret,
442
460
  "log_level": log_level, "listen_host": listen_host, "listen_port": listen_port, "video_source": video_source,
443
461
  "endpoint": endpoint, "proxy_http": proxy_http, "proxy_https": proxy_https, "match_materials_to_script": match_materials_to_script,
444
462
  "llm_provider": llm_provider, "openai_api_key": openai_api_key, "openai_base_url": openai_base_url, "openai_model_name": openai_model_name,
@@ -609,8 +627,8 @@ def main():
609
627
  ]
610
628
  current_page = st.session_state.get("page", "Dashboard")
611
629
  with st.sidebar:
612
- st.title("Thunderbolt")
613
- st.caption("Navegação")
630
+ version_markup = f'<span class="tb-brand-version">{APP_VERSION}</span>' if APP_VERSION else ""
631
+ st.markdown(f'<div class="tb-brand"><span class="tb-brand-name">Thunderbolt</span>{version_markup}</div>', unsafe_allow_html=True)
614
632
  for target, icon, label in pages:
615
633
  if st.button(label, key=f"nav_{target}", icon=icon, use_container_width=True, type="primary" if current_page == target else "secondary"):
616
634
  st.session_state["page"] = target
@@ -29,6 +29,8 @@ DEFAULTS: dict[str, Any] = {
29
29
  "video_concurrency": 3,
30
30
  "upload_concurrency": 2,
31
31
  "youtube_api_key": "",
32
+ "youtube_client_id": "",
33
+ "youtube_client_secret": "",
32
34
  "llm_provider": "moonshot",
33
35
  "moonshot_api_key": "",
34
36
  "moonshot_base_url": "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
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",