@danhachuel/thunderbolt 0.2.43 → 0.2.45

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.43
5
+ > **Versão deste manual:** 0.2.45
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.43 install
103
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.45 install
104
104
  ```
105
105
 
106
106
  Linux/macOS:
107
107
 
108
108
  ```bash
109
- npx --yes @danhachuel/thunderbolt@0.2.43 install
109
+ npx --yes @danhachuel/thunderbolt@0.2.45 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.
@@ -371,7 +371,7 @@ As credenciais devem ser inseridas apenas na configuração local. A Kaggle API
371
371
 
372
372
  ## OpenAI/ NVIDIA NIM — API key, Base URL e modelo
373
373
 
374
- A secção **LLM — providers e modelos** mantém o provider técnico `openai`, mas a área visual passou a chamar-se **OpenAI/ NVIDIA NIM — API key, Base URL e modelo**. Isto permite usar a API oficial da OpenAI, a API pública NVIDIA NIM/NVIDIA Build ou qualquer servidor local OpenAI-compatible sem alterar o restante fluxo do MoneyPrinterTurbo.
374
+ A secção **LLM — providers e modelos** mantém o provider técnico `openai`, mas a área visual passou a chamar-se **OpenAI/ NVIDIA NIM — API key, Base URL e modelo**. Isto permite usar a API oficial da OpenAI, a API pública NVIDIA NIM/NVIDIA Build ou qualquer servidor local OpenAI-compatible sem alterar o restante fluxo do MoneyPrinterTurbo. O campo de modelo manual utiliza o parâmetro `help` compatível com as versões de Streamlit instaladas pelo Thunderbolt; não utiliza `help_text`.
375
375
 
376
376
  Para usar NVIDIA NIM, abra **Configurações > Configurações Técnicas**, mantenha ou preencha a Base URL `https://integrate.api.nvidia.com/v1` e introduza a API key do NVIDIA Build. Clique em **Consultar/actualizar modelos NIM**. O Thunderbolt executa a consulta apenas nesse momento, acrescentando `/models` à Base URL, envia a API key como `Authorization: Bearer ...` e interpreta a resposta OpenAI-compatible `data[].id`. Os IDs devolvidos aparecem num selector; ao escolher um, o valor é guardado em `openai_model_name` e continua a ser enviado para o `config.toml` do MoneyPrinterTurbo.
377
377
 
@@ -397,7 +397,7 @@ Após iniciar a aplicação, valide o seguinte percurso:
397
397
  12. **Criação de Vídeos:** confirme que `Pexels/Pixabay` substitui o label antigo, que `Estilo IA` aparece apenas em `full_ia` e que `Apenas Música` exige áudio e guarda `background_mode=none`.
398
398
  13. **Automação:** no cartão de cada canal, escolha o **Blueprint padrão** e a **Voz padrão**, clique em `Guardar` e confirme que o resumo do cartão se actualiza. Configure também **Automação ON** e um horário `HH:MM`; confirme a lista de vídeos cadastrados. Os mesmos defaults aparecem em **Canais** e são usados em novas tarefas. Inicie o Thunderbolt pelo launcher, confirme o aviso verde **Worker activo** e verifique que o relógio apresentado corresponde ao computador. O worker cria no máximo um lote por canal por dia quando o horário local coincide.
399
399
  14. **Configurações > Configurações Técnicas > Teste de vozes:** teste Edge/Azure ou provider configurado e confirme reprodução/download sem criação de tarefa.
400
- 15. **Upload directo:** em **Configurações > Configurações Técnicas > Contas Google/YouTube — canais em lote**, seleccione cada conta Google e carregue o seu ficheiro de cookies no painel **Upload directo — sessão YouTube Frontend API**. São aceites JSON de navegador, lista JSON e formato Netscape; o Thunderbolt valida `SID`, `SSID`, `HSID`, `APISID` e `SAPISID` e guarda o ficheiro em `storage/youtube_direct_accounts/<id-da-conta>/cookies.json`. Preencha também o `sessionInfo token` da mesma conta. Em **Canais > Upload directo — conta e canal**, associe o canal à conta e preencha o `DELEGATED_SESSION_ID` individual. Configure `INNERTUBE_API_KEY`, teste apenas com um vídeo de validação e confirme que o botão só fica disponível quando os três dados — cookies, sessionInfo e ID delegado — estão configurados. O método envia chunks de 256 KiB e não extrai cookies do navegador.
400
+ 15. **Upload directo:** em **Configurações > Configurações Técnicas > Contas Google/YouTube — canais em lote**, adicione cada conta Google. No painel aberto **Upload directo — sessão YouTube Frontend API**, preencha o `sessionInfo token` dessa conta, carregue o ficheiro de cookies e clique em **Guardar cookies e sessionInfo por conta**. Em **Canais > Canais cadastrados**, use o painel aberto **Upload directo — conta e canal** para preencher o `DELEGATED_SESSION_ID deste canal (individual)` e clique em **Guardar credenciais deste canal**. Configure `INNERTUBE_API_KEY`, teste apenas com um vídeo de validação e confirme que o botão só fica disponível quando os três dados — cookies, sessionInfo e ID delegado — estão configurados. O método envia chunks de 256 KiB e não extrai cookies do navegador.
401
401
  16. **Configurações > MCP > Client MCP:** confirme que Short Video Maker, AutoVio, OpenMontage e OpenCut aparecem com as portas padrão editáveis. O estado **Activo** é uma preferência local; a detecção deve indicar **Não detectado** quando os serviços externos não estiverem instalados ou iniciados.
402
402
  17. **Configurações > MCP > Servidor MCP:** abra a subaba, mantenha o host `127.0.0.1`, active **Servidor MCP ON** e clique em **Guardar e iniciar Servidor MCP**. Confirme o endpoint `/mcp` e o health endpoint `/health`. Mantenha **Permitir ferramentas de escrita** desactivado até precisar que um agente crie lotes.
403
403
  18. **Configurações > MCP > Skill:** clique em **Guardar skill localmente** e confirme o ficheiro em `storage/skills/moneyprinterturbo-video.md`; opcionalmente use **Descarregar skill .md** para obter a cópia através do navegador.
@@ -418,7 +418,7 @@ Ao abrir a página, o Thunderbolt não prepara dados públicos, não descarrega
418
418
 
419
419
  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.
420
420
 
421
- 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.43 install`; o instalador detecta e reutiliza o que já estiver válido.
421
+ 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.45 install`; o instalador detecta e reutiliza o que já estiver válido.
422
422
 
423
423
  ### Niche Finder Apify
424
424
 
@@ -448,7 +448,11 @@ A área **Teste de vozes**, dentro de **Configurações > Configurações Técni
448
448
 
449
449
  ## Upload directo
450
450
 
451
- A subaba **Upload directo** adapta o [YouTube-Video-Upload-Frontend-Api](https://github.com/Nojus10/YouTube-Video-Upload-Frontend-Api). As credenciais deixam de ser globais: cada conta Google/YouTube cadastrada em **Configurações Técnicas > Contas Google/YouTube — canais em lote** tem um ficheiro de cookies próprio e um `sessionInfo token` próprio. O carregador aceita três representações: objecto JSON com os cookies, lista JSON de cookies e formato Netscape; os cinco nomes obrigatórios são `SID`, `SSID`, `HSID`, `APISID` e `SAPISID`. O ficheiro validado é guardado em `storage/youtube_direct_accounts/<id-da-conta>/cookies.json`, fora de `storage/state/`, com permissões locais restritas.
451
+ Em **Canais > Canais cadastrados**, o painel **Upload directo conta e canal** fica aberto por defeito em cada cartão. Seleccione a conta Google responsável pelo canal, preencha o campo **DELEGATED_SESSION_ID deste canal (individual)** e clique em **Guardar credenciais deste canal**. Este valor não é global: cada canal deve ter o seu próprio ID delegado.
452
+
453
+ Em **Configurações Técnicas > Upload directo — sessão YouTube Frontend API**, o painel fica aberto por defeito. Para cada conta listada, preencha o **sessionInfo token**, carregue em **Ficheiro de cookies** o ficheiro JSON/lista JSON/Netscape que contém `SID`, `SSID`, `HSID`, `APISID` e `SAPISID`, e clique em **Guardar cookies e sessionInfo por conta**. O ficheiro é gravado separadamente em `storage/youtube_direct_accounts/<id-da-conta>/cookies.json`; não é uma configuração global. Se ainda não existir nenhuma conta, adicione-a primeiro em **Contas Google/YouTube — canais em lote**.
454
+
455
+ A subaba **Upload directo** adapta o [YouTube-Video-Upload-Frontend-Api](https://github.com/Nojus10/YouTube-Video-Upload-Frontend-Api). As credenciais deixam de ser globais: cada conta Google/YouTube cadastrada tem um ficheiro de cookies próprio e um `sessionInfo token` próprio. O carregador aceita três representações: objecto JSON com os cookies, lista JSON de cookies e formato Netscape; os cinco nomes obrigatórios são `SID`, `SSID`, `HSID`, `APISID` e `SAPISID`. O ficheiro validado é guardado em `storage/youtube_direct_accounts/<id-da-conta>/cookies.json`, fora de `storage/state/`, com permissões locais restritas.
452
456
 
453
457
  Em **Canais > Upload directo — conta e canal**, associe cada canal à conta Google que detém os cookies e o `sessionInfo token`, e preencha o `DELEGATED_SESSION_ID` individual desse canal. O upload lê os cookies e o token da conta associada e usa o ID delegado do canal como `pageId`/destino. No momento do upload, o Thunderbolt bloqueia a operação se não existir conta associada, ficheiro de cookies válido, `sessionInfo token`, `DELEGATED_SESSION_ID`, `INNERTUBE_API_KEY` ou vídeo elegível. O tamanho de chunk é validado e normalizado para múltiplos de 262144 bytes. O método é uma integração não oficial de sessão do YouTube; não extraia cookies automaticamente, não os coloque no repositório e não os partilhe.
454
458
 
package/README.md CHANGED
@@ -27,22 +27,22 @@ A primeira versão implementa a camada UI independente com:
27
27
 
28
28
  ## Upload directo — credenciais por conta e por canal
29
29
 
30
- O Upload directo baseado no [YouTube-Video-Upload-Frontend-Api](https://github.com/Nojus10/YouTube-Video-Upload-Frontend-Api) usa dois níveis de configuração. Em **Configurações Técnicas > Upload directo — sessão YouTube Frontend API**, cada conta Google cadastrada possui o seu próprio ficheiro de cookies e o seu próprio `sessionInfo token`. O ficheiro pode ser um JSON exportado do navegador, uma lista JSON de cookies ou um ficheiro Netscape; o Thunderbolt valida e guarda apenas `SID`, `SSID`, `HSID`, `APISID` e `SAPISID` em `storage/youtube_direct_accounts/<id-da-conta>/cookies.json`.
30
+ O Upload directo baseado no [YouTube-Video-Upload-Frontend-Api](https://github.com/Nojus10/YouTube-Video-Upload-Frontend-Api) usa dois níveis de configuração. Em **Configurações Técnicas > Upload directo — sessão YouTube Frontend API**, o painel fica aberto por defeito e cada conta Google cadastrada possui o seu próprio ficheiro de cookies e o seu próprio `sessionInfo token`. Primeiro adicione a conta em **Contas Google/YouTube — canais em lote**; depois, no painel da conta, surgem o campo `sessionInfo token`, o uploader **Ficheiro de cookies**, o estado do ficheiro e o botão **Guardar cookies e sessionInfo por conta**. O ficheiro pode ser um JSON exportado do navegador, uma lista JSON de cookies ou um ficheiro Netscape; o Thunderbolt valida e guarda apenas `SID`, `SSID`, `HSID`, `APISID` e `SAPISID` em `storage/youtube_direct_accounts/<id-da-conta>/cookies.json`.
31
31
 
32
- Em **Canais > Upload directo — conta e canal**, cada canal é associado à conta Google que fornece os cookies e o `sessionInfo token`, e possui o seu próprio `DELEGATED_SESSION_ID`. O upload lê os cookies e o token da conta associada e envia o ID delegado individual do canal como `pageId`/`onBehalfOfUser`. O botão é bloqueado quando falta qualquer destes elementos. O `INNERTUBE_API_KEY` e o tamanho de chunk continuam nas configurações directas; o tamanho é normalizado para múltiplos de 262144 bytes.
32
+ Em **Canais > Canais cadastrados**, o painel **Upload directo — conta e canal** fica aberto por defeito em cada cartão. Cada canal é associado à conta Google que fornece os cookies e o `sessionInfo token`, e possui o seu próprio `DELEGATED_SESSION_ID` no campo **DELEGATED_SESSION_ID deste canal (individual)**. O upload lê os cookies e o token da conta associada e envia o ID delegado individual do canal como `pageId`/`onBehalfOfUser`. O botão é bloqueado quando falta qualquer destes elementos. O `INNERTUBE_API_KEY` e o tamanho de chunk continuam nas configurações directas; o tamanho é normalizado para múltiplos de 262144 bytes.
33
33
 
34
34
  Os dados são segredos de sessão. Os valores não aparecem em tabelas ou logs, o ficheiro é escrito com permissões locais restritas e não é incluído no Git. O Thunderbolt não extrai cookies automaticamente do browser e não envia as credenciais para o GitHub. O método é não oficial e pode deixar de funcionar se o YouTube alterar os endpoints internos.
35
35
 
36
36
 
37
37
  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.
38
38
 
39
- ## Navegação da UI 0.2.43
39
+ ## Navegação da UI 0.2.45
40
40
 
41
41
  A barra lateral mantém os níveis principais, nesta ordem: **Início**, **Niche Finder**, **Pipeline**, **Automação**, **Edição**, **Models AI** e **Configurações**. **Pipeline** é expansível e contém **Criação de Vídeos**, **Criação de Músicas** e **Upload**. **Edição** é expansível e contém **Limpador de Metadados**, **Cortes** e **Editor Python**, nessa ordem. **Models AI** é expansível e contém **Personagens** e **Redes Sociais**, nessa ordem. **Niche Finder** é expansível e contém **Niche Finder Kaggle** e **Niche Finder Apify**. **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.
42
42
 
43
43
  ## OpenAI/ NVIDIA NIM — descoberta de modelos
44
44
 
45
- Em **Configurações Técnicas > LLM — providers e modelos**, a área anteriormente chamada **OpenAI — API key, Base URL e modelo** passa a chamar-se **OpenAI/ NVIDIA NIM — API key, Base URL e modelo**. O provider interno continua a ser `openai`, para preservar a compatibilidade com o MoneyPrinterTurbo e com os restantes endpoints OpenAI-compatible.
45
+ Em **Configurações Técnicas > LLM — providers e modelos**, a área anteriormente chamada **OpenAI — API key, Base URL e modelo** passa a chamar-se **OpenAI/ NVIDIA NIM — API key, Base URL e modelo**. O campo de modelo manual usa o parâmetro `help` suportado pelas versões do Streamlit instaladas pelo Thunderbolt, evitando o erro de argumento `help_text`. O provider interno continua a ser `openai`, para preservar a compatibilidade com o MoneyPrinterTurbo e com os restantes endpoints OpenAI-compatible.
46
46
 
47
47
  A Base URL predefinida para NVIDIA NIM é `https://integrate.api.nvidia.com/v1`. Depois de inserir a API key, clique em **Consultar/actualizar modelos NIM**. O Thunderbolt consulta a Base URL acrescentando `/models`, lê os identificadores do formato OpenAI (`data[].id`) e apresenta-os num selector. O modelo escolhido é guardado em `openai_model_name` e é sincronizado para o `config.toml` do motor.
48
48
 
@@ -133,9 +133,9 @@ thunderbolt
133
133
  No Windows PowerShell, se `npx` for bloqueado por `npx.ps1`, use directamente `npx.cmd`:
134
134
 
135
135
  ```powershell
136
- npx.cmd --yes @danhachuel/thunderbolt@0.2.43 install
137
- npx.cmd --yes @danhachuel/thunderbolt@0.2.43 doctor
138
- npx.cmd --yes @danhachuel/thunderbolt@0.2.43
136
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.45 install
137
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.45 doctor
138
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.45
139
139
  ```
140
140
 
141
141
  Como alternativa, pode permitir scripts para o seu utilizador:
@@ -159,7 +159,7 @@ O menu expansível **Niche Finder** contém duas alternativas independentes. **N
159
159
 
160
160
  A interface apresenta dentro da aba 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 página permanece sem resultados até o primeiro clique em **Analisar Nichos**; depois, se os parâmetros forem alterados, mostra os resultados anteriores e pede novo clique para aplicar os filtros actuais. 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.
161
161
 
162
- **Niche Finder Apify** é a segunda alternativa e não usa o dataset, filtros, execução ou resultados Kaggle. Define três palavras-chave, período, limite de resultados, Shorts, duração, idioma de legendas e ordenação; depois de clicar em **Pesquisar no Apify**, inicia o actor `streamers~youtube-scraper`, acompanha o run, carrega o dataset, normaliza vídeos, limpa SRT, calcula VSC Ratio e tenta resumir as transcrições com o provider LLM configurado. Os resultados ficam na sessão própria `niche_apify_results`, o histórico pequeno fica em `storage/state/niche_apify_runs.json` e existem exportações JSON/CSV. Configure o **Apify API Token** em Configurações Técnicas. As dependências adicionais são instaladas pelo fluxo normal do pacote: `requests`, `pandas` e os componentes já existentes da análise. Em instalações existentes, execute novamente `npx.cmd --yes @danhachuel/thunderbolt@0.2.43 install`; o instalador detecta e reutiliza componentes já válidos.
162
+ **Niche Finder Apify** é a segunda alternativa e não usa o dataset, filtros, execução ou resultados Kaggle. Define três palavras-chave, período, limite de resultados, Shorts, duração, idioma de legendas e ordenação; depois de clicar em **Pesquisar no Apify**, inicia o actor `streamers~youtube-scraper`, acompanha o run, carrega o dataset, normaliza vídeos, limpa SRT, calcula VSC Ratio e tenta resumir as transcrições com o provider LLM configurado. Os resultados ficam na sessão própria `niche_apify_results`, o histórico pequeno fica em `storage/state/niche_apify_runs.json` e existem exportações JSON/CSV. Configure o **Apify API Token** em Configurações Técnicas. As dependências adicionais são instaladas pelo fluxo normal do pacote: `requests`, `pandas` e os componentes já existentes da análise. Em instalações existentes, execute novamente `npx.cmd --yes @danhachuel/thunderbolt@0.2.45 install`; o instalador detecta e reutiliza componentes já válidos.
163
163
 
164
164
  ## Editor Python baseado no PYEdit
165
165
 
package/app/main.py CHANGED
@@ -593,10 +593,11 @@ def render_channels():
593
593
  if current_channel_account_id and current_channel_account_id not in channel_account_ids:
594
594
  channel_account_ids.append(current_channel_account_id)
595
595
  youtube_account_labels[current_channel_account_id] = "Conta Google não configurada"
596
- with st.expander("Upload directo — conta e canal", expanded=False):
596
+ with st.expander("Upload directo — conta e canal", expanded=True):
597
+ st.caption("Defina aqui a conta Google deste canal e o DELEGATED_SESSION_ID individual. Os cookies e o sessionInfo token são carregados na área da conta em Configurações Técnicas.")
597
598
  with st.form(f"channel_direct_credentials_{channel['id']}"):
598
599
  channel_account_id = st.selectbox("Conta Google dos cookies/sessionInfo", channel_account_ids, index=channel_account_ids.index(current_channel_account_id) if current_channel_account_id in channel_account_ids else 0, format_func=lambda item: youtube_account_labels.get(item, item or "Sem conta Google associada"), key=f"channel_account_{channel['id']}")
599
- channel_delegated_session_id = st.text_input("DELEGATED_SESSION_ID deste canal", value=str(channel.get("delegated_session_id", "")), type="password", key=f"channel_delegated_session_id_{channel['id']}")
600
+ channel_delegated_session_id = st.text_input("DELEGATED_SESSION_ID deste canal (individual)", value=str(channel.get("delegated_session_id", "")), type="password", key=f"channel_delegated_session_id_{channel['id']}")
600
601
  save_channel_direct_credentials = st.form_submit_button("Guardar credenciais deste canal", type="primary")
601
602
  if save_channel_direct_credentials:
602
603
  update_channel(channel["id"], {"google_account_id": channel_account_id.strip(), "google_account_email": str(youtube_accounts_by_id.get(channel_account_id, {}).get("email", "")), "delegated_session_id": channel_delegated_session_id.strip()})
@@ -1540,11 +1541,12 @@ def render_settings():
1540
1541
 
1541
1542
  direct_account_session_fields = {}
1542
1543
  direct_cookie_uploads = {}
1543
- with st.expander("Upload directo — sessão YouTube Frontend API"):
1544
+ save_direct_credentials = False
1545
+ with st.expander("Upload directo — sessão YouTube Frontend API", expanded=True):
1544
1546
  st.caption("Os cookies e o sessionInfo token são configurados por conta Google/YouTube. O DELEGATED_SESSION_ID é configurado separadamente em cada canal.")
1545
1547
  direct_accounts = [account for account in settings.get("youtube_batch_accounts", []) if isinstance(account, dict) and account.get("id")]
1546
1548
  if not direct_accounts:
1547
- st.info("Adicione primeiro uma conta em Contas Google/YouTube canais em lote. Cada conta terá o seu ficheiro de cookies e sessionInfo token.")
1549
+ st.warning("Ainda não existe uma conta Google/YouTube cadastrada. Adicione primeiro a conta acima; depois deste formulário aparecerão, para cada Gmail, o campo de `sessionInfo token` e o uploader do ficheiro com SID, SSID, HSID, APISID e SAPISID.")
1548
1550
  for direct_account in direct_accounts:
1549
1551
  direct_account_id = str(direct_account["id"])
1550
1552
  direct_status = direct_account_status(STORAGE, direct_account)
@@ -1564,6 +1566,8 @@ def render_settings():
1564
1566
  st.warning("Sem ficheiro de cookies")
1565
1567
  st.caption("O ficheiro é guardado em storage/youtube_direct_accounts/<conta>/cookies.json. Os valores não são mostrados nem enviados para o Git.")
1566
1568
  direct_account_session_fields[direct_account_id] = direct_session_info_value
1569
+ if direct_accounts:
1570
+ save_direct_credentials = st.form_submit_button("Guardar cookies e sessionInfo por conta", type="secondary", use_container_width=True)
1567
1571
 
1568
1572
  with st.container(border=True):
1569
1573
  st.markdown("**Compatibilidade com instalação antiga — credenciais globais**")
@@ -1615,7 +1619,7 @@ def render_settings():
1615
1619
  model_index = model_options.index(current_model_name) if current_model_name in model_options else 0
1616
1620
  selected_model = st.selectbox("Modelo OpenAI/ NVIDIA NIM", model_options, index=model_index, format_func=lambda value: "Escrever modelo manualmente" if value == manual_option else value, key="settings_openai_model_select")
1617
1621
  if selected_model == manual_option:
1618
- openai_model_name = st.text_input("Modelo manual", value=current_model_name if current_model_name not in cached_models else "", help_text="Ex.: nvidia_nim/minimaxai/minimax-m3", key="settings_openai_model_manual")
1622
+ openai_model_name = st.text_input("Modelo manual", value=current_model_name if current_model_name not in cached_models else "", help="Ex.: nvidia_nim/minimaxai/minimax-m3", key="settings_openai_model_manual")
1619
1623
  else:
1620
1624
  openai_model_name = selected_model
1621
1625
  else:
@@ -1710,7 +1714,8 @@ def render_settings():
1710
1714
  st.session_state["openai_model_catalog"] = {"key": catalog_key, "models": [], "error": str(exc)}
1711
1715
  st.rerun()
1712
1716
 
1713
- if st.form_submit_button("Guardar configurações do Thunderbolt", type="primary"):
1717
+ save_all_settings = st.form_submit_button("Guardar configurações do Thunderbolt", type="primary")
1718
+ if save_all_settings or save_direct_credentials:
1714
1719
  direct_cookie_error = ""
1715
1720
  configured_direct_accounts = [account for account in settings.get("youtube_batch_accounts", []) if isinstance(account, dict) and account.get("id")]
1716
1721
  for direct_account in configured_direct_accounts:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.2.43",
3
+ "version": "0.2.45",
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",