@danhachuel/thunderbolt 0.2.13 → 0.2.15

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.13
5
+ > **Versão deste manual:** 0.2.15
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.13 install
103
+ npx.cmd --yes @danhachuel/thunderbolt@0.2.15 install
104
104
  ```
105
105
 
106
106
  Linux/macOS:
107
107
 
108
108
  ```bash
109
- npx --yes @danhachuel/thunderbolt@0.2.13 install
109
+ npx --yes @danhachuel/thunderbolt@0.2.15 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.
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.13 install
107
- npx.cmd --yes @danhachuel/thunderbolt@0.2.13 doctor
108
- npx.cmd --yes @danhachuel/thunderbolt@0.2.13
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
109
109
  ```
110
110
 
111
111
  Como alternativa, pode permitir scripts para o seu utilizador:
package/app/main.py CHANGED
@@ -359,8 +359,16 @@ def render_settings():
359
359
  with st.expander("LLM — providers e modelos", expanded=True):
360
360
  provider_options = ["moonshot", "shengsuanyun", "openai", "gemini", "deepseek", "qwen", "azure", "volcengine", "grok", "minimax", "mimo", "cloudflare", "modelscope", "aihubmix", "aimlapi", "evolink", "ollama", "oneapi", "litellm", "groq", "pollinations"]
361
361
  llm_provider = st.selectbox("LLM provider", provider_options, index=provider_options.index(settings.get("llm_provider", "moonshot")) if settings.get("llm_provider", "moonshot") in provider_options else 0)
362
+ st.markdown("**OpenAI — API key, Base URL e modelo**")
363
+ openai_cols = st.columns(3)
364
+ with openai_cols[0]:
365
+ openai_api_key = text_setting("OpenAI API key", "openai_api_key", secret=True)
366
+ with openai_cols[1]:
367
+ openai_base_url = text_setting("OpenAI Base URL", "openai_base_url", help_text="Opcional. Deixe vazio para a API oficial ou indique um endpoint compatível.")
368
+ with openai_cols[2]:
369
+ openai_model_name = text_setting("OpenAI model", "openai_model_name", help_text="Ex.: gpt-4o, gpt-4.1 ou o modelo disponibilizado pelo seu endpoint.")
362
370
  llm_fields = [
363
- ("Moonshot / Kimi", "moonshot", True), ("Shengsuan Cloud", "shengsuanyun", True), ("OpenAI", "openai", True),
371
+ ("Moonshot / Kimi", "moonshot", True), ("Shengsuan Cloud", "shengsuanyun", True),
364
372
  ("Google Gemini", "gemini", True), ("DeepSeek", "deepseek", True), ("Alibaba Qwen", "qwen", True),
365
373
  ("Azure OpenAI", "azure", True), ("VolcEngine Ark", "volcengine", True), ("xAI Grok", "grok", True),
366
374
  ("MiniMax", "minimax", True), ("Xiaomi MiMo", "mimo", True), ("Cloudflare AI Gateway", "cloudflare", True),
@@ -381,7 +389,7 @@ def render_settings():
381
389
  with cols[2]:
382
390
  settings[f"{prefix}_model_name"] = text_setting("Model", f"{prefix}_model_name")
383
391
 
384
- with st.expander("Voz, TTS e música"):
392
+ with st.expander("Voz, TTS e música — Azure Speech e restantes serviços", expanded=True):
385
393
  cols = st.columns(2)
386
394
  with cols[0]:
387
395
  azure_speech_key = text_setting("Azure Speech key", "azure_speech_key", secret=True)
@@ -416,7 +424,7 @@ def render_settings():
416
424
  whisper_device = st.selectbox("Whisper device", ["cpu", "cuda"], index=0 if settings.get("whisper_device", "cpu") == "cpu" else 1)
417
425
  whisper_compute_type = text_setting("Whisper compute type", "whisper_compute_type")
418
426
 
419
- with st.expander("TikTok for Developers"):
427
+ with st.expander("TikTok for Developers — Client ID e Client Secret", expanded=True):
420
428
  st.caption("Apenas as credenciais da aplicação ficam nesta UI. Redirect URI, scopes, autorização e tokens são geridos no TikTok for Developers Playground.")
421
429
  tiktok_client_key = text_setting("TikTok Client ID", "tiktok_client_key", secret=True)
422
430
  tiktok_client_secret = text_setting("TikTok Client Secret", "tiktok_client_secret", secret=True)
@@ -433,7 +441,8 @@ def render_settings():
433
441
  "port": port, "moneyprinter_path": moneyprinter_path, "youtube_api_key": youtube_api_key,
434
442
  "log_level": log_level, "listen_host": listen_host, "listen_port": listen_port, "video_source": video_source,
435
443
  "endpoint": endpoint, "proxy_http": proxy_http, "proxy_https": proxy_https, "match_materials_to_script": match_materials_to_script,
436
- "llm_provider": llm_provider, "azure_speech_key": azure_speech_key, "azure_speech_region": azure_speech_region,
444
+ "llm_provider": llm_provider, "openai_api_key": openai_api_key, "openai_base_url": openai_base_url, "openai_model_name": openai_model_name,
445
+ "azure_speech_key": azure_speech_key, "azure_speech_region": azure_speech_region,
437
446
  "siliconflow_tts_api_key": siliconflow_tts_api_key, "minimax_tts_api_key": minimax_tts_api_key,
438
447
  "minimax_tts_base_url": minimax_tts_base_url, "minimax_tts_model_id": minimax_tts_model_id, "minimax_tts_voice_id": minimax_tts_voice_id,
439
448
  "elevenlabs_api_key": elevenlabs_api_key, "elevenlabs_model_id": elevenlabs_model_id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
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",
package/scripts/cli.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import { spawn, spawnSync } from "node:child_process";
2
3
  import { existsSync, mkdirSync, readFileSync, copyFileSync, readdirSync } from "node:fs";
3
4
  import { homedir, platform } from "node:os";
@@ -24,8 +25,22 @@ const python = process.env.THUNDERBOLT_PYTHON || process.env.HERMES_PYTHON || (e
24
25
  const main = resolve(root, "app", "main.py");
25
26
  const settingsPath = join(thunderboltHome, "storage", "state", "settings.json");
26
27
 
27
- function run(command, commandArgs) {
28
- const result = spawnSync(command, commandArgs, { stdio: "inherit", env: process.env });
28
+ function run(command, commandArgs, label = "comando") {
29
+ console.log(`Thunderbolt: a iniciar ${label}...`);
30
+ const result = spawnSync(command, commandArgs, {
31
+ stdio: "inherit",
32
+ env: process.env,
33
+ cwd: root,
34
+ windowsHide: false,
35
+ });
36
+ if (result.error) {
37
+ console.error(`Thunderbolt: não foi possível iniciar ${label}: ${result.error.message}`);
38
+ process.exit(1);
39
+ }
40
+ if (result.signal) {
41
+ console.error(`Thunderbolt: ${label} terminou pelo sinal ${result.signal}.`);
42
+ process.exit(1);
43
+ }
29
44
  process.exit(result.status ?? 1);
30
45
  }
31
46
 
@@ -96,7 +111,14 @@ function check() {
96
111
  }
97
112
  }
98
113
 
99
- if (args[0] === "install") run(process.execPath, [resolve(root, "scripts", "install.mjs"), ...args.slice(1)]);
114
+ if (args[0] === "install" || args[0] === "--install") {
115
+ const installer = resolve(root, "scripts", "install.mjs");
116
+ if (!existsSync(installer)) {
117
+ console.error(`Thunderbolt: instalador não encontrado: ${installer}`);
118
+ process.exit(1);
119
+ }
120
+ run(process.execPath, [installer, ...args.slice(1)], "a instalação");
121
+ }
100
122
  if (args[0] === "doctor" || args.includes("--check")) {
101
123
  check();
102
124
  process.exit(0);
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import { existsSync, mkdirSync, readFileSync, rmSync, renameSync, cpSync, copyFileSync, readdirSync, writeFileSync } from "node:fs";
2
3
  import { homedir, platform } from "node:os";
3
4
  import { basename, dirname, join, resolve } from "node:path";