@danhachuel/thunderbolt 0.2.89 → 0.2.90

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.
package/app/main.py CHANGED
@@ -22,7 +22,7 @@ except (OSError, json.JSONDecodeError):
22
22
 
23
23
  from hermes_ui.domain import STAGES, create_batch, create_channel, create_tasks_for_batch, delete_channel, pipeline_summary, set_channel_defaults, transition_task, update_channel, update_channel_video
24
24
  from hermes_ui.automation_worker import load_worker_status
25
- from hermes_ui.storage import BLUEPRINTS, MEDIA_DOWNLOADS, STORAGE, TIKTOK_PROMPT_MASTERS, ensure_storage, get_display_name, list_blueprint_files, list_prompt_master_files, load_blueprint_file, load_prompt_master_file, now, read_json, set_display_name, write_json
25
+ from hermes_ui.storage import BLUEPRINTS, DEFAULT_LLM_PROVIDER, MEDIA_DOWNLOADS, STORAGE, TIKTOK_PROMPT_MASTERS, ensure_storage, get_display_name, list_blueprint_files, list_prompt_master_files, load_blueprint_file, load_prompt_master_file, now, read_json, set_display_name, write_json
26
26
  from app.modules.niche_finder.apify import ApifyError, DEFAULT_ACTOR_ID, abort_actor_run, build_actor_input, get_dataset_items, normalize_video_items, start_actor_run, wait_for_actor_run
27
27
  from app.modules.niche_finder.core import NicheAnalysisError, run_niche_analysis
28
28
  from app.modules.niche_finder.data_loader import DatasetError, download_kaggle_dataset
@@ -3566,8 +3566,9 @@ def render_settings():
3566
3566
  gemini_image_size = st.selectbox("Tamanho da imagem", ["1K", "2K", "4K"], index=["1K", "2K", "4K"].index(str(settings.get("gemini_image_size") or "1K")) if str(settings.get("gemini_image_size") or "1K") in {"1K", "2K", "4K"} else 0)
3567
3567
 
3568
3568
  with st.expander("LLM — providers e modelos", expanded=True):
3569
- provider_options = ["moonshot", "shengsuanyun", "openai", "gemini", "deepseek", "qwen", "azure", "volcengine", "grok", "minimax", "mimo", "cloudflare", "modelscope", "aihubmix", "aimlapi", "evolink", "ollama", "oneapi", "litellm", "groq", "pollinations"]
3570
- 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)
3569
+ provider_options = ["openai", "moonshot", "shengsuanyun", "gemini", "deepseek", "qwen", "azure", "volcengine", "grok", "minimax", "mimo", "cloudflare", "modelscope", "aihubmix", "aimlapi", "evolink", "ollama", "oneapi", "litellm", "groq", "pollinations"]
3570
+ current_llm_provider = str(settings.get("llm_provider") or DEFAULT_LLM_PROVIDER).strip().lower()
3571
+ llm_provider = st.selectbox("LLM provider", provider_options, index=provider_options.index(current_llm_provider) if current_llm_provider in provider_options else 0)
3571
3572
  st.markdown("**OpenAI/ NVIDIA NIM — API key, Base URL e modelo**")
3572
3573
  st.caption("O provider interno continua a ser `openai`, mas pode usar qualquer endpoint OpenAI-compatible. Para NVIDIA NIM, a Base URL predefinida é `https://integrate.api.nvidia.com/v1`; o selector consulta `/models` e deixa um campo manual como fallback.")
3573
3574
  openai_cols = st.columns(3)
@@ -10,6 +10,8 @@ from typing import Any
10
10
 
11
11
  ROOT = Path(__file__).resolve().parents[1]
12
12
  STORAGE = Path(os.getenv("THUNDERBOLT_STORAGE_DIR") or ROOT / "storage")
13
+ DEFAULT_LLM_PROVIDER = "openai"
14
+ LEGACY_DEFAULT_LLM_PROVIDERS = {"", "moonshot"}
13
15
  STATE = STORAGE / "state"
14
16
  BLUEPRINTS = STORAGE / "blueprints"
15
17
  TIKTOK_PROMPT_MASTERS = STORAGE / "tiktok" / "prompts_master"
@@ -125,7 +127,7 @@ DEFAULTS: dict[str, Any] = {
125
127
  "apify_actor_id": "streamers~youtube-scraper",
126
128
  "apify_poll_interval_seconds": 10,
127
129
  "apify_run_timeout_seconds": 900,
128
- "llm_provider": "moonshot",
130
+ "llm_provider": DEFAULT_LLM_PROVIDER
129
131
  "moonshot_api_key": "",
130
132
  "moonshot_base_url": "",
131
133
  "moonshot_model_name": "",
@@ -290,6 +292,18 @@ def seed_prompt_masters() -> None:
290
292
  shutil.copy2(source, target)
291
293
 
292
294
 
295
+ def _migrate_settings(settings: Any) -> tuple[dict[str, Any], bool]:
296
+ """Keep the shipped OpenAI/NVIDIA NIM default across package upgrades."""
297
+ if not isinstance(settings, dict):
298
+ return {"llm_provider": DEFAULT_LLM_PROVIDER}, True
299
+
300
+ provider = str(settings.get("llm_provider") or "").strip().lower()
301
+ if provider not in LEGACY_DEFAULT_LLM_PROVIDERS:
302
+ return settings, False
303
+
304
+ return {**settings, "llm_provider": DEFAULT_LLM_PROVIDER}, True
305
+
306
+
293
307
  def ensure_storage() -> None:
294
308
  for path in [STATE, BLUEPRINTS / "canais", BLUEPRINTS / "nichos", BLUEPRINTS / "importados", BLUEPRINTS / "brandings", TIKTOK_PROMPT_MASTERS, MEDIA_DOWNLOADS, STORAGE / "brand", STORAGE / "scripts", STORAGE / "thumbnails", STORAGE / "videos", STORAGE / "artifacts", STORAGE / "skills", STORAGE / "metadata_cleaner", STORAGE / "metadata_cleaner" / "outputs", STORAGE / "music", STORAGE / "voice_previews", STORAGE / "python_editor", NICHES_DATA]:
295
309
  path.mkdir(parents=True, exist_ok=True)
@@ -321,7 +335,13 @@ def read_json(name: str, default: Any | None = None) -> Any:
321
335
  path = STATE / name
322
336
  try:
323
337
  with path.open("r", encoding="utf-8") as handle:
324
- return json.load(handle)
338
+ data = json.load(handle)
339
+ if name != "settings.json":
340
+ return data
341
+ migrated, changed = _migrate_settings(data)
342
+ if changed:
343
+ atomic_write(path, migrated)
344
+ return migrated
325
345
  except (json.JSONDecodeError, OSError):
326
346
  backup = path.with_suffix(path.suffix + f".corrupt-{datetime.now().strftime('%Y%m%d%H%M%S')}")
327
347
  if path.exists():
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.2.89",
3
+ "version": "0.2.90",
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",
@@ -302,6 +302,9 @@ function writeSettings(moneyprinterPath) {
302
302
  try { settings = JSON.parse(readFileSync(settingsPath, "utf8")); } catch { settings = {}; }
303
303
  }
304
304
  settings.moneyprinter_path = moneyprinterPath;
305
+ if (!settings.llm_provider || String(settings.llm_provider).trim().toLowerCase() === "moonshot") {
306
+ settings.llm_provider = "openai";
307
+ }
305
308
  settings.port = Number(process.env.THUNDERBOLT_PORT || process.env.HERMES_PORT || settings.port || 3030);
306
309
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
307
310
  }