@danhachuel/thunderbolt 0.3.46 → 0.3.47

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.3.46
5
+ > **Versão deste manual:** 0.3.47
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 --prefer-online @danhachuel/thunderbolt@0.3.46 install
103
+ npx.cmd --yes --prefer-online @danhachuel/thunderbolt@0.3.47 install
104
104
  ```
105
105
 
106
106
  Linux/macOS:
107
107
 
108
108
  ```bash
109
- npx --yes --prefer-online @danhachuel/thunderbolt@0.3.46 install
109
+ npx --yes --prefer-online @danhachuel/thunderbolt@0.3.47 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.
@@ -114,7 +114,7 @@ A instalação normal é **segura para actualizações**: preserva `storage`, Bl
114
114
  Se quiser apagar absolutamente tudo de forma intencional, use o comando destrutivo separado:
115
115
 
116
116
  ```powershell
117
- npx.cmd --yes --prefer-online @danhachuel/thunderbolt@0.3.46 install --purge-data
117
+ npx.cmd --yes --prefer-online @danhachuel/thunderbolt@0.3.47 install --purge-data
118
118
  ```
119
119
 
120
120
  O parâmetro `--purge-data` apaga Blueprints, Brandings, configurações, storage e artefactos locais. Não o use numa actualização normal.
@@ -359,7 +359,7 @@ Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
359
359
 
360
360
  ### 4.1 Pools de LLM, imagem e vídeo
361
361
 
362
- Em **Configuração API > API Keys**, o expander **LLM — providers e modelos** continua a guardar cartões independentes para os providers textuais. Pode manter várias API keys do mesmo provider em cartões distintos; a geração textual percorre o **pool LLM** e tenta o cartão seguinte apenas em quota, timeout, erro de transporte ou falha transitória.
362
+ Em **Configuração API > API Keys**, o expander **LLM — providers e modelos** continua a guardar cartões independentes para os providers textuais. O campo **Prioridade** substitui o antigo checkbox **LLM principal**: o cartão com valor **1** é tentado primeiro, depois o **2**, o **3** e assim sucessivamente. Pode manter várias API keys do mesmo provider em cartões distintos; a geração textual percorre o pool por essa ordem e tenta a prioridade seguinte apenas em quota, timeout, erro de transporte ou falha transitória. A chave interna de cartão activo permanece apenas como espelho de compatibilidade das instalações antigas.
363
363
 
364
364
  O bloco **Limite LLM NVIDIA NIM** permite ligar **Activar limitador NVIDIA NIM — 40 RPM**. O valor padrão é 40 pedidos numa janela de 60 segundos. O contador é persistido localmente por cartão/chave e aplica-se à criação manual, aos workers e às automações. A opção vem desligada para não alterar instalações existentes; ligue-a quando o endpoint activo for NVIDIA NIM e a sua conta tiver esse limite.
365
365
 
@@ -522,7 +522,7 @@ Ao abrir a página, o Thunderbolt não prepara dados públicos, não descarrega
522
522
 
523
523
  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.
524
524
 
525
- 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 --prefer-online @danhachuel/thunderbolt@0.3.46 install`; o instalador detecta e reutiliza o que já estiver válido.
525
+ 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 --prefer-online @danhachuel/thunderbolt@0.3.47 install`; o instalador detecta e reutiliza o que já estiver válido.
526
526
 
527
527
  ### Niche Finder Apify
528
528
 
package/README.md CHANGED
@@ -69,7 +69,7 @@ No topo da área principal da aplicação existe o menu nativo de idioma no padr
69
69
 
70
70
  A UI suporta os temas **Dark** e **Light** através do menu nativo de três pontos do Streamlit, no local original do toolbar. Não existe um selector Theme adicional dentro da página. A configuração distribuída em `.streamlit/config.toml` disponibiliza as variantes nomeadas **Dark** e **Light**, e o menu nativo continua responsável por alternar entre os modos, seguindo o padrão do [MoneyPrinterTurbo](https://github.com/harry0703/MoneyPrinterTurbo). O CSS próprio do Thunderbolt usa cores semânticas, `currentColor` e `color-mix` para acompanhar o tema activo, sem alterar a posição nem a funcionalidade do toolbar, do botão Deploy e do menu principal.
71
71
 
72
- ## Navegação da UI 0.3.46
72
+ ## Navegação da UI 0.3.47
73
73
 
74
74
  A barra lateral mantém os níveis principais, nesta ordem: **Início**, **Niche Finder**, **Pipeline**, **Pipeline TikTok**, **Automação**, **Edição**, **AI Influencers** e **Configurações**. **Pipeline Vídeos** é expansível e contém **Criação de Vídeos**, **Backlog Vídeos**, **Roteiros**, **Thumbnails** e **Upload**. **Pipeline Música** é expansível e contém **Criação de Músicas** e **Upload Música**. **Automação** também é expansível e contém **Automação Youtube**. **Edição** é expansível e contém **Limpador de Metadados**, **Cortes**, **Editor Python** e **Download Mídia**, nessa ordem. **AI Influencers** é expansível e contém **Personagens**, **Redes Sociais**, **Tutorial Meta** e **Tutorial Supabase**, nessa ordem. **Niche Finder** é expansível e contém **Niche Finder Kaggle** e **Niche Finder Apify**. **Configurações** é expansível e contém **Canais Youtube**, **Blueprints Youtube**, **MCP**, **Contas Google**, **Notificações**, **Logs** e **Configuração API**, nessa ordem. O Início reúne o dashboard e as filas do Pipeline, sem botões de acções rápidas.
75
75
 
@@ -85,6 +85,8 @@ Em **Configuração API > API Keys**, a subaba **Fontes de materiais** segue o p
85
85
 
86
86
  A subaba **Serviços e modelos** mantém as credenciais de providers e serviços que não são fontes de materiais. A chave `gemini_image_api_key` da Nano Banana continua separada de `gemini_api_key` do LLM textual. `INNERTUBE_API_KEY` permanece exclusivamente em **Configurações > Contas Google**, no bloco de configuração global fora dos cartões, e não é duplicada em API Keys.
87
87
 
88
+ Nos cartões de **LLM — providers e modelos**, o campo **Prioridade** define a ordem de tentativa do pool textual. O valor **1** é usado primeiro; em quota, timeout, erro de transporte ou falha transitória, o router tenta a prioridade **2**, depois **3** e assim sucessivamente. O checkbox antigo **LLM principal** deixou de existir. A chave interna de cartão activo continua apenas como espelho de compatibilidade para instalações antigas.
89
+
88
90
  O expander **Imagem e Video** reúne cartões independentes para **Nano Banana**, **Pollinations.ai**, **Agnes AI**, **Hugging Face Inference API**, **Cloudflare Workers AI**, **InferencePort Proxy**, **阿里云 (Alibaba Cloud Model Studio)**, **KIE AI** e **FAL AI**. Cada cartão permite configurar API key/token quando necessário, modelo, Base URL, activar o provider, escolher participação no **Pool Imagem** e/ou **Pool Vídeo**, definir prioridade e executar **Testar Chamada API**. Os parâmetros técnicos de composição, como **Image Size** e **Aspect Ratio**, não são apresentados nem editáveis nos cartões: ficam como defaults internos e são acrescentados automaticamente ao prompt da geração de imagem e/ou vídeo. O InferencePort usa por defeito `http://localhost:8080/v1` e não exige chave; o Cloudflare requer Account ID; os restantes providers devem ser preenchidos de acordo com a conta e endpoint disponibilizados pelo serviço.
89
91
 
90
92
  O router mantém três pools independentes: **LLM textual**, **imagem** e **vídeo**. O failover só passa ao cartão seguinte em quota, timeout, erro de transporte ou HTTP transitório; erros de credencial, endpoint/modelo inexistente ou payload inválido ficam registados e não são mascarados por um provider diferente. O pool de vídeo externo é opcional: quando desligado, o worker continua a usar o motor local MoneyPrinterTurbo; quando ligado, usa apenas os cartões marcados para Pool Vídeo.
package/app/main.py CHANGED
@@ -38,7 +38,7 @@ from hermes_ui.cuts import CutsError, download_direct_video_url, generate_clips,
38
38
  from hermes_ui.mcp import detect_local_service, install_skill_locally, load_integrations, load_server_config, read_packaged_skill, save_server_config, update_integration
39
39
  from hermes_ui.mcp_server import server_status, start_server, stop_server
40
40
  from hermes_ui.material_sources import apply_material_source_cards_to_settings, ensure_material_source_cards, material_source_catalog, material_source_definition, new_material_card, normalize_material_card, selected_material_source
41
- from hermes_ui.llm_providers import LLM_CARDS_KEY, LLM_ACTIVE_CARD_KEY, LLM_PROVIDER_CATALOG, apply_llm_cards_to_settings, ensure_llm_provider_cards, new_llm_card, normalize_llm_card, provider_definition, test_llm_provider_card, stamp_test_result
41
+ from hermes_ui.llm_providers import LLM_CARDS_KEY, LLM_PROVIDER_CATALOG, apply_llm_cards_to_settings, ensure_llm_provider_cards, new_llm_card, normalize_llm_card, provider_definition, test_llm_provider_card, stamp_test_result
42
42
  from hermes_ui.media_providers import MEDIA_CARDS_KEY, MEDIA_IMAGE_ACTIVE_CARD_KEY, MEDIA_VIDEO_ACTIVE_CARD_KEY, apply_media_provider_cards_to_settings, ensure_media_provider_cards, media_provider_catalog, media_provider_definition, new_media_card, normalize_media_card
43
43
  from hermes_ui.music import list_music_files, materialize_suno_audio, request_suno_generation, store_music_file
44
44
  from hermes_ui.media_downloader import AUDIO_FORMATS, VIDEO_CONTAINERS, VIDEO_QUALITY_OPTIONS, MediaDownloadError, build_download_options, clear_media_download_history, dependency_status, download_media, list_media_downloads, media_download_file
@@ -5040,11 +5040,14 @@ def _render_llm_card(settings: dict[str, Any], cards: list[dict[str, Any]], inde
5040
5040
  with status_cols[0]:
5041
5041
  enabled = st.checkbox("Provider activo", value=bool(card.get("enabled", True)), key=f"llm_card_{card_id}_enabled")
5042
5042
  with status_cols[1]:
5043
- primary_llm = st.checkbox(
5044
- "LLM principal",
5045
- value=str(settings.get(LLM_ACTIVE_CARD_KEY) or "") == card_id,
5046
- help="Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.",
5047
- key=f"llm_card_{card_id}_primary",
5043
+ priority = st.number_input(
5044
+ "Prioridade",
5045
+ min_value=1,
5046
+ max_value=999,
5047
+ value=max(1, int(card.get("priority", index + 1))),
5048
+ step=1,
5049
+ help="Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, segue para 2, 3 e assim por diante.",
5050
+ key=f"llm_card_{card_id}_priority",
5048
5051
  )
5049
5052
  with status_cols[2]:
5050
5053
  telegram_llm = st.checkbox(
@@ -5060,29 +5063,28 @@ def _render_llm_card(settings: dict[str, Any], cards: list[dict[str, Any]], inde
5060
5063
  remove_clicked = st.form_submit_button("Remover cartão", use_container_width=True, key=f"llm_card_{card_id}_remove")
5061
5064
 
5062
5065
  edited = dict(card)
5063
- edited.update({"api_key": str(api_key or "").strip(), "model": str(model or "").strip(), "base_url": str(base_url or "").strip(), "enabled": bool(enabled), "telegram_llm": bool(telegram_llm), **extra_values})
5066
+ edited.update({"api_key": str(api_key or "").strip(), "model": str(model or "").strip(), "base_url": str(base_url or "").strip(), "enabled": bool(enabled), "priority": max(1, int(priority)), "telegram_llm": bool(telegram_llm), **extra_values})
5064
5067
  cards[index] = edited
5065
5068
  if test_clicked:
5066
5069
  test_result = test_llm_provider_card(edited)
5067
5070
  edited["test_result"] = stamp_test_result(test_result)
5068
- _persist_llm_cards(settings, cards, str(settings.get(LLM_ACTIVE_CARD_KEY) or card_id))
5071
+ _persist_llm_cards(settings, cards)
5069
5072
  elif refresh_clicked:
5070
5073
  try:
5071
5074
  from integrations.openai_model_discovery import fetch_openai_compatible_models
5072
5075
  discovered = fetch_openai_compatible_models(edited.get("api_key", ""), edited.get("base_url", ""))
5073
5076
  st.session_state[f"llm_model_catalog_{card_id}"] = discovered
5074
- _persist_llm_cards(settings, cards, str(settings.get(LLM_ACTIVE_CARD_KEY) or card_id))
5077
+ _persist_llm_cards(settings, cards)
5075
5078
  st.success(f"{len(discovered)} modelo(s) disponíveis neste endpoint.")
5076
5079
  except Exception:
5077
5080
  st.error("Não foi possível consultar os modelos deste endpoint.")
5078
5081
  elif save_clicked:
5079
- active_id = card_id if primary_llm and enabled else str(settings.get(LLM_ACTIVE_CARD_KEY) or "")
5080
- _persist_llm_cards(settings, cards, active_id)
5082
+ _persist_llm_cards(settings, cards)
5081
5083
  st.success("Cartão LLM guardado.")
5082
5084
  st.rerun()
5083
5085
  elif remove_clicked:
5084
5086
  remaining = [item for item in cards if str(item.get("id")) != card_id]
5085
- _persist_llm_cards(settings, remaining, str(settings.get(LLM_ACTIVE_CARD_KEY) or ""))
5087
+ _persist_llm_cards(settings, remaining)
5086
5088
  st.success("Cartão LLM removido.")
5087
5089
  st.rerun()
5088
5090
 
@@ -5102,7 +5104,7 @@ def render_llm_provider_cards(settings: dict[str, Any], *, embedded: bool = Fals
5102
5104
  settings.update(migrated)
5103
5105
  write_json("settings.json", settings)
5104
5106
  with st.expander("LLM — providers e modelos", expanded=False):
5105
- st.caption("Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.")
5107
+ st.caption("Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; a prioridade 1 é tentada primeiro e o router segue para as prioridades seguintes em falhas elegíveis.")
5106
5108
  for index in range(len(cards)):
5107
5109
  _render_llm_card(settings, cards, index, embedded=embedded)
5108
5110
  st.divider()
@@ -5121,8 +5123,9 @@ def render_llm_provider_cards(settings: dict[str, Any], *, embedded: bool = Fals
5121
5123
  )
5122
5124
  if add_provider_clicked:
5123
5125
  new_card = new_llm_card(provider_to_add, card_id=f"llm-{provider_to_add}-{uuid.uuid4().hex[:8]}")
5126
+ new_card["priority"] = max((int(item.get("priority", index + 1)) for index, item in enumerate(cards)), default=0) + 1
5124
5127
  cards.append(new_card)
5125
- _persist_llm_cards(settings, cards, str(settings.get(LLM_ACTIVE_CARD_KEY) or DEFAULT_LLM_CARD_ID))
5128
+ _persist_llm_cards(settings, cards)
5126
5129
  st.rerun()
5127
5130
 
5128
5131
 
@@ -205,16 +205,16 @@ for _language_code, _llm_extra_values in _LLM_EXTRA_PROVIDER_TRANSLATIONS.items(
205
205
  UI_TRANSLATIONS[_language_code].update(_llm_extra_values)
206
206
 
207
207
  _LLM_CONTROL_TRANSLATIONS = {
208
- "pt": {"LLM principal": "LLM principal", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.", "Account Id": "Account ID", "Gateway Id": "Gateway ID", "Api Version": "Versão da API", "Endpoint gerido pelo provider: ": "Endpoint gerido pelo provider: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.", "ID do modelo usado pelo endpoint Chat Completions.": "ID do modelo usado pelo endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo."},
209
- "en": {"LLM principal": "Primary LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Use this card as the primary provider for topics, scripts, titles and keywords.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Use this card exclusively for Telegram notification routing. Only one card can be selected.", "Account Id": "Account ID", "Gateway Id": "Gateway ID", "Api Version": "API version", "Endpoint gerido pelo provider: ": "Provider-managed endpoint: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "This field appears only for providers with a configurable OpenAI-compatible endpoint.", "ID do modelo usado pelo endpoint Chat Completions.": "Model ID used by the Chat Completions endpoint.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configure each provider in an independent card. You can repeat a provider for multiple API keys; the active card is used for content generation."},
210
- "zh": {"LLM principal": "主要 LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "将此卡片用作主题、脚本、标题和关键词的主要提供商。", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "此卡片仅用于 Telegram 通知路由。只能选择一个卡片。", "Account Id": "账户 ID", "Gateway Id": "网关 ID", "Api Version": "API 版本", "Endpoint gerido pelo provider: ": "提供商管理的端点:", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "仅在提供商支持自定义 OpenAI 兼容端点时显示。", "ID do modelo usado pelo endpoint Chat Completions.": "Chat Completions 端点使用的模型 ID。", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "在独立卡片中配置每个提供商。可为同一提供商添加多个 API 密钥;内容生成使用活动卡片。"},
211
- "de": {"LLM principal": "Primärer LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Diese Karte als primären Anbieter für Themen, Skripte, Titel und Keywords verwenden.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Diese Karte ausschließlich für die Telegram-Benachrichtigungsweiterleitung verwenden. Nur eine Karte kann ausgewählt werden.", "Account Id": "Konto-ID", "Gateway Id": "Gateway-ID", "Api Version": "API-Version", "Endpoint gerido pelo provider: ": "Vom Anbieter verwalteter Endpunkt: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Dieses Feld erscheint nur bei Anbietern mit konfigurierbarem OpenAI-kompatiblem Endpunkt.", "ID do modelo usado pelo endpoint Chat Completions.": "Vom Chat-Completions-Endpunkt verwendete Modell-ID.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Jeden Anbieter in einer eigenen Karte konfigurieren. Anbieter können für mehrere API-Schlüssel wiederholt werden; die aktive Karte wird für die Inhaltserstellung verwendet."},
212
- "vi": {"LLM principal": "LLM chính", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Dùng thẻ này làm nhà cung cấp chính cho chủ đề, kịch bản, tiêu đề và từ khóa.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Chỉ dùng thẻ này để định tuyến thông báo Telegram. Chỉ được chọn một thẻ.", "Account Id": "ID tài khoản", "Gateway Id": "ID cổng", "Api Version": "Phiên bản API", "Endpoint gerido pelo provider: ": "Endpoint do nhà cung cấp quản lý: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Chỉ hiển thị trường này với nhà cung cấp có endpoint OpenAI tương thích tùy chỉnh.", "ID do modelo usado pelo endpoint Chat Completions.": "ID mô hình được endpoint Chat Completions sử dụng.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Định cấu hình từng nhà cung cấp trong thẻ riêng. Có thể lặp lại nhà cung cấp cho nhiều khóa API; thẻ đang hoạt động được dùng để tạo nội dung."},
213
- "tr": {"LLM principal": "Birincil LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Konu, senaryo, başlık ve anahtar kelimeler için bu kartı birincil sağlayıcı olarak kullanın.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Bu kartı yalnızca Telegram bildirim yönlendirmesi için kullanın. Yalnızca bir kart seçilebilir.", "Account Id": "Hesap Kimliği", "Gateway Id": "Ağ Geçidi Kimliği", "Api Version": "API sürümü", "Endpoint gerido pelo provider: ": "Sağlayıcı tarafından yönetilen uç nokta: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Bu alan yalnızca yapılandırılabilir OpenAI uyumlu uç noktası olan sağlayıcılarda görünür.", "ID do modelo usado pelo endpoint Chat Completions.": "Chat Completions uç noktası tarafından kullanılan model kimliği.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Her sağlayıcıyı bağımsız bir kartta yapılandırın. Bir sağlayıcı birden fazla API anahtarı için tekrarlanabilir; etkin kart içerik üretiminde kullanılır."},
214
- "ru": {"LLM principal": "Основной LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Использовать эту карточку как основной провайдер для тем, сценариев, заголовков и ключевых слов.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Использовать эту карточку только для маршрутизации уведомлений Telegram. Можно выбрать только одну карточку.", "Account Id": "ID аккаунта", "Gateway Id": "ID шлюза", "Api Version": "Версия API", "Endpoint gerido pelo provider: ": "Эндпоинт под управлением провайдера: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Поле отображается только для провайдеров с настраиваемым OpenAI-совместимым эндпоинтом.", "ID do modelo usado pelo endpoint Chat Completions.": "ID модели, используемый эндпоинтом Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Настройте каждого провайдера в отдельной карточке. Провайдера можно повторить для нескольких API-ключей; активная карточка используется для генерации контента."},
215
- "es": {"LLM principal": "LLM principal", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Usar esta tarjeta como proveedor principal para temas, guiones, títulos y palabras clave.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Usar esta tarjeta exclusivamente para enrutar notificaciones de Telegram. Solo se puede seleccionar una tarjeta.", "Account Id": "ID de cuenta", "Gateway Id": "ID de puerta de enlace", "Api Version": "Versión de API", "Endpoint gerido pelo provider: ": "Endpoint gestionado por el proveedor: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Este campo solo aparece para proveedores con un endpoint OpenAI compatible configurable.", "ID do modelo usado pelo endpoint Chat Completions.": "ID del modelo usado por el endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configura cada proveedor en una tarjeta independiente. Puedes repetir un proveedor para varias claves API; la tarjeta activa se usa para generar contenido."},
216
- "id": {"LLM principal": "LLM utama", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Gunakan kartu ini sebagai penyedia utama untuk topik, skrip, judul, dan kata kunci.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Gunakan kartu ini khusus untuk perutean notifikasi Telegram. Hanya satu kartu yang dapat dipilih.", "Account Id": "ID akun", "Gateway Id": "ID gateway", "Api Version": "Versi API", "Endpoint gerido pelo provider: ": "Endpoint yang dikelola penyedia: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Bidang ini hanya tampil untuk penyedia dengan endpoint OpenAI-compatible yang dapat dikonfigurasi.", "ID do modelo usado pelo endpoint Chat Completions.": "ID model yang digunakan endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Konfigurasikan setiap penyedia dalam kartu terpisah. Penyedia dapat diulang untuk beberapa kunci API; kartu aktif digunakan untuk pembuatan konten."},
217
- "it": {"LLM principal": "LLM principale", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Usa questa scheda come provider principale per argomenti, copioni, titoli e parole chiave.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Usa questa scheda esclusivamente per il routing delle notifiche Telegram. È possibile selezionare una sola scheda.", "Account Id": "ID account", "Gateway Id": "ID gateway", "Api Version": "Versione API", "Endpoint gerido pelo provider: ": "Endpoint gestito dal provider: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Il campo appare solo per provider con endpoint OpenAI compatibile configurabile.", "ID do modelo usado pelo endpoint Chat Completions.": "ID del modello usato dall'endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configura ogni provider in una scheda indipendente. Puoi ripetere un provider per più chiavi API; la scheda attiva viene usata per generare contenuti."},
208
+ "pt": {"Prioridade": "Prioridade", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.", "Account Id": "Account ID", "Gateway Id": "Gateway ID", "Api Version": "Versão da API", "Endpoint gerido pelo provider: ": "Endpoint gerido pelo provider: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.", "ID do modelo usado pelo endpoint Chat Completions.": "ID do modelo usado pelo endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo."},
209
+ "en": {"Prioridade": "Priority", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Use this card as the primary provider for topics, scripts, titles and keywords.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Use this card exclusively for Telegram notification routing. Only one card can be selected.", "Account Id": "Account ID", "Gateway Id": "Gateway ID", "Api Version": "API version", "Endpoint gerido pelo provider: ": "Provider-managed endpoint: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "This field appears only for providers with a configurable OpenAI-compatible endpoint.", "ID do modelo usado pelo endpoint Chat Completions.": "Model ID used by the Chat Completions endpoint.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configure each provider in an independent card. You can repeat a provider for multiple API keys; the active card is used for content generation."},
210
+ "zh": {"Prioridade": "优先级", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "将此卡片用作主题、脚本、标题和关键词的主要提供商。", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "此卡片仅用于 Telegram 通知路由。只能选择一个卡片。", "Account Id": "账户 ID", "Gateway Id": "网关 ID", "Api Version": "API 版本", "Endpoint gerido pelo provider: ": "提供商管理的端点:", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "仅在提供商支持自定义 OpenAI 兼容端点时显示。", "ID do modelo usado pelo endpoint Chat Completions.": "Chat Completions 端点使用的模型 ID。", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "在独立卡片中配置每个提供商。可为同一提供商添加多个 API 密钥;内容生成使用活动卡片。"},
211
+ "de": {"Prioridade": "Priorität", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Diese Karte als primären Anbieter für Themen, Skripte, Titel und Keywords verwenden.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Diese Karte ausschließlich für die Telegram-Benachrichtigungsweiterleitung verwenden. Nur eine Karte kann ausgewählt werden.", "Account Id": "Konto-ID", "Gateway Id": "Gateway-ID", "Api Version": "API-Version", "Endpoint gerido pelo provider: ": "Vom Anbieter verwalteter Endpunkt: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Dieses Feld erscheint nur bei Anbietern mit konfigurierbarem OpenAI-kompatiblem Endpunkt.", "ID do modelo usado pelo endpoint Chat Completions.": "Vom Chat-Completions-Endpunkt verwendete Modell-ID.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Jeden Anbieter in einer eigenen Karte konfigurieren. Anbieter können für mehrere API-Schlüssel wiederholt werden; die aktive Karte wird für die Inhaltserstellung verwendet."},
212
+ "vi": {"Prioridade": "Ưu tiên", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Dùng thẻ này làm nhà cung cấp chính cho chủ đề, kịch bản, tiêu đề và từ khóa.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Chỉ dùng thẻ này để định tuyến thông báo Telegram. Chỉ được chọn một thẻ.", "Account Id": "ID tài khoản", "Gateway Id": "ID cổng", "Api Version": "Phiên bản API", "Endpoint gerido pelo provider: ": "Endpoint do nhà cung cấp quản lý: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Chỉ hiển thị trường này với nhà cung cấp có endpoint OpenAI tương thích tùy chỉnh.", "ID do modelo usado pelo endpoint Chat Completions.": "ID mô hình được endpoint Chat Completions sử dụng.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Định cấu hình từng nhà cung cấp trong thẻ riêng. Có thể lặp lại nhà cung cấp cho nhiều khóa API; thẻ đang hoạt động được dùng để tạo nội dung."},
213
+ "tr": {"Prioridade": "Öncelik", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Konu, senaryo, başlık ve anahtar kelimeler için bu kartı birincil sağlayıcı olarak kullanın.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Bu kartı yalnızca Telegram bildirim yönlendirmesi için kullanın. Yalnızca bir kart seçilebilir.", "Account Id": "Hesap Kimliği", "Gateway Id": "Ağ Geçidi Kimliği", "Api Version": "API sürümü", "Endpoint gerido pelo provider: ": "Sağlayıcı tarafından yönetilen uç nokta: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Bu alan yalnızca yapılandırılabilir OpenAI uyumlu uç noktası olan sağlayıcılarda görünür.", "ID do modelo usado pelo endpoint Chat Completions.": "Chat Completions uç noktası tarafından kullanılan model kimliği.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Her sağlayıcıyı bağımsız bir kartta yapılandırın. Bir sağlayıcı birden fazla API anahtarı için tekrarlanabilir; etkin kart içerik üretiminde kullanılır."},
214
+ "ru": {"Prioridade": "Приоритет", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Использовать эту карточку как основной провайдер для тем, сценариев, заголовков и ключевых слов.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Использовать эту карточку только для маршрутизации уведомлений Telegram. Можно выбрать только одну карточку.", "Account Id": "ID аккаунта", "Gateway Id": "ID шлюза", "Api Version": "Версия API", "Endpoint gerido pelo provider: ": "Эндпоинт под управлением провайдера: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Поле отображается только для провайдеров с настраиваемым OpenAI-совместимым эндпоинтом.", "ID do modelo usado pelo endpoint Chat Completions.": "ID модели, используемый эндпоинтом Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Настройте каждого провайдера в отдельной карточке. Провайдера можно повторить для нескольких API-ключей; активная карточка используется для генерации контента."},
215
+ "es": {"Prioridade": "Prioridad", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Usar esta tarjeta como proveedor principal para temas, guiones, títulos y palabras clave.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Usar esta tarjeta exclusivamente para enrutar notificaciones de Telegram. Solo se puede seleccionar una tarjeta.", "Account Id": "ID de cuenta", "Gateway Id": "ID de puerta de enlace", "Api Version": "Versión de API", "Endpoint gerido pelo provider: ": "Endpoint gestionado por el proveedor: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Este campo solo aparece para proveedores con un endpoint OpenAI compatible configurable.", "ID do modelo usado pelo endpoint Chat Completions.": "ID del modelo usado por el endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configura cada proveedor en una tarjeta independiente. Puedes repetir un proveedor para varias claves API; la tarjeta activa se usa para generar contenido."},
216
+ "id": {"Prioridade": "Prioritas", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Gunakan kartu ini sebagai penyedia utama untuk topik, skrip, judul, dan kata kunci.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Gunakan kartu ini khusus untuk perutean notifikasi Telegram. Hanya satu kartu yang dapat dipilih.", "Account Id": "ID akun", "Gateway Id": "ID gateway", "Api Version": "Versi API", "Endpoint gerido pelo provider: ": "Endpoint yang dikelola penyedia: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Bidang ini hanya tampil untuk penyedia dengan endpoint OpenAI-compatible yang dapat dikonfigurasi.", "ID do modelo usado pelo endpoint Chat Completions.": "ID model yang digunakan endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Konfigurasikan setiap penyedia dalam kartu terpisah. Penyedia dapat diulang untuk beberapa kunci API; kartu aktif digunakan untuk pembuatan konten."},
217
+ "it": {"Prioridade": "Priorità", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Usa questa scheda come provider principale per argomenti, copioni, titoli e parole chiave.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Usa questa scheda esclusivamente per il routing delle notifiche Telegram. È possibile selezionare una sola scheda.", "Account Id": "ID account", "Gateway Id": "ID gateway", "Api Version": "Versione API", "Endpoint gerido pelo provider: ": "Endpoint gestito dal provider: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Il campo appare solo per provider con endpoint OpenAI compatibile configurabile.", "ID do modelo usado pelo endpoint Chat Completions.": "ID del modello usato dall'endpoint Chat Completions.", "Configure cada provider num cartão independente. Pode repetir o mesmo provider para manter várias API keys; o cartão activo é usado pela geração de conteúdo.": "Configura ogni provider in una scheda indipendente. Puoi ripetere un provider per più chiavi API; la scheda attiva viene usata per generare contenuti."},
218
218
  }
219
219
  for _language_code, _llm_control_values in _LLM_CONTROL_TRANSLATIONS.items():
220
220
  UI_TRANSLATIONS[_language_code].update(_llm_control_values)
@@ -1357,19 +1357,19 @@ for _language_code, _api_test_values in _API_TEST_TRANSLATIONS.items():
1357
1357
  _NEW_UI_TRANSLATIONS: dict[str, dict[str, str]] = {
1358
1358
  "pl": {
1359
1359
  "Início": "Strona główna", "Niche Finder": "Wyszukiwarka nisz", "Pipeline": "Potok", "Pipeline TikTok": "Potok TikTok", "Automação": "Automatyzacja", "Edição": "Edycja", "AI Influencers": "Influencerzy AI", "Configurações": "Ustawienia", "Criação de Vídeos": "Tworzenie wideo", "Criação de Músicas": "Tworzenie muzyki", "Roteiros": "Scenariusze", "Upload": "Przesyłanie", "Prompts Master": "Mistrzowie promptów", "Contas TikTok": "Konta TikTok", "Automação Youtube": "Automatyzacja YouTube", "Niche Finder Kaggle": "Wyszukiwarka nisz Kaggle", "Niche Finder Apify": "Wyszukiwarka nisz Apify", "Limpador de Metadados": "Czyścik metadanych", "Cortes": "Cięcia", "Editor Python": "Edytor Pythona", "Download Mídia": "Pobieranie multimediów", "Personagens": "Postacie", "Redes Sociais": "Sieci społecznościowe", "Tutorial Meta": "Samouczek Meta", "Tutorial Supabase": "Samouczek Supabase", "Canais Youtube": "Kanały YouTube", "Blueprints Youtube": "Blueprinty YouTube", "Contas Google": "Konta Google", "Configuração API": "Konfiguracja API", "Notificações": "Powiadomienia", "Interface local para operação e automação de conteúdo faceless": "Lokalny interfejs do obsługi i automatyzacji treści faceless", "Canais": "Kanały", "activos": "aktywne", "Tarefas": "Zadania", "total registado": "łącznie zarejestrowano", "A fazer": "Do zrobienia", "na pipeline": "w potoku", "Em execução": "Uruchomione", "a decorrer": "w toku", "Concluídos": "Ukończone", "artefactos prontos": "gotowe artefakty", "Falhas": "Błędy", "requerem atenção": "wymagają uwagi", "Filas locais e dependências da cascata": "Lokalne kolejki i zależności potoku", "Niche": "Nisza", "Blueprints": "Blueprinty", "Brand": "Marka", "Script": "Scenariusz", "Title": "Tytuł", "Thumbnail": "Miniatura", "Video": "Wideo", "Edit": "Edytuj", "fila": "kolejka", "na biblioteca": "w bibliotece", "tarefa(s) na fila": "zadanie(a) w kolejce", "Language": "Język", "Theme": "Motyw", "Dark": "Ciemny", "Light": "Jasny",
1360
- "LLM — providers e modelos": "LLM — dostawcy i modele", "Adicionar provider LLM": "Dodaj dostawcę LLM", "Provider LLM": "Dostawca LLM", "Configurar Novo Provedor LLM": "Skonfiguruj nowego dostawcę LLM", "API key": "Klucz API", "Modelo": "Model", "Base URL": "Bazowy adres URL", "Modelo manual": "Model ręczny", "Escrever modelo manualmente": "Wpisz model ręcznie", "Provider activo": "Dostawca aktywny", "LLM Telegram": "LLM Telegram", "Testar chamada API": "Testuj wywołanie API", "Consultar modelos": "Pobierz modele", "Salvar": "Zapisz", "Remover cartão": "Usuń kartę", "Último teste:": "Ostatni test:", "Teste API:": "Test API:", "Missing key": "Brak klucza", "Missing configuration": "Brak konfiguracji", "Configured": "Skonfigurowano", "Local / sem API key": "Lokalny / bez klucza API", "Este provider não exige API key.": "Ten dostawca nie wymaga klucza API.", "LLM principal": "Główny LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Użyj tej karty jako głównego dostawcy do generowania tematów, scenariuszy, tytułów i słów kluczowych.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Używaj tej karty wyłącznie do kierowania powiadomień Telegram. Tylko jedna karta może być wybrana.", "Account Id": "Identyfikator konta", "Gateway Id": "Identyfikator bramy", "Api Version": "Wersja API", "Endpoint gerido pelo provider: ": "Punkt końcowy zarządzany przez dostawcę: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Punkt końcowy zgodny z OpenAI; widoczny tylko wtedy, gdy można go skonfigurować.", "ID do modelo usado pelo endpoint Chat Completions.": "Identyfikator modelu używanego przez punkt końcowy Chat Completions.", "Niche Finder — Kaggle": "Wyszukiwarka nisz — Kaggle", "Niche Finder — Apify": "Wyszukiwarka nisz — Apify", "Arquivos Base": "Pliki bazowe", "Pipeline Vídeos": "Potok wideo", "Canais e Perfis de Vídeos": "Kanały i profile wideo", "Canais YouTube": "Kanały YouTube", "Prompt Masters": "Mistrzowie promptów", "Backlog Vídeos": "Backlog wideo", "Thumbnails": "Miniatury", "Música": "Muzyka", "Upload Música": "Prześlij muzykę", "Geração de Conteúdo IA": "Generowanie treści AI", "Growth": "Rozwój", "Analista Growth Youtube": "Analityk rozwoju YouTube", "Analista Growth Tiktok": "Analityk rozwoju TikTok", "Analista Growth Instagram": "Analityk rozwoju Instagram", "Documentação": "Dokumentacja", "Tutorial Kaggle": "Samouczek Kaggle", "Tutorial Apify": "Samouczek Apify", "Pipeline Música": "Potok muzyki", "módulos disponíveis": "dostępne moduły", "Esta é uma chave API global do YouTube: aplica-se a todas as contas Google/YouTube e a todo o sistema. Não é associada a uma conta específica, não faz parte dos documentos de cookies/credenciais e não é editada no separador API Keys.": "To jest globalny klucz API YouTube: dotyczy wszystkich kont Google/YouTube i całego systemu. Nie jest przypisany do konkretnego konta, nie należy do dokumentów cookie/poświadczeń i nie jest edytowany w zakładce Klucze API.", "Chave global usada pelo Upload directo para todas as contas Google/YouTube. Guarde-a na configuração global, separada dos documentos de cookies.": "Globalny klucz używany przez bezpośrednie przesyłanie dla wszystkich kont Google/YouTube. Zapisz go w konfiguracji globalnej, oddzielnie od dokumentów cookie.", "Guardar INNERTUBE_API_KEY global": "Zapisz globalny INNERTUBE_API_KEY", "INNERTUBE_API_KEY global guardada para todas as contas Google/YouTube e para todo o sistema.": "Globalny INNERTUBE_API_KEY zapisany dla wszystkich kont Google/YouTube i całego systemu.", "Gerar tópico, roteiro e palavras-chave com IA": "Generuj temat, scenariusz i słowa kluczowe za pomocą AI", "A gerar tópico, roteiro e palavras-chave com IA…": "Generowanie tematu, scenariusza i słów kluczowych za pomocą AI…", "Tema, roteiro e palavras-chave gerados com IA.": "Temat, scenariusz i słowa kluczowe wygenerowane przez AI.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "Wypełnij pole Video Subject albo użyj przycisku automatycznego generowania pod słowami kluczowymi.", "Refazer thumbnail": "Utwórz miniaturę ponownie", "Salvar rascunho": "Zapisz wersję roboczą", "Rascunho guardado localmente": "Wersja robocza zapisana lokalnie", "Thumbnail refeita com sucesso.": "Miniatura została utworzona ponownie.", "Ver prompt da thumbnail": "Zobacz prompt miniatury", "Sem imagem": "Brak obrazu", "Imagem ainda não gerada": "Obraz nie został jeszcze wygenerowany", "Palavras-chave": "Słowa kluczowe", "Título do rascunho": "Tytuł wersji roboczej", "Gerar de Rascunho": "Generuj z wersji roboczej", "Roteiros guardados": "Zapisane scenariusze", "Seleccione um roteiro": "Wybierz scenariusz", "Configurações a completar": "Ustawienia do uzupełnienia", "Configurações de vídeo": "Ustawienia wideo", "Configurações de áudio": "Ustawienia audio", "Configurações de legendas": "Ustawienia napisów", "Continuar criação": "Kontynuuj tworzenie", "Gerar apenas o vídeo": "Generuj tylko wideo", "Seleccione um canal para continuar.": "Wybierz kanał, aby kontynuować.", "Ainda não existem roteiros guardados.": "Nie ma jeszcze zapisanych scenariuszy.", "Histórico guardado": "Zapisana historia", "Rascunho local": "Lokalna wersja robocza", "Origem": "Źródło", "Brandings": "Brandingi", "Pesquisa pública": "Wyszukiwanie publiczne", "Cadastro manual": "Rejestracja ręczna", "Contas cadastradas": "Zarejestrowane konta", "Biblioteca": "Biblioteka", "Importar do YouTube": "Importuj z YouTube", "Canais em lote gmail": "Kanały zbiorcze Gmail", "Criar vídeo": "Utwórz wideo", "Vídeos": "Wideo", "Novo roteiro/letra": "Nowy scenariusz/tekst", "Clusters encontrados": "Znalezione klastry", "Regras de associação": "Reguły powiązań", "Dados analisados": "Przeanalizowane dane", "Upload ficheiro": "Prześlij plik", "URL de vídeo": "Adres URL wideo", "Vídeos gerados": "Wygenerowane wideo", "Pasta local": "Folder lokalny", "Código Python": "Kod Python", "Upload convencional": "Zwykłe przesyłanie", "Upload directo": "Przesyłanie bezpośrednie", "Postiz": "Postiz", "Upload-Post": "Upload-Post", "API Keys": "Klucze API", "Teste de Voz": "Test głosu", "Serviços e modelos": "Usługi i modele", "Fontes de Materiais": "Źródła materiałów", "Client MCP": "Klient MCP", "Servidor MCP": "Serwer MCP", "Skill": "Umiejętność", "Guia de configuração do Supabase para automações com n8n.": "Przewodnik konfiguracji Supabase dla automatyzacji z n8n.", "Adicionar fonte de materiais": "Dodaj źródło materiałów", "Provedor de materiais": "Dostawca materiałów", "Configurar Nova Fonte de Materiais": "Skonfiguruj nowe źródło materiałów", "Fonte activa": "Źródło aktywne", "Usar esta fonte na pipeline": "Używaj tego źródła w potoku", "Esta fonte não usa API key.": "To źródło nie używa klucza API.", "A testar chamada API…": "Testowanie wywołania API…", "Último teste: API Key OK": "Ostatni test: klucz API OK", "Último teste: falta configuração": "Ostatni test: brak konfiguracji", "Último teste: requer autorização ou endpoint seguro": "Ostatni test: wymagana dodatkowa autoryzacja lub bezpieczny punkt końcowy", "Último teste: chamada falhou": "Ostatni test: wywołanie nie powiodło się", "Testar credenciais TTS e música": "Testuj dane uwierzytelniające TTS i muzyki", "Facebook Pages": "Strony Facebook", "Motion Control": "Sterowanie ruchem", "UGC Products": "Produkty UGC",
1360
+ "LLM — providers e modelos": "LLM — dostawcy i modele", "Adicionar provider LLM": "Dodaj dostawcę LLM", "Provider LLM": "Dostawca LLM", "Configurar Novo Provedor LLM": "Skonfiguruj nowego dostawcę LLM", "API key": "Klucz API", "Modelo": "Model", "Base URL": "Bazowy adres URL", "Modelo manual": "Model ręczny", "Escrever modelo manualmente": "Wpisz model ręcznie", "Provider activo": "Dostawca aktywny", "LLM Telegram": "LLM Telegram", "Testar chamada API": "Testuj wywołanie API", "Consultar modelos": "Pobierz modele", "Salvar": "Zapisz", "Remover cartão": "Usuń kartę", "Último teste:": "Ostatni test:", "Teste API:": "Test API:", "Missing key": "Brak klucza", "Missing configuration": "Brak konfiguracji", "Configured": "Skonfigurowano", "Local / sem API key": "Lokalny / bez klucza API", "Este provider não exige API key.": "Ten dostawca nie wymaga klucza API.", "Prioridade": "Priorytet", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Użyj tej karty jako głównego dostawcy do generowania tematów, scenariuszy, tytułów i słów kluczowych.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Używaj tej karty wyłącznie do kierowania powiadomień Telegram. Tylko jedna karta może być wybrana.", "Account Id": "Identyfikator konta", "Gateway Id": "Identyfikator bramy", "Api Version": "Wersja API", "Endpoint gerido pelo provider: ": "Punkt końcowy zarządzany przez dostawcę: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Punkt końcowy zgodny z OpenAI; widoczny tylko wtedy, gdy można go skonfigurować.", "ID do modelo usado pelo endpoint Chat Completions.": "Identyfikator modelu używanego przez punkt końcowy Chat Completions.", "Niche Finder — Kaggle": "Wyszukiwarka nisz — Kaggle", "Niche Finder — Apify": "Wyszukiwarka nisz — Apify", "Arquivos Base": "Pliki bazowe", "Pipeline Vídeos": "Potok wideo", "Canais e Perfis de Vídeos": "Kanały i profile wideo", "Canais YouTube": "Kanały YouTube", "Prompt Masters": "Mistrzowie promptów", "Backlog Vídeos": "Backlog wideo", "Thumbnails": "Miniatury", "Música": "Muzyka", "Upload Música": "Prześlij muzykę", "Geração de Conteúdo IA": "Generowanie treści AI", "Growth": "Rozwój", "Analista Growth Youtube": "Analityk rozwoju YouTube", "Analista Growth Tiktok": "Analityk rozwoju TikTok", "Analista Growth Instagram": "Analityk rozwoju Instagram", "Documentação": "Dokumentacja", "Tutorial Kaggle": "Samouczek Kaggle", "Tutorial Apify": "Samouczek Apify", "Pipeline Música": "Potok muzyki", "módulos disponíveis": "dostępne moduły", "Esta é uma chave API global do YouTube: aplica-se a todas as contas Google/YouTube e a todo o sistema. Não é associada a uma conta específica, não faz parte dos documentos de cookies/credenciais e não é editada no separador API Keys.": "To jest globalny klucz API YouTube: dotyczy wszystkich kont Google/YouTube i całego systemu. Nie jest przypisany do konkretnego konta, nie należy do dokumentów cookie/poświadczeń i nie jest edytowany w zakładce Klucze API.", "Chave global usada pelo Upload directo para todas as contas Google/YouTube. Guarde-a na configuração global, separada dos documentos de cookies.": "Globalny klucz używany przez bezpośrednie przesyłanie dla wszystkich kont Google/YouTube. Zapisz go w konfiguracji globalnej, oddzielnie od dokumentów cookie.", "Guardar INNERTUBE_API_KEY global": "Zapisz globalny INNERTUBE_API_KEY", "INNERTUBE_API_KEY global guardada para todas as contas Google/YouTube e para todo o sistema.": "Globalny INNERTUBE_API_KEY zapisany dla wszystkich kont Google/YouTube i całego systemu.", "Gerar tópico, roteiro e palavras-chave com IA": "Generuj temat, scenariusz i słowa kluczowe za pomocą AI", "A gerar tópico, roteiro e palavras-chave com IA…": "Generowanie tematu, scenariusza i słów kluczowych za pomocą AI…", "Tema, roteiro e palavras-chave gerados com IA.": "Temat, scenariusz i słowa kluczowe wygenerowane przez AI.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "Wypełnij pole Video Subject albo użyj przycisku automatycznego generowania pod słowami kluczowymi.", "Refazer thumbnail": "Utwórz miniaturę ponownie", "Salvar rascunho": "Zapisz wersję roboczą", "Rascunho guardado localmente": "Wersja robocza zapisana lokalnie", "Thumbnail refeita com sucesso.": "Miniatura została utworzona ponownie.", "Ver prompt da thumbnail": "Zobacz prompt miniatury", "Sem imagem": "Brak obrazu", "Imagem ainda não gerada": "Obraz nie został jeszcze wygenerowany", "Palavras-chave": "Słowa kluczowe", "Título do rascunho": "Tytuł wersji roboczej", "Gerar de Rascunho": "Generuj z wersji roboczej", "Roteiros guardados": "Zapisane scenariusze", "Seleccione um roteiro": "Wybierz scenariusz", "Configurações a completar": "Ustawienia do uzupełnienia", "Configurações de vídeo": "Ustawienia wideo", "Configurações de áudio": "Ustawienia audio", "Configurações de legendas": "Ustawienia napisów", "Continuar criação": "Kontynuuj tworzenie", "Gerar apenas o vídeo": "Generuj tylko wideo", "Seleccione um canal para continuar.": "Wybierz kanał, aby kontynuować.", "Ainda não existem roteiros guardados.": "Nie ma jeszcze zapisanych scenariuszy.", "Histórico guardado": "Zapisana historia", "Rascunho local": "Lokalna wersja robocza", "Origem": "Źródło", "Brandings": "Brandingi", "Pesquisa pública": "Wyszukiwanie publiczne", "Cadastro manual": "Rejestracja ręczna", "Contas cadastradas": "Zarejestrowane konta", "Biblioteca": "Biblioteka", "Importar do YouTube": "Importuj z YouTube", "Canais em lote gmail": "Kanały zbiorcze Gmail", "Criar vídeo": "Utwórz wideo", "Vídeos": "Wideo", "Novo roteiro/letra": "Nowy scenariusz/tekst", "Clusters encontrados": "Znalezione klastry", "Regras de associação": "Reguły powiązań", "Dados analisados": "Przeanalizowane dane", "Upload ficheiro": "Prześlij plik", "URL de vídeo": "Adres URL wideo", "Vídeos gerados": "Wygenerowane wideo", "Pasta local": "Folder lokalny", "Código Python": "Kod Python", "Upload convencional": "Zwykłe przesyłanie", "Upload directo": "Przesyłanie bezpośrednie", "Postiz": "Postiz", "Upload-Post": "Upload-Post", "API Keys": "Klucze API", "Teste de Voz": "Test głosu", "Serviços e modelos": "Usługi i modele", "Fontes de Materiais": "Źródła materiałów", "Client MCP": "Klient MCP", "Servidor MCP": "Serwer MCP", "Skill": "Umiejętność", "Guia de configuração do Supabase para automações com n8n.": "Przewodnik konfiguracji Supabase dla automatyzacji z n8n.", "Adicionar fonte de materiais": "Dodaj źródło materiałów", "Provedor de materiais": "Dostawca materiałów", "Configurar Nova Fonte de Materiais": "Skonfiguruj nowe źródło materiałów", "Fonte activa": "Źródło aktywne", "Usar esta fonte na pipeline": "Używaj tego źródła w potoku", "Esta fonte não usa API key.": "To źródło nie używa klucza API.", "A testar chamada API…": "Testowanie wywołania API…", "Último teste: API Key OK": "Ostatni test: klucz API OK", "Último teste: falta configuração": "Ostatni test: brak konfiguracji", "Último teste: requer autorização ou endpoint seguro": "Ostatni test: wymagana dodatkowa autoryzacja lub bezpieczny punkt końcowy", "Último teste: chamada falhou": "Ostatni test: wywołanie nie powiodło się", "Testar credenciais TTS e música": "Testuj dane uwierzytelniające TTS i muzyki", "Facebook Pages": "Strony Facebook", "Motion Control": "Sterowanie ruchem", "UGC Products": "Produkty UGC",
1361
1361
  },
1362
1362
  "ga": {
1363
1363
  "Início": "Baile", "Niche Finder": "Aimsitheoir nideoga", "Pipeline": "Píblíne", "Pipeline TikTok": "Píblíne TikTok", "Automação": "Uathoibriú", "Edição": "Eagarthóireacht", "AI Influencers": "Tionchair AI", "Configurações": "Socruithe", "Criação de Vídeos": "Cruthú físeán", "Criação de Músicas": "Cruthú ceoil", "Roteiros": "Scripteanna", "Upload": "Uaslódáil", "Prompts Master": "Máistrí leideanna", "Contas TikTok": "Cuntais TikTok", "Automação Youtube": "Uathoibriú YouTube", "Niche Finder Kaggle": "Aimsitheoir nideoga Kaggle", "Niche Finder Apify": "Aimsitheoir nideoga Apify", "Limpador de Metadados": "Glantóir meiteashonraí", "Cortes": "Ciorruithe", "Editor Python": "Eagarthóir Python", "Download Mídia": "Íoslódáil meán", "Personagens": "Carachtair", "Redes Sociais": "Líonraí sóisialta", "Tutorial Meta": "Teagasc Meta", "Tutorial Supabase": "Teagasc Supabase", "Canais Youtube": "Cainéil YouTube", "Blueprints Youtube": "Blueprints YouTube", "Contas Google": "Cuntais Google", "Configuração API": "Cumraíocht API", "Notificações": "Fógraí", "Interface local para operação e automação de conteúdo faceless": "Comhéadan logánta chun inneachar faceless a oibriú agus a uathoibriú", "Canais": "Cainéil", "activos": "gníomhach", "Tarefas": "Tascanna", "total registado": "iomlán cláraithe", "A fazer": "Le déanamh", "na pipeline": "sa phíblíne", "Em execução": "Ar siúl", "a decorrer": "ar bun", "Concluídos": "Críochnaithe", "artefactos prontos": "déantáin réidh", "Falhas": "Teipeanna", "requerem atenção": "teastaíonn aird", "Filas locais e dependências da cascata": "Scuainí logánta agus spleáchais na píblíne", "Niche": "Nideoige", "Blueprints": "Blueprints", "Brand": "Branda", "Script": "Script", "Title": "Teideal", "Thumbnail": "Mionsamhail", "Video": "Físeán", "Edit": "Cuir in eagar", "fila": "scuaine", "na biblioteca": "sa leabharlann", "tarefa(s) na fila": "tasc(anna) sa scuaine", "Language": "Teanga", "Theme": "Téama", "Dark": "Dorcha", "Light": "Geal",
1364
- "LLM — providers e modelos": "LLM — soláthraithe agus samhlacha", "Adicionar provider LLM": "Cuir soláthraí LLM leis", "Provider LLM": "Soláthraí LLM", "Configurar Novo Provedor LLM": "Cumraigh soláthraí nua LLM", "API key": "Eochair API", "Modelo": "Samhail", "Base URL": "URL bonn", "Modelo manual": "Samhail láimhe", "Escrever modelo manualmente": "Scríobh an tsamhail de láimh", "Provider activo": "Soláthraí gníomhach", "LLM Telegram": "LLM Telegram", "Testar chamada API": "Tástáil glao API", "Consultar modelos": "Faigh samhlacha", "Salvar": "Sábháil", "Remover cartão": "Bain cárta", "Último teste:": "An tástáil is déanaí:", "Teste API:": "Tástáil API:", "Missing key": "Eochair ar iarraidh", "Missing configuration": "Cumraíocht ar iarraidh", "Configured": "Cumraithe", "Local / sem API key": "Logánta / gan eochair API", "Este provider não exige API key.": "Níl eochair API ag teastáil ón soláthraí seo.", "LLM principal": "Príomh-LLM", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "Úsáid an cárta seo mar phríomhsholáthraí chun topaicí, scripteanna, teidil agus eochairfhocail a ghiniúint.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Úsáid an cárta seo go heisiach chun fógraí Telegram a ródú. Ní féidir ach cárta amháin a roghnú.", "Account Id": "Aitheantas cuntais", "Gateway Id": "Aitheantas geata", "Api Version": "Leagan API", "Endpoint gerido pelo provider: ": "Críochphointe á bhainistiú ag an soláthraí: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Críochphointe atá comhoiriúnach le OpenAI; taispeántar é nuair is féidir é a chumrú.", "ID do modelo usado pelo endpoint Chat Completions.": "Aitheantas na samhla a úsáideann críochphointe Chat Completions.", "Niche Finder — Kaggle": "Aimsitheoir nideoga — Kaggle", "Niche Finder — Apify": "Aimsitheoir nideoga — Apify", "Arquivos Base": "Comhaid bhunúsacha", "Pipeline Vídeos": "Píblíne físeáin", "Canais e Perfis de Vídeos": "Cainéil agus próifílí físeáin", "Canais YouTube": "Cainéil YouTube", "Prompt Masters": "Máistrí leideanna", "Backlog Vídeos": "Riaráiste físeáin", "Thumbnails": "Mionsamhlacha", "Música": "Ceol", "Upload Música": "Uaslódáil ceol", "Geração de Conteúdo IA": "Giniúint inneachair AI", "Growth": "Fás", "Analista Growth Youtube": "Anailísí fáis YouTube", "Analista Growth Tiktok": "Anailísí fáis TikTok", "Analista Growth Instagram": "Anailísí fáis Instagram", "Documentação": "Doiciméadú", "Tutorial Kaggle": "Teagasc Kaggle", "Tutorial Apify": "Teagasc Apify", "Pipeline Música": "Píblíne ceoil", "módulos disponíveis": "modúil ar fáil", "Esta é uma chave API global do YouTube: aplica-se a todas as contas Google/YouTube e a todo o sistema. Não é associada a uma conta específica, não faz parte dos documentos de cookies/credenciais e não é editada no separador API Keys.": "Is eochair API dhomhanda YouTube í seo: baineann sí le gach cuntas Google/YouTube agus leis an gcóras ar fad. Ní bhaineann sí le cuntas ar leith, ní cuid de dhoiciméid fianán/dintiúr í agus ní chuirtear in eagar í sa chluaisín Eochracha API.", "Chave global usada pelo Upload directo para todas as contas Google/YouTube. Guarde-a na configuração global, separada dos documentos de cookies.": "Eochair dhomhanda a úsáideann an tUaslódáil díreach do gach cuntas Google/YouTube. Sábháil sa chumraíocht dhomhanda í, scartha ó na doiciméid fianán.", "Guardar INNERTUBE_API_KEY global": "Sábháil INNERTUBE_API_KEY domhanda", "INNERTUBE_API_KEY global guardada para todas as contas Google/YouTube e para todo o sistema.": "INNERTUBE_API_KEY domhanda sábháilte do gach cuntas Google/YouTube agus don chóras ar fad.", "Gerar tópico, roteiro e palavras-chave com IA": "Gin topaic, script agus eochairfhocail le AI", "A gerar tópico, roteiro e palavras-chave com IA…": "Topaic, script agus eochairfhocail á nginiúint le AI…", "Tema, roteiro e palavras-chave gerados com IA.": "Topaic, script agus eochairfhocail ginte le AI.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "Líon an réimse Video Subject nó úsáid an cnaipe giniúna uathoibríoch faoi na heochairfhocail.", "Refazer thumbnail": "Athchruthaigh an mionsamhail", "Salvar rascunho": "Sábháil dréacht", "Rascunho guardado localmente": "Dréacht sábháilte go logánta", "Thumbnail refeita com sucesso.": "Athchruthaíodh an mionsamhail go rathúil.", "Ver prompt da thumbnail": "Féach ar leid na mionsamhla", "Sem imagem": "Gan íomhá", "Imagem ainda não gerada": "Níor gineadh íomhá fós", "Palavras-chave": "Eochairfhocail", "Título do rascunho": "Teideal an dréachta", "Gerar de Rascunho": "Gin ón dréacht", "Roteiros guardados": "Scripteanna sábháilte", "Seleccione um roteiro": "Roghnaigh script", "Configurações a completar": "Cumraíochtaí le comhlánú", "Configurações de vídeo": "Cumraíochtaí físeáin", "Configurações de áudio": "Cumraíochtaí fuaime", "Configurações de legendas": "Cumraíochtaí fotheideal", "Continuar criação": "Lean den chruthú", "Gerar apenas o vídeo": "Gin an físeán amháin", "Seleccione um canal para continuar.": "Roghnaigh cainéal chun leanúint ar aghaidh.", "Ainda não existem roteiros guardados.": "Níl aon scripteanna sábháilte ann fós.", "Histórico guardado": "Stair shábháilte", "Rascunho local": "Dréacht logánta", "Origem": "Foinse", "Brandings": "Brandálacha", "Pesquisa pública": "Cuardach poiblí", "Cadastro manual": "Clárú láimhe", "Contas cadastradas": "Cuntais chláraithe", "Biblioteca": "Leabharlann", "Importar do YouTube": "Iompórtáil ó YouTube", "Canais em lote gmail": "Cainéil bhaisc Gmail", "Criar vídeo": "Cruthaigh físeán", "Vídeos": "Físeáin", "Novo roteiro/letra": "Script/liric nua", "Clusters encontrados": "Braislí aimsithe", "Regras de associação": "Rialacha comhlachais", "Dados analisados": "Sonraí anailísithe", "Upload ficheiro": "Uaslódáil comhad", "URL de vídeo": "URL físeáin", "Vídeos gerados": "Físeáin ginte", "Pasta local": "Fillteán logánta", "Código Python": "Cód Python", "Upload convencional": "Uaslódáil traidisiúnta", "Upload directo": "Uaslódáil díreach", "API Keys": "Eochracha API", "Teste de Voz": "Tástáil gutha", "Serviços e modelos": "Seirbhísí agus samhlacha", "Fontes de Materiais": "Foinsí ábhair", "Client MCP": "Cliant MCP", "Servidor MCP": "Freastalaí MCP", "Skill": "Scil", "Guia de configuração do Supabase para automações com n8n.": "Treoir chumraíochta Supabase le haghaidh uathoibrithe le n8n.", "Adicionar fonte de materiais": "Cuir foinse ábhair leis", "Provedor de materiais": "Soláthraí ábhair", "Configurar Nova Fonte de Materiais": "Cumraigh foinse nua ábhair", "Fonte activa": "Foinse ghníomhach", "Usar esta fonte na pipeline": "Úsáid an fhoinse seo sa phíblíne", "Esta fonte não usa API key.": "Ní úsáideann an fhoinse seo eochair API.", "A testar chamada API…": "Glao API á thástáil…", "Último teste: API Key OK": "An tástáil is déanaí: eochair API ceart", "Último teste: falta configuração": "An tástáil is déanaí: cumraíocht ar iarraidh", "Último teste: requer autorização ou endpoint seguro": "An tástáil is déanaí: údarú breise nó críochphointe sábháilte de dhíth", "Último teste: chamada falhou": "An tástáil is déanaí: theip ar an nglao", "Testar credenciais TTS e música": "Tástáil dintiúr TTS agus ceoil", "Facebook Pages": "Leathanaigh Facebook", "Motion Control": "Rialú gluaisne", "UGC Products": "Táirgí UGC",
1364
+ "LLM — providers e modelos": "LLM — soláthraithe agus samhlacha", "Adicionar provider LLM": "Cuir soláthraí LLM leis", "Provider LLM": "Soláthraí LLM", "Configurar Novo Provedor LLM": "Cumraigh soláthraí nua LLM", "API key": "Eochair API", "Modelo": "Samhail", "Base URL": "URL bonn", "Modelo manual": "Samhail láimhe", "Escrever modelo manualmente": "Scríobh an tsamhail de láimh", "Provider activo": "Soláthraí gníomhach", "LLM Telegram": "LLM Telegram", "Testar chamada API": "Tástáil glao API", "Consultar modelos": "Faigh samhlacha", "Salvar": "Sábháil", "Remover cartão": "Bain cárta", "Último teste:": "An tástáil is déanaí:", "Teste API:": "Tástáil API:", "Missing key": "Eochair ar iarraidh", "Missing configuration": "Cumraíocht ar iarraidh", "Configured": "Cumraithe", "Local / sem API key": "Logánta / gan eochair API", "Este provider não exige API key.": "Níl eochair API ag teastáil ón soláthraí seo.", "Prioridade": "Príomh-LLM", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "Úsáid an cárta seo mar phríomhsholáthraí chun topaicí, scripteanna, teidil agus eochairfhocail a ghiniúint.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "Úsáid an cárta seo go heisiach chun fógraí Telegram a ródú. Ní féidir ach cárta amháin a roghnú.", "Account Id": "Aitheantas cuntais", "Gateway Id": "Aitheantas geata", "Api Version": "Leagan API", "Endpoint gerido pelo provider: ": "Críochphointe á bhainistiú ag an soláthraí: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "Críochphointe atá comhoiriúnach le OpenAI; taispeántar é nuair is féidir é a chumrú.", "ID do modelo usado pelo endpoint Chat Completions.": "Aitheantas na samhla a úsáideann críochphointe Chat Completions.", "Niche Finder — Kaggle": "Aimsitheoir nideoga — Kaggle", "Niche Finder — Apify": "Aimsitheoir nideoga — Apify", "Arquivos Base": "Comhaid bhunúsacha", "Pipeline Vídeos": "Píblíne físeáin", "Canais e Perfis de Vídeos": "Cainéil agus próifílí físeáin", "Canais YouTube": "Cainéil YouTube", "Prompt Masters": "Máistrí leideanna", "Backlog Vídeos": "Riaráiste físeáin", "Thumbnails": "Mionsamhlacha", "Música": "Ceol", "Upload Música": "Uaslódáil ceol", "Geração de Conteúdo IA": "Giniúint inneachair AI", "Growth": "Fás", "Analista Growth Youtube": "Anailísí fáis YouTube", "Analista Growth Tiktok": "Anailísí fáis TikTok", "Analista Growth Instagram": "Anailísí fáis Instagram", "Documentação": "Doiciméadú", "Tutorial Kaggle": "Teagasc Kaggle", "Tutorial Apify": "Teagasc Apify", "Pipeline Música": "Píblíne ceoil", "módulos disponíveis": "modúil ar fáil", "Esta é uma chave API global do YouTube: aplica-se a todas as contas Google/YouTube e a todo o sistema. Não é associada a uma conta específica, não faz parte dos documentos de cookies/credenciais e não é editada no separador API Keys.": "Is eochair API dhomhanda YouTube í seo: baineann sí le gach cuntas Google/YouTube agus leis an gcóras ar fad. Ní bhaineann sí le cuntas ar leith, ní cuid de dhoiciméid fianán/dintiúr í agus ní chuirtear in eagar í sa chluaisín Eochracha API.", "Chave global usada pelo Upload directo para todas as contas Google/YouTube. Guarde-a na configuração global, separada dos documentos de cookies.": "Eochair dhomhanda a úsáideann an tUaslódáil díreach do gach cuntas Google/YouTube. Sábháil sa chumraíocht dhomhanda í, scartha ó na doiciméid fianán.", "Guardar INNERTUBE_API_KEY global": "Sábháil INNERTUBE_API_KEY domhanda", "INNERTUBE_API_KEY global guardada para todas as contas Google/YouTube e para todo o sistema.": "INNERTUBE_API_KEY domhanda sábháilte do gach cuntas Google/YouTube agus don chóras ar fad.", "Gerar tópico, roteiro e palavras-chave com IA": "Gin topaic, script agus eochairfhocail le AI", "A gerar tópico, roteiro e palavras-chave com IA…": "Topaic, script agus eochairfhocail á nginiúint le AI…", "Tema, roteiro e palavras-chave gerados com IA.": "Topaic, script agus eochairfhocail ginte le AI.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "Líon an réimse Video Subject nó úsáid an cnaipe giniúna uathoibríoch faoi na heochairfhocail.", "Refazer thumbnail": "Athchruthaigh an mionsamhail", "Salvar rascunho": "Sábháil dréacht", "Rascunho guardado localmente": "Dréacht sábháilte go logánta", "Thumbnail refeita com sucesso.": "Athchruthaíodh an mionsamhail go rathúil.", "Ver prompt da thumbnail": "Féach ar leid na mionsamhla", "Sem imagem": "Gan íomhá", "Imagem ainda não gerada": "Níor gineadh íomhá fós", "Palavras-chave": "Eochairfhocail", "Título do rascunho": "Teideal an dréachta", "Gerar de Rascunho": "Gin ón dréacht", "Roteiros guardados": "Scripteanna sábháilte", "Seleccione um roteiro": "Roghnaigh script", "Configurações a completar": "Cumraíochtaí le comhlánú", "Configurações de vídeo": "Cumraíochtaí físeáin", "Configurações de áudio": "Cumraíochtaí fuaime", "Configurações de legendas": "Cumraíochtaí fotheideal", "Continuar criação": "Lean den chruthú", "Gerar apenas o vídeo": "Gin an físeán amháin", "Seleccione um canal para continuar.": "Roghnaigh cainéal chun leanúint ar aghaidh.", "Ainda não existem roteiros guardados.": "Níl aon scripteanna sábháilte ann fós.", "Histórico guardado": "Stair shábháilte", "Rascunho local": "Dréacht logánta", "Origem": "Foinse", "Brandings": "Brandálacha", "Pesquisa pública": "Cuardach poiblí", "Cadastro manual": "Clárú láimhe", "Contas cadastradas": "Cuntais chláraithe", "Biblioteca": "Leabharlann", "Importar do YouTube": "Iompórtáil ó YouTube", "Canais em lote gmail": "Cainéil bhaisc Gmail", "Criar vídeo": "Cruthaigh físeán", "Vídeos": "Físeáin", "Novo roteiro/letra": "Script/liric nua", "Clusters encontrados": "Braislí aimsithe", "Regras de associação": "Rialacha comhlachais", "Dados analisados": "Sonraí anailísithe", "Upload ficheiro": "Uaslódáil comhad", "URL de vídeo": "URL físeáin", "Vídeos gerados": "Físeáin ginte", "Pasta local": "Fillteán logánta", "Código Python": "Cód Python", "Upload convencional": "Uaslódáil traidisiúnta", "Upload directo": "Uaslódáil díreach", "API Keys": "Eochracha API", "Teste de Voz": "Tástáil gutha", "Serviços e modelos": "Seirbhísí agus samhlacha", "Fontes de Materiais": "Foinsí ábhair", "Client MCP": "Cliant MCP", "Servidor MCP": "Freastalaí MCP", "Skill": "Scil", "Guia de configuração do Supabase para automações com n8n.": "Treoir chumraíochta Supabase le haghaidh uathoibrithe le n8n.", "Adicionar fonte de materiais": "Cuir foinse ábhair leis", "Provedor de materiais": "Soláthraí ábhair", "Configurar Nova Fonte de Materiais": "Cumraigh foinse nua ábhair", "Fonte activa": "Foinse ghníomhach", "Usar esta fonte na pipeline": "Úsáid an fhoinse seo sa phíblíne", "Esta fonte não usa API key.": "Ní úsáideann an fhoinse seo eochair API.", "A testar chamada API…": "Glao API á thástáil…", "Último teste: API Key OK": "An tástáil is déanaí: eochair API ceart", "Último teste: falta configuração": "An tástáil is déanaí: cumraíocht ar iarraidh", "Último teste: requer autorização ou endpoint seguro": "An tástáil is déanaí: údarú breise nó críochphointe sábháilte de dhíth", "Último teste: chamada falhou": "An tástáil is déanaí: theip ar an nglao", "Testar credenciais TTS e música": "Tástáil dintiúr TTS agus ceoil", "Facebook Pages": "Leathanaigh Facebook", "Motion Control": "Rialú gluaisne", "UGC Products": "Táirgí UGC",
1365
1365
  },
1366
1366
  "ar": {
1367
1367
  "Início": "الصفحة الرئيسية", "Niche Finder": "باحث المجالات", "Pipeline": "خط الإنتاج", "Pipeline TikTok": "خط إنتاج TikTok", "Automação": "الأتمتة", "Edição": "التحرير", "AI Influencers": "مؤثرو الذكاء الاصطناعي", "Configurações": "الإعدادات", "Criação de Vídeos": "إنشاء الفيديو", "Criação de Músicas": "إنشاء الموسيقى", "Roteiros": "السيناريوهات", "Upload": "رفع", "Prompts Master": "محرّكات المطالبات", "Contas TikTok": "حسابات TikTok", "Automação Youtube": "أتمتة YouTube", "Niche Finder Kaggle": "باحث المجالات — Kaggle", "Niche Finder Apify": "باحث المجالات — Apify", "Limpador de Metadados": "منظف البيانات الوصفية", "Cortes": "القصاصات", "Editor Python": "محرر Python", "Download Mídia": "تنزيل الوسائط", "Personagens": "الشخصيات", "Redes Sociais": "الشبكات الاجتماعية", "Tutorial Meta": "دليل Meta", "Tutorial Supabase": "دليل Supabase", "Canais Youtube": "قنوات YouTube", "Blueprints Youtube": "مخططات YouTube", "Contas Google": "حسابات Google", "Configuração API": "إعداد API", "Notificações": "الإشعارات", "Interface local para operação e automação de conteúdo faceless": "واجهة محلية لتشغيل وأتمتة المحتوى دون ظهور", "Canais": "القنوات", "activos": "نشطة", "Tarefas": "المهام", "total registado": "الإجمالي المسجل", "A fazer": "قيد التنفيذ", "na pipeline": "في خط الإنتاج", "Em execução": "قيد التشغيل", "a decorrer": "جارٍ", "Concluídos": "مكتملة", "artefactos prontos": "النتائج الجاهزة", "Falhas": "الأخطاء", "requerem atenção": "تتطلب الانتباه", "Filas locais e dependências da cascata": "قوائم الانتظار المحلية وتبعيات خط الإنتاج", "Niche": "مجال", "Blueprints": "المخططات", "Brand": "العلامة التجارية", "Script": "السيناريو", "Title": "العنوان", "Thumbnail": "الصورة المصغرة", "Video": "الفيديو", "Edit": "تحرير", "fila": "قائمة الانتظار", "na biblioteca": "في المكتبة", "tarefa(s) na fila": "مهمة/مهام في قائمة الانتظار", "Language": "اللغة", "Theme": "السمة", "Dark": "داكن", "Light": "فاتح",
1368
- "LLM — providers e modelos": "LLM — المزوّدون والنماذج", "Adicionar provider LLM": "إضافة مزوّد LLM", "Provider LLM": "مزوّد LLM", "Configurar Novo Provedor LLM": "إعداد مزوّد LLM جديد", "API key": "مفتاح API", "Modelo": "النموذج", "Base URL": "عنوان URL الأساسي", "Modelo manual": "نموذج يدوي", "Escrever modelo manualmente": "اكتب النموذج يدوياً", "Provider activo": "المزوّد النشط", "LLM Telegram": "LLM Telegram", "Testar chamada API": "اختبار استدعاء API", "Consultar modelos": "جلب النماذج", "Salvar": "حفظ", "Remover cartão": "إزالة البطاقة", "Último teste:": "آخر اختبار:", "Teste API:": "اختبار API:", "Missing key": "المفتاح مفقود", "Missing configuration": "الإعداد مفقود", "Configured": "تم الإعداد", "Local / sem API key": "محلي / بلا مفتاح API", "Este provider não exige API key.": "هذا المزوّد لا يتطلب مفتاح API.", "LLM principal": "LLM الرئيسي", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "استخدم هذه البطاقة كمزوّد رئيسي لإنشاء الموضوعات والسيناريوهات والعناوين والكلمات المفتاحية.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "استخدم هذه البطاقة حصرياً لتوجيه إشعارات Telegram. يمكن تحديد بطاقة واحدة فقط.", "Account Id": "معرّف الحساب", "Gateway Id": "معرّف البوابة", "Api Version": "إصدار API", "Endpoint gerido pelo provider: ": "نقطة النهاية التي يديرها المزوّد: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "نقطة نهاية متوافقة مع OpenAI؛ تظهر فقط عند إمكانية إعدادها.", "ID do modelo usado pelo endpoint Chat Completions.": "معرّف النموذج المستخدم في نقطة نهاية Chat Completions.", "Arquivos Base": "الملفات الأساسية", "Pipeline Vídeos": "خط إنتاج الفيديو", "Canais e Perfis de Vídeos": "قنوات وملفات الفيديو", "Canais YouTube": "قنوات YouTube", "Facebook Pages": "صفحات Facebook", "Prompt Masters": "محرّكات المطالبات", "Backlog Vídeos": "تراكم الفيديوهات", "Thumbnails": "الصور المصغرة", "Música": "الموسيقى", "Upload Música": "رفع الموسيقى", "Geração de Conteúdo IA": "إنشاء محتوى بالذكاء الاصطناعي", "Motion Control": "التحكم بالحركة", "UGC Products": "منتجات UGC", "Growth": "النمو", "Analista Growth Youtube": "محلل نمو YouTube", "Analista Growth Tiktok": "محلل نمو TikTok", "Analista Growth Instagram": "محلل نمو Instagram", "Documentação": "التوثيق", "Tutorial Kaggle": "دليل Kaggle", "Tutorial Apify": "دليل Apify", "Pipeline Música": "خط إنتاج الموسيقى", "módulos disponíveis": "الوحدات المتاحة", "Guardar INNERTUBE_API_KEY global": "حفظ INNERTUBE_API_KEY العام", "Gerar tópico, roteiro e palavras-chave com IA": "إنشاء الموضوع والسيناريو والكلمات المفتاحية بالذكاء الاصطناعي", "A gerar tópico, roteiro e palavras-chave com IA…": "جارٍ إنشاء الموضوع والسيناريو والكلمات المفتاحية بالذكاء الاصطناعي…", "Tema, roteiro e palavras-chave gerados com IA.": "تم إنشاء الموضوع والسيناريو والكلمات المفتاحية بالذكاء الاصطناعي.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "املأ حقل Video Subject أو استخدم زر الإنشاء التلقائي أسفل الكلمات المفتاحية.", "Refazer thumbnail": "إعادة إنشاء الصورة المصغرة", "Salvar rascunho": "حفظ المسودة", "Rascunho guardado localmente": "تم حفظ المسودة محلياً", "Thumbnail refeita com sucesso.": "تمت إعادة إنشاء الصورة المصغرة بنجاح.", "Ver prompt da thumbnail": "عرض مطالبة الصورة المصغرة", "Sem imagem": "لا توجد صورة", "Imagem ainda não gerada": "لم يتم إنشاء الصورة بعد", "Palavras-chave": "الكلمات المفتاحية", "Título do rascunho": "عنوان المسودة", "Gerar de Rascunho": "الإنشاء من مسودة", "Roteiros guardados": "السيناريوهات المحفوظة", "Seleccione um roteiro": "اختر سيناريو", "Configurações a completar": "إعدادات يجب إكمالها", "Configurações de vídeo": "إعدادات الفيديو", "Configurações de áudio": "إعدادات الصوت", "Configurações de legendas": "إعدادات الترجمة", "Continuar criação": "متابعة الإنشاء", "Gerar apenas o vídeo": "إنشاء الفيديو فقط", "Seleccione um canal para continuar.": "اختر قناة للمتابعة.", "Ainda não existem roteiros guardados.": "لا توجد سيناريوهات محفوظة بعد.", "Histórico guardado": "السجل المحفوظ", "Rascunho local": "مسودة محلية", "Origem": "المصدر", "Brandings": "الهوية البصرية", "Pesquisa pública": "بحث عام", "Cadastro manual": "تسجيل يدوي", "Contas cadastradas": "الحسابات المسجلة", "Biblioteca": "المكتبة", "Importar do YouTube": "استيراد من YouTube", "Canais em lote gmail": "قنوات Gmail المجمعة", "Criar vídeo": "إنشاء فيديو", "Vídeos": "الفيديوهات", "Novo roteiro/letra": "سيناريو/كلمات جديدة", "Clusters encontrados": "العناقيد المكتشفة", "Regras de associação": "قواعد الارتباط", "Dados analisados": "البيانات المحللة", "Upload ficheiro": "رفع ملف", "URL de vídeo": "رابط الفيديو", "Vídeos gerados": "الفيديوهات المنشأة", "Pasta local": "المجلد المحلي", "Código Python": "كود Python", "Upload convencional": "رفع تقليدي", "Upload directo": "رفع مباشر", "Postiz": "Postiz", "Upload-Post": "Upload-Post", "API Keys": "مفاتيح API", "Teste de Voz": "اختبار الصوت", "Serviços e modelos": "الخدمات والنماذج", "Fontes de Materiais": "مصادر الوسائط", "Client MCP": "عميل MCP", "Servidor MCP": "خادم MCP", "Skill": "المهارة", "Guia de configuração do Supabase para automações com n8n.": "دليل إعداد Supabase للأتمتة باستخدام n8n.", "Adicionar fonte de materiais": "إضافة مصدر وسائط", "Provedor de materiais": "مزوّد الوسائط", "Configurar Nova Fonte de Materiais": "إعداد مصدر وسائط جديد", "Fonte activa": "المصدر النشط", "Usar esta fonte na pipeline": "استخدم هذا المصدر في خط الإنتاج", "Esta fonte não usa API key.": "لا يستخدم هذا المصدر مفتاح API.", "A testar chamada API…": "جارٍ اختبار استدعاء API…", "Último teste: API Key OK": "آخر اختبار: مفتاح API صالح", "Último teste: falta configuração": "آخر اختبار: الإعداد مفقود", "Último teste: requer autorização ou endpoint seguro": "آخر اختبار: يلزم تفويض إضافي أو نقطة نهاية آمنة", "Último teste: chamada falhou": "آخر اختبار: فشل الاستدعاء", "Testar credenciais TTS e música": "اختبار بيانات اعتماد TTS والموسيقى",
1368
+ "LLM — providers e modelos": "LLM — المزوّدون والنماذج", "Adicionar provider LLM": "إضافة مزوّد LLM", "Provider LLM": "مزوّد LLM", "Configurar Novo Provedor LLM": "إعداد مزوّد LLM جديد", "API key": "مفتاح API", "Modelo": "النموذج", "Base URL": "عنوان URL الأساسي", "Modelo manual": "نموذج يدوي", "Escrever modelo manualmente": "اكتب النموذج يدوياً", "Provider activo": "المزوّد النشط", "LLM Telegram": "LLM Telegram", "Testar chamada API": "اختبار استدعاء API", "Consultar modelos": "جلب النماذج", "Salvar": "حفظ", "Remover cartão": "إزالة البطاقة", "Último teste:": "آخر اختبار:", "Teste API:": "اختبار API:", "Missing key": "المفتاح مفقود", "Missing configuration": "الإعداد مفقود", "Configured": "تم الإعداد", "Local / sem API key": "محلي / بلا مفتاح API", "Este provider não exige API key.": "هذا المزوّد لا يتطلب مفتاح API.", "Prioridade": "LLM الرئيسي", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "استخدم هذه البطاقة كمزوّد رئيسي لإنشاء الموضوعات والسيناريوهات والعناوين والكلمات المفتاحية.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "استخدم هذه البطاقة حصرياً لتوجيه إشعارات Telegram. يمكن تحديد بطاقة واحدة فقط.", "Account Id": "معرّف الحساب", "Gateway Id": "معرّف البوابة", "Api Version": "إصدار API", "Endpoint gerido pelo provider: ": "نقطة النهاية التي يديرها المزوّد: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "نقطة نهاية متوافقة مع OpenAI؛ تظهر فقط عند إمكانية إعدادها.", "ID do modelo usado pelo endpoint Chat Completions.": "معرّف النموذج المستخدم في نقطة نهاية Chat Completions.", "Arquivos Base": "الملفات الأساسية", "Pipeline Vídeos": "خط إنتاج الفيديو", "Canais e Perfis de Vídeos": "قنوات وملفات الفيديو", "Canais YouTube": "قنوات YouTube", "Facebook Pages": "صفحات Facebook", "Prompt Masters": "محرّكات المطالبات", "Backlog Vídeos": "تراكم الفيديوهات", "Thumbnails": "الصور المصغرة", "Música": "الموسيقى", "Upload Música": "رفع الموسيقى", "Geração de Conteúdo IA": "إنشاء محتوى بالذكاء الاصطناعي", "Motion Control": "التحكم بالحركة", "UGC Products": "منتجات UGC", "Growth": "النمو", "Analista Growth Youtube": "محلل نمو YouTube", "Analista Growth Tiktok": "محلل نمو TikTok", "Analista Growth Instagram": "محلل نمو Instagram", "Documentação": "التوثيق", "Tutorial Kaggle": "دليل Kaggle", "Tutorial Apify": "دليل Apify", "Pipeline Música": "خط إنتاج الموسيقى", "módulos disponíveis": "الوحدات المتاحة", "Guardar INNERTUBE_API_KEY global": "حفظ INNERTUBE_API_KEY العام", "Gerar tópico, roteiro e palavras-chave com IA": "إنشاء الموضوع والسيناريو والكلمات المفتاحية بالذكاء الاصطناعي", "A gerar tópico, roteiro e palavras-chave com IA…": "جارٍ إنشاء الموضوع والسيناريو والكلمات المفتاحية بالذكاء الاصطناعي…", "Tema, roteiro e palavras-chave gerados com IA.": "تم إنشاء الموضوع والسيناريو والكلمات المفتاحية بالذكاء الاصطناعي.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "املأ حقل Video Subject أو استخدم زر الإنشاء التلقائي أسفل الكلمات المفتاحية.", "Refazer thumbnail": "إعادة إنشاء الصورة المصغرة", "Salvar rascunho": "حفظ المسودة", "Rascunho guardado localmente": "تم حفظ المسودة محلياً", "Thumbnail refeita com sucesso.": "تمت إعادة إنشاء الصورة المصغرة بنجاح.", "Ver prompt da thumbnail": "عرض مطالبة الصورة المصغرة", "Sem imagem": "لا توجد صورة", "Imagem ainda não gerada": "لم يتم إنشاء الصورة بعد", "Palavras-chave": "الكلمات المفتاحية", "Título do rascunho": "عنوان المسودة", "Gerar de Rascunho": "الإنشاء من مسودة", "Roteiros guardados": "السيناريوهات المحفوظة", "Seleccione um roteiro": "اختر سيناريو", "Configurações a completar": "إعدادات يجب إكمالها", "Configurações de vídeo": "إعدادات الفيديو", "Configurações de áudio": "إعدادات الصوت", "Configurações de legendas": "إعدادات الترجمة", "Continuar criação": "متابعة الإنشاء", "Gerar apenas o vídeo": "إنشاء الفيديو فقط", "Seleccione um canal para continuar.": "اختر قناة للمتابعة.", "Ainda não existem roteiros guardados.": "لا توجد سيناريوهات محفوظة بعد.", "Histórico guardado": "السجل المحفوظ", "Rascunho local": "مسودة محلية", "Origem": "المصدر", "Brandings": "الهوية البصرية", "Pesquisa pública": "بحث عام", "Cadastro manual": "تسجيل يدوي", "Contas cadastradas": "الحسابات المسجلة", "Biblioteca": "المكتبة", "Importar do YouTube": "استيراد من YouTube", "Canais em lote gmail": "قنوات Gmail المجمعة", "Criar vídeo": "إنشاء فيديو", "Vídeos": "الفيديوهات", "Novo roteiro/letra": "سيناريو/كلمات جديدة", "Clusters encontrados": "العناقيد المكتشفة", "Regras de associação": "قواعد الارتباط", "Dados analisados": "البيانات المحللة", "Upload ficheiro": "رفع ملف", "URL de vídeo": "رابط الفيديو", "Vídeos gerados": "الفيديوهات المنشأة", "Pasta local": "المجلد المحلي", "Código Python": "كود Python", "Upload convencional": "رفع تقليدي", "Upload directo": "رفع مباشر", "Postiz": "Postiz", "Upload-Post": "Upload-Post", "API Keys": "مفاتيح API", "Teste de Voz": "اختبار الصوت", "Serviços e modelos": "الخدمات والنماذج", "Fontes de Materiais": "مصادر الوسائط", "Client MCP": "عميل MCP", "Servidor MCP": "خادم MCP", "Skill": "المهارة", "Guia de configuração do Supabase para automações com n8n.": "دليل إعداد Supabase للأتمتة باستخدام n8n.", "Adicionar fonte de materiais": "إضافة مصدر وسائط", "Provedor de materiais": "مزوّد الوسائط", "Configurar Nova Fonte de Materiais": "إعداد مصدر وسائط جديد", "Fonte activa": "المصدر النشط", "Usar esta fonte na pipeline": "استخدم هذا المصدر في خط الإنتاج", "Esta fonte não usa API key.": "لا يستخدم هذا المصدر مفتاح API.", "A testar chamada API…": "جارٍ اختبار استدعاء API…", "Último teste: API Key OK": "آخر اختبار: مفتاح API صالح", "Último teste: falta configuração": "آخر اختبار: الإعداد مفقود", "Último teste: requer autorização ou endpoint seguro": "آخر اختبار: يلزم تفويض إضافي أو نقطة نهاية آمنة", "Último teste: chamada falhou": "آخر اختبار: فشل الاستدعاء", "Testar credenciais TTS e música": "اختبار بيانات اعتماد TTS والموسيقى",
1369
1369
  },
1370
1370
  "he": {
1371
1371
  "Início": "דף הבית", "Niche Finder": "מאתר נישות", "Pipeline": "צינור עבודה", "Pipeline TikTok": "צינור TikTok", "Automação": "אוטומציה", "Edição": "עריכה", "AI Influencers": "משפיעני AI", "Configurações": "הגדרות", "Criação de Vídeos": "יצירת וידאו", "Criação de Músicas": "יצירת מוזיקה", "Roteiros": "תסריטים", "Upload": "העלאה", "Prompts Master": "מאסטרים של פרומפטים", "Contas TikTok": "חשבונות TikTok", "Automação Youtube": "אוטומציית YouTube", "Niche Finder Kaggle": "מאתר נישות Kaggle", "Niche Finder Apify": "מאתר נישות Apify", "Limpador de Metadados": "מנקה מטא־נתונים", "Cortes": "חיתוכים", "Editor Python": "עורך Python", "Download Mídia": "הורדת מדיה", "Personagens": "דמויות", "Redes Sociais": "רשתות חברתיות", "Tutorial Meta": "מדריך Meta", "Tutorial Supabase": "מדריך Supabase", "Canais Youtube": "ערוצי YouTube", "Blueprints Youtube": "שרטוטי YouTube", "Contas Google": "חשבונות Google", "Configuração API": "הגדרת API", "Notificações": "התראות", "Interface local para operação e automação de conteúdo faceless": "ממשק מקומי להפעלה ולאוטומציה של תוכן ללא הופעה", "Canais": "ערוצים", "activos": "פעילים", "Tarefas": "משימות", "total registado": "סה״כ רשומים", "A fazer": "לביצוע", "na pipeline": "בצינור העבודה", "Em execução": "בהרצה", "a decorrer": "בתהליך", "Concluídos": "הושלמו", "artefactos prontos": "תוצרים מוכנים", "Falhas": "כשלים", "requerem atenção": "דורשים תשומת לב", "Filas locais e dependências da cascata": "תורים מקומיים ותלויות בצינור", "Niche": "נישה", "Blueprints": "שרטוטים", "Brand": "מותג", "Script": "תסריט", "Title": "כותרת", "Thumbnail": "תמונה ממוזערת", "Video": "וידאו", "Edit": "עריכה", "fila": "תור", "na biblioteca": "בספרייה", "tarefa(s) na fila": "משימה/משימות בתור", "Language": "שפה", "Theme": "ערכת נושא", "Dark": "כהה", "Light": "בהיר",
1372
- "LLM — providers e modelos": "LLM — ספקים ומודלים", "Adicionar provider LLM": "הוסף ספק LLM", "Provider LLM": "ספק LLM", "Configurar Novo Provedor LLM": "הגדרת ספק LLM חדש", "API key": "מפתח API", "Modelo": "מודל", "Base URL": "כתובת URL בסיסית", "Modelo manual": "מודל ידני", "Escrever modelo manualmente": "כתיבת מודל ידנית", "Provider activo": "ספק פעיל", "LLM Telegram": "LLM Telegram", "Testar chamada API": "בדיקת קריאת API", "Consultar modelos": "קבלת מודלים", "Salvar": "שמירה", "Remover cartão": "הסרת כרטיס", "Último teste:": "בדיקה אחרונה:", "Teste API:": "בדיקת API:", "Missing key": "מפתח חסר", "Missing configuration": "הגדרה חסרה", "Configured": "מוגדר", "Local / sem API key": "מקומי / ללא מפתח API", "Este provider não exige API key.": "ספק זה אינו דורש מפתח API.", "LLM principal": "LLM ראשי", "Usar este cartão como provider principal para geração de temas, roteiros, títulos e keywords.": "השתמש בכרטיס זה כספק הראשי ליצירת נושאים, תסריטים, כותרות ומילות מפתח.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "השתמש בכרטיס זה אך ורק לניתוב התראות Telegram. ניתן לבחור כרטיס אחד בלבד.", "Account Id": "מזהה חשבון", "Gateway Id": "מזהה שער", "Api Version": "גרסת API", "Endpoint gerido pelo provider: ": "נקודת קצה בניהול הספק: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "נקודת קצה תואמת OpenAI; מוצגת רק כאשר ניתן להגדירה.", "ID do modelo usado pelo endpoint Chat Completions.": "מזהה המודל שבו משתמשת נקודת הקצה Chat Completions.", "Arquivos Base": "קבצי בסיס", "Pipeline Vídeos": "צינור וידאו", "Canais e Perfis de Vídeos": "ערוצי ופרופילי וידאו", "Canais YouTube": "ערוצי YouTube", "Facebook Pages": "דפי Facebook", "Prompt Masters": "מאסטרים של פרומפטים", "Backlog Vídeos": "צבר וידאו", "Thumbnails": "תמונות ממוזערות", "Música": "מוזיקה", "Upload Música": "העלאת מוזיקה", "Geração de Conteúdo IA": "יצירת תוכן AI", "Motion Control": "בקרת תנועה", "UGC Products": "מוצרי UGC", "Growth": "צמיחה", "Analista Growth Youtube": "אנליסט צמיחת YouTube", "Analista Growth Tiktok": "אנליסט צמיחת TikTok", "Analista Growth Instagram": "אנליסט צמיחת Instagram", "Documentação": "תיעוד", "Tutorial Kaggle": "מדריך Kaggle", "Tutorial Apify": "מדריך Apify", "Pipeline Música": "צינור מוזיקה", "módulos disponíveis": "מודולים זמינים", "Guardar INNERTUBE_API_KEY global": "שמירת INNERTUBE_API_KEY גלובלי", "Gerar tópico, roteiro e palavras-chave com IA": "יצירת נושא, תסריט ומילות מפתח בעזרת AI", "A gerar tópico, roteiro e palavras-chave com IA…": "יוצר נושא, תסריט ומילות מפתח בעזרת AI…", "Tema, roteiro e palavras-chave gerados com IA.": "הנושא, התסריט ומילות המפתח נוצרו בעזרת AI.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "מלא את השדה Video Subject או השתמש בלחצן היצירה האוטומטית שמתחת למילות המפתח.", "Refazer thumbnail": "יצירת תמונה ממוזערת מחדש", "Salvar rascunho": "שמירת טיוטה", "Rascunho guardado localmente": "הטיוטה נשמרה מקומית", "Thumbnail refeita com sucesso.": "התמונה הממוזערת נוצרה מחדש בהצלחה.", "Ver prompt da thumbnail": "צפייה בפרומפט התמונה הממוזערת", "Sem imagem": "אין תמונה", "Imagem ainda não gerada": "התמונה עדיין לא נוצרה", "Palavras-chave": "מילות מפתח", "Título do rascunho": "כותרת הטיוטה", "Gerar de Rascunho": "יצירה מטיוטה", "Roteiros guardados": "תסריטים שמורים", "Seleccione um roteiro": "בחירת תסריט", "Configurações a completar": "הגדרות להשלמה", "Configurações de vídeo": "הגדרות וידאו", "Configurações de áudio": "הגדרות שמע", "Configurações de legendas": "הגדרות כתוביות", "Continuar criação": "המשך יצירה", "Gerar apenas o vídeo": "יצירת הווידאו בלבד", "Seleccione um canal para continuar.": "בחר ערוץ כדי להמשיך.", "Ainda não existem roteiros guardados.": "עדיין אין תסריטים שמורים.", "Histórico guardado": "היסטוריה שמורה", "Rascunho local": "טיוטה מקומית", "Origem": "מקור", "Brandings": "מיתוגים", "Pesquisa pública": "חיפוש ציבורי", "Cadastro manual": "רישום ידני", "Contas cadastradas": "חשבונות רשומים", "Biblioteca": "ספרייה", "Importar do YouTube": "ייבוא מ-YouTube", "Canais em lote gmail": "ערוצי Gmail באצווה", "Criar vídeo": "יצירת וידאו", "Vídeos": "סרטונים", "Novo roteiro/letra": "תסריט/מילים חדשים", "Clusters encontrados": "אשכולות שנמצאו", "Regras de associação": "כללי שיוך", "Dados analisados": "נתונים שנותחו", "Upload ficheiro": "העלאת קובץ", "URL de vídeo": "כתובת URL של וידאו", "Vídeos gerados": "סרטונים שנוצרו", "Pasta local": "תיקייה מקומית", "Código Python": "קוד Python", "Upload convencional": "העלאה רגילה", "Upload directo": "העלאה ישירה", "API Keys": "מפתחות API", "Teste de Voz": "בדיקת קול", "Serviços e modelos": "שירותים ומודלים", "Fontes de Materiais": "מקורות מדיה", "Client MCP": "לקוח MCP", "Servidor MCP": "שרת MCP", "Skill": "מיומנות", "Guia de configuração do Supabase para automações com n8n.": "מדריך להגדרת Supabase לאוטומציות עם n8n.", "Adicionar fonte de materiais": "הוספת מקור מדיה", "Provedor de materiais": "ספק מדיה", "Configurar Nova Fonte de Materiais": "הגדרת מקור מדיה חדש", "Fonte activa": "מקור פעיל", "Usar esta fonte na pipeline": "שימוש במקור זה בצינור", "Esta fonte não usa API key.": "מקור זה אינו משתמש במפתח API.", "A testar chamada API…": "בודק קריאת API…", "Último teste: API Key OK": "בדיקה אחרונה: מפתח API תקין", "Último teste: falta configuração": "בדיקה אחרונה: חסרה הגדרה", "Último teste: requer autorização ou endpoint seguro": "בדיקה אחרונה: נדרש אישור נוסף או נקודת קצה בטוחה", "Último teste: chamada falhou": "בדיקה אחרונה: הקריאה נכשלה", "Testar credenciais TTS e música": "בדיקת פרטי הגישה של TTS ומוזיקה",
1372
+ "LLM — providers e modelos": "LLM — ספקים ומודלים", "Adicionar provider LLM": "הוסף ספק LLM", "Provider LLM": "ספק LLM", "Configurar Novo Provedor LLM": "הגדרת ספק LLM חדש", "API key": "מפתח API", "Modelo": "מודל", "Base URL": "כתובת URL בסיסית", "Modelo manual": "מודל ידני", "Escrever modelo manualmente": "כתיבת מודל ידנית", "Provider activo": "ספק פעיל", "LLM Telegram": "LLM Telegram", "Testar chamada API": "בדיקת קריאת API", "Consultar modelos": "קבלת מודלים", "Salvar": "שמירה", "Remover cartão": "הסרת כרטיס", "Último teste:": "בדיקה אחרונה:", "Teste API:": "בדיקת API:", "Missing key": "מפתח חסר", "Missing configuration": "הגדרה חסרה", "Configured": "מוגדר", "Local / sem API key": "מקומי / ללא מפתח API", "Este provider não exige API key.": "ספק זה אינו דורש מפתח API.", "Prioridade": "LLM ראשי", "Ordem de tentativa do pool LLM: 1 é o primeiro; em falha elegível, seguem-se as prioridades seguintes.": "השתמש בכרטיס זה כספק הראשי ליצירת נושאים, תסריטים, כותרות ומילות מפתח.", "Usar este cartão exclusivamente para o roteamento de notificações Telegram. Apenas um cartão pode ficar seleccionado.": "השתמש בכרטיס זה אך ורק לניתוב התראות Telegram. ניתן לבחור כרטיס אחד בלבד.", "Account Id": "מזהה חשבון", "Gateway Id": "מזהה שער", "Api Version": "גרסת API", "Endpoint gerido pelo provider: ": "נקודת קצה בניהול הספק: ", "Endpoint OpenAI-compatible deste provider; só aparece quando é configurável.": "נקודת קצה תואמת OpenAI; מוצגת רק כאשר ניתן להגדירה.", "ID do modelo usado pelo endpoint Chat Completions.": "מזהה המודל שבו משתמשת נקודת הקצה Chat Completions.", "Arquivos Base": "קבצי בסיס", "Pipeline Vídeos": "צינור וידאו", "Canais e Perfis de Vídeos": "ערוצי ופרופילי וידאו", "Canais YouTube": "ערוצי YouTube", "Facebook Pages": "דפי Facebook", "Prompt Masters": "מאסטרים של פרומפטים", "Backlog Vídeos": "צבר וידאו", "Thumbnails": "תמונות ממוזערות", "Música": "מוזיקה", "Upload Música": "העלאת מוזיקה", "Geração de Conteúdo IA": "יצירת תוכן AI", "Motion Control": "בקרת תנועה", "UGC Products": "מוצרי UGC", "Growth": "צמיחה", "Analista Growth Youtube": "אנליסט צמיחת YouTube", "Analista Growth Tiktok": "אנליסט צמיחת TikTok", "Analista Growth Instagram": "אנליסט צמיחת Instagram", "Documentação": "תיעוד", "Tutorial Kaggle": "מדריך Kaggle", "Tutorial Apify": "מדריך Apify", "Pipeline Música": "צינור מוזיקה", "módulos disponíveis": "מודולים זמינים", "Guardar INNERTUBE_API_KEY global": "שמירת INNERTUBE_API_KEY גלובלי", "Gerar tópico, roteiro e palavras-chave com IA": "יצירת נושא, תסריט ומילות מפתח בעזרת AI", "A gerar tópico, roteiro e palavras-chave com IA…": "יוצר נושא, תסריט ומילות מפתח בעזרת AI…", "Tema, roteiro e palavras-chave gerados com IA.": "הנושא, התסריט ומילות המפתח נוצרו בעזרת AI.", "Preencha o campo Video Subject ou use o botão de geração automática abaixo das keywords.": "מלא את השדה Video Subject או השתמש בלחצן היצירה האוטומטית שמתחת למילות המפתח.", "Refazer thumbnail": "יצירת תמונה ממוזערת מחדש", "Salvar rascunho": "שמירת טיוטה", "Rascunho guardado localmente": "הטיוטה נשמרה מקומית", "Thumbnail refeita com sucesso.": "התמונה הממוזערת נוצרה מחדש בהצלחה.", "Ver prompt da thumbnail": "צפייה בפרומפט התמונה הממוזערת", "Sem imagem": "אין תמונה", "Imagem ainda não gerada": "התמונה עדיין לא נוצרה", "Palavras-chave": "מילות מפתח", "Título do rascunho": "כותרת הטיוטה", "Gerar de Rascunho": "יצירה מטיוטה", "Roteiros guardados": "תסריטים שמורים", "Seleccione um roteiro": "בחירת תסריט", "Configurações a completar": "הגדרות להשלמה", "Configurações de vídeo": "הגדרות וידאו", "Configurações de áudio": "הגדרות שמע", "Configurações de legendas": "הגדרות כתוביות", "Continuar criação": "המשך יצירה", "Gerar apenas o vídeo": "יצירת הווידאו בלבד", "Seleccione um canal para continuar.": "בחר ערוץ כדי להמשיך.", "Ainda não existem roteiros guardados.": "עדיין אין תסריטים שמורים.", "Histórico guardado": "היסטוריה שמורה", "Rascunho local": "טיוטה מקומית", "Origem": "מקור", "Brandings": "מיתוגים", "Pesquisa pública": "חיפוש ציבורי", "Cadastro manual": "רישום ידני", "Contas cadastradas": "חשבונות רשומים", "Biblioteca": "ספרייה", "Importar do YouTube": "ייבוא מ-YouTube", "Canais em lote gmail": "ערוצי Gmail באצווה", "Criar vídeo": "יצירת וידאו", "Vídeos": "סרטונים", "Novo roteiro/letra": "תסריט/מילים חדשים", "Clusters encontrados": "אשכולות שנמצאו", "Regras de associação": "כללי שיוך", "Dados analisados": "נתונים שנותחו", "Upload ficheiro": "העלאת קובץ", "URL de vídeo": "כתובת URL של וידאו", "Vídeos gerados": "סרטונים שנוצרו", "Pasta local": "תיקייה מקומית", "Código Python": "קוד Python", "Upload convencional": "העלאה רגילה", "Upload directo": "העלאה ישירה", "API Keys": "מפתחות API", "Teste de Voz": "בדיקת קול", "Serviços e modelos": "שירותים ומודלים", "Fontes de Materiais": "מקורות מדיה", "Client MCP": "לקוח MCP", "Servidor MCP": "שרת MCP", "Skill": "מיומנות", "Guia de configuração do Supabase para automações com n8n.": "מדריך להגדרת Supabase לאוטומציות עם n8n.", "Adicionar fonte de materiais": "הוספת מקור מדיה", "Provedor de materiais": "ספק מדיה", "Configurar Nova Fonte de Materiais": "הגדרת מקור מדיה חדש", "Fonte activa": "מקור פעיל", "Usar esta fonte na pipeline": "שימוש במקור זה בצינור", "Esta fonte não usa API key.": "מקור זה אינו משתמש במפתח API.", "A testar chamada API…": "בודק קריאת API…", "Último teste: API Key OK": "בדיקה אחרונה: מפתח API תקין", "Último teste: falta configuração": "בדיקה אחרונה: חסרה הגדרה", "Último teste: requer autorização ou endpoint seguro": "בדיקה אחרונה: נדרש אישור נוסף או נקודת קצה בטוחה", "Último teste: chamada falhou": "בדיקה אחרונה: הקריאה נכשלה", "Testar credenciais TTS e música": "בדיקת פרטי הגישה של TTS ומוזיקה",
1373
1373
  },
1374
1374
  }
1375
1375
 
@@ -22,6 +22,7 @@ LLM_ACTIVE_CARD_KEY = "llm_active_card_id"
22
22
  LLM_TELEGRAM_CARD_KEY = "llm_telegram_card_id"
23
23
  DEFAULT_LLM_PROVIDER = "openai"
24
24
  DEFAULT_LLM_CARD_ID = "llm-openai-default"
25
+ DEFAULT_LLM_PRIORITY = 1
25
26
 
26
27
 
27
28
  @dataclass(frozen=True, slots=True)
@@ -160,7 +161,7 @@ def _legacy_value(settings: Mapping[str, Any], provider: str, suffix: str) -> st
160
161
  return str(settings.get(f"{prefix}_{suffix}") or "").strip()
161
162
 
162
163
 
163
- def _legacy_card(settings: Mapping[str, Any], provider: str, card_id: str) -> dict[str, Any]:
164
+ def _legacy_card(settings: Mapping[str, Any], provider: str, card_id: str, *, priority: int = DEFAULT_LLM_PRIORITY) -> dict[str, Any]:
164
165
  definition = provider_definition(provider)
165
166
  code = normalize_provider_code(provider)
166
167
  base_url = _legacy_value(settings, code, "base_url") or definition.default_base_url
@@ -179,6 +180,7 @@ def _legacy_card(settings: Mapping[str, Any], provider: str, card_id: str) -> di
179
180
  "model": model,
180
181
  "base_url": base_url,
181
182
  "enabled": True,
183
+ "priority": max(1, int(priority)),
182
184
  "telegram_llm": False,
183
185
  **extra,
184
186
  }
@@ -194,6 +196,7 @@ def new_llm_card(provider: Any, *, card_id: str | None = None) -> dict[str, Any]
194
196
  "model": "",
195
197
  "base_url": definition.default_base_url,
196
198
  "enabled": True,
199
+ "priority": DEFAULT_LLM_PRIORITY,
197
200
  "telegram_llm": False,
198
201
  **{field: "" for field in definition.extra_fields},
199
202
  }
@@ -212,6 +215,13 @@ def _clean_test_result(value: Any) -> dict[str, Any]:
212
215
  }
213
216
 
214
217
 
218
+ def _normalise_priority(value: Any, fallback: int = DEFAULT_LLM_PRIORITY) -> int:
219
+ try:
220
+ return max(1, int(value))
221
+ except (TypeError, ValueError):
222
+ return max(1, int(fallback or DEFAULT_LLM_PRIORITY))
223
+
224
+
215
225
  def normalize_llm_card(card: Any, index: int = 0) -> dict[str, Any]:
216
226
  source = dict(card) if isinstance(card, Mapping) else {}
217
227
  code = normalize_provider_code(source.get("provider") or source.get("provider_code"))
@@ -225,6 +235,7 @@ def normalize_llm_card(card: Any, index: int = 0) -> dict[str, Any]:
225
235
  "model": str(source.get("model") or source.get("model_name") or "").strip(),
226
236
  "base_url": str(source.get("base_url") or "").strip() or definition.default_base_url,
227
237
  "enabled": bool(source.get("enabled", True)),
238
+ "priority": _normalise_priority(source.get("priority", index + 1), index + 1),
228
239
  "telegram_llm": bool(source.get("telegram_llm", source.get("llm_telegram", False))),
229
240
  }
230
241
  for field in definition.extra_fields:
@@ -251,9 +262,15 @@ def ensure_llm_provider_cards(settings: Mapping[str, Any]) -> tuple[dict[str, An
251
262
  cards = [normalize_llm_card(item, index) for index, item in enumerate(raw_cards)] if isinstance(raw_cards, list) else []
252
263
  changed = not isinstance(raw_cards, list)
253
264
 
265
+ selected_provider = normalize_provider_code(result.get("llm_provider") or DEFAULT_LLM_PROVIDER)
266
+ legacy_selected_provider = selected_provider != DEFAULT_LLM_PROVIDER and _card_has_legacy_configuration(result, selected_provider)
267
+ active_id = str(result.get(LLM_ACTIVE_CARD_KEY) or "").strip()
268
+
254
269
  # O primeiro card OpenAI/NVIDIA NIM é estrutural e nunca é removido pela migração.
270
+ # Quando uma configuração legada apontava para outro provider, esse provider
271
+ # recebe prioridade 1 e o cartão estrutural fica logo a seguir.
255
272
  if not any(card.get("provider") == DEFAULT_LLM_PROVIDER for card in cards):
256
- cards.insert(0, _legacy_card(result, DEFAULT_LLM_PROVIDER, DEFAULT_LLM_CARD_ID))
273
+ cards.insert(0, _legacy_card(result, DEFAULT_LLM_PROVIDER, DEFAULT_LLM_CARD_ID, priority=2 if legacy_selected_provider else 1))
257
274
  changed = True
258
275
  elif cards[0].get("provider") != DEFAULT_LLM_PROVIDER:
259
276
  openai_card = next(card for card in cards if card.get("provider") == DEFAULT_LLM_PROVIDER)
@@ -261,26 +278,36 @@ def ensure_llm_provider_cards(settings: Mapping[str, Any]) -> tuple[dict[str, An
261
278
  cards.insert(0, openai_card)
262
279
  changed = True
263
280
 
264
- selected_provider = normalize_provider_code(result.get("llm_provider") or DEFAULT_LLM_PROVIDER)
265
281
  if not str(result.get("llm_provider") or "").strip():
266
282
  result["llm_provider"] = DEFAULT_LLM_PROVIDER
267
283
  changed = True
268
284
  # A migração preserva uma configuração explícita antiga que ainda não tinha card.
269
- if selected_provider != DEFAULT_LLM_PROVIDER and _card_has_legacy_configuration(result, selected_provider):
285
+ if legacy_selected_provider:
270
286
  if not any(card.get("provider") == selected_provider for card in cards):
271
- cards.append(_legacy_card(result, selected_provider, f"llm-{selected_provider}-legacy"))
287
+ cards.append(_legacy_card(result, selected_provider, f"llm-{selected_provider}-legacy", priority=1))
272
288
  changed = True
273
289
 
290
+ # Instalações anteriores só tinham um cartão activo. Transformamos essa
291
+ # escolha na prioridade 1 uma única vez, sem apagar a preferência do utilizador.
292
+ if isinstance(raw_cards, list) and not any(isinstance(item, Mapping) and "priority" in item for item in raw_cards):
293
+ preferred_id = active_id or next((str(card.get("id")) for card in cards if card.get("provider") == selected_provider), "")
294
+ if preferred_id:
295
+ for card in cards:
296
+ old_priority = int(card.get("priority", DEFAULT_LLM_PRIORITY))
297
+ card["priority"] = 1 if str(card.get("id")) == preferred_id else max(2, old_priority)
298
+ changed = True
299
+
300
+ cards = _ordered_cards(cards)
274
301
  serialized_before = raw_cards if isinstance(raw_cards, list) else None
275
302
  if serialized_before != cards:
276
303
  changed = True
277
304
  result[LLM_CARDS_KEY] = cards
278
305
 
279
- active_id = str(result.get(LLM_ACTIVE_CARD_KEY) or "").strip()
280
306
  ids = {str(card.get("id")) for card in cards}
281
- if active_id not in ids:
282
- matching = next((card for card in cards if card.get("provider") == selected_provider), cards[0])
283
- result[LLM_ACTIVE_CARD_KEY] = str(matching["id"])
307
+ ordered = _ordered_cards(cards)
308
+ first_enabled = next((card for card in ordered if card.get("enabled", True)), ordered[0])
309
+ if active_id != str(first_enabled["id"]):
310
+ result[LLM_ACTIVE_CARD_KEY] = str(first_enabled["id"])
284
311
  changed = True
285
312
  if not any(card.get("telegram_llm") for card in cards):
286
313
  if result.get(LLM_TELEGRAM_CARD_KEY):
@@ -294,19 +321,23 @@ def ensure_llm_provider_cards(settings: Mapping[str, Any]) -> tuple[dict[str, An
294
321
  return result, changed
295
322
 
296
323
 
324
+ def _ordered_cards(cards: list[Mapping[str, Any]]) -> list[dict[str, Any]]:
325
+ indexed = [(index, normalize_llm_card(card, index)) for index, card in enumerate(cards)]
326
+ indexed.sort(key=lambda pair: (pair[1].get("priority", pair[0] + 1), pair[0]))
327
+ return [card for _index, card in indexed]
328
+
329
+
297
330
  def llm_cards(settings: Mapping[str, Any]) -> list[dict[str, Any]]:
298
331
  migrated, _ = ensure_llm_provider_cards(settings)
299
- return [dict(card) for card in migrated.get(LLM_CARDS_KEY, [])]
332
+ cards = migrated.get(LLM_CARDS_KEY, [])
333
+ return _ordered_cards(cards) if isinstance(cards, list) else []
300
334
 
301
335
 
302
336
  def active_llm_card(settings: Mapping[str, Any]) -> dict[str, Any]:
303
337
  migrated, _ = ensure_llm_provider_cards(settings)
304
338
  cards = migrated.get(LLM_CARDS_KEY, [])
305
- active_id = str(migrated.get(LLM_ACTIVE_CARD_KEY) or "")
306
- for card in cards:
307
- if str(card.get("id")) == active_id and card.get("enabled", True):
308
- return dict(card)
309
- for card in cards:
339
+ ordered = _ordered_cards(cards) if isinstance(cards, list) else []
340
+ for card in ordered:
310
341
  if card.get("enabled", True):
311
342
  return dict(card)
312
343
  return new_llm_card(DEFAULT_LLM_PROVIDER, card_id=DEFAULT_LLM_CARD_ID)
@@ -322,7 +353,7 @@ def telegram_llm_card(settings: Mapping[str, Any]) -> dict[str, Any] | None:
322
353
  def apply_llm_cards_to_settings(
323
354
  settings: Mapping[str, Any], cards: list[Mapping[str, Any]], active_card_id: str = ""
324
355
  ) -> dict[str, Any]:
325
- """Persist cards and mirror the active card to the legacy runtime contract."""
356
+ """Persist priority-ordered cards and mirror priority 1 to the legacy runtime contract."""
326
357
  result = dict(settings)
327
358
  normalized = [normalize_llm_card(item, index) for index, item in enumerate(cards)]
328
359
  if not normalized or not any(card.get("provider") == DEFAULT_LLM_PROVIDER for card in normalized):
@@ -334,10 +365,12 @@ def apply_llm_cards_to_settings(
334
365
  for card in normalized:
335
366
  card["telegram_llm"] = bool(telegram and card["id"] == telegram["id"])
336
367
 
337
- wanted_id = str(active_card_id or result.get(LLM_ACTIVE_CARD_KEY) or "").strip()
338
- active = next((card for card in normalized if card["id"] == wanted_id), None)
339
- if active is None or not active.get("enabled", True):
340
- active = next((card for card in normalized if card.get("enabled", True)), normalized[0])
368
+ if active_card_id and not any(isinstance(item, Mapping) and "priority" in item for item in cards):
369
+ for card in normalized:
370
+ old_priority = int(card.get("priority", DEFAULT_LLM_PRIORITY))
371
+ card["priority"] = 1 if str(card.get("id")) == str(active_card_id) else max(2, old_priority)
372
+ ordered = _ordered_cards(normalized)
373
+ active = next((card for card in ordered if card.get("enabled", True)), ordered[0])
341
374
  result[LLM_CARDS_KEY] = normalized
342
375
  result[LLM_ACTIVE_CARD_KEY] = active["id"]
343
376
  result[LLM_TELEGRAM_CARD_KEY] = telegram["id"] if telegram else ""
@@ -276,17 +276,18 @@ def classify_response(response: Any) -> None:
276
276
 
277
277
 
278
278
  def enabled_cards(settings: Mapping[str, Any], pool: str) -> list[dict[str, Any]]:
279
- """Return cards in priority order; capability filtering is applied by media adapters."""
279
+ """Return cards in deterministic priority order; media pools keep active-card preference."""
280
280
  if pool == POOL_LLM:
281
281
  migrated, _ = ensure_llm_provider_cards(settings)
282
282
  raw_cards = migrated.get("llm_provider_cards", [])
283
283
  cards = [normalize_llm_card(item, index) for index, item in enumerate(raw_cards)] if isinstance(raw_cards, list) else []
284
- active_id = str(migrated.get(LLM_ACTIVE_CARD_KEY) or "")
285
- else:
286
- raw_cards = settings.get("media_provider_cards", [])
287
- cards = [dict(item) for item in raw_cards if isinstance(item, Mapping)] if isinstance(raw_cards, list) else []
288
- active_key = "media_image_active_card_id" if pool == POOL_IMAGE else "media_video_active_card_id"
289
- active_id = str(settings.get(active_key) or "")
284
+ enabled = [(index, card) for index, card in enumerate(cards) if bool(card.get("enabled", True))]
285
+ enabled.sort(key=lambda pair: (int(pair[1].get("priority", 1)), pair[0]))
286
+ return [card for _index, card in enabled]
287
+ raw_cards = settings.get("media_provider_cards", [])
288
+ cards = [dict(item) for item in raw_cards if isinstance(item, Mapping)] if isinstance(raw_cards, list) else []
289
+ active_key = "media_image_active_card_id" if pool == POOL_IMAGE else "media_video_active_card_id"
290
+ active_id = str(settings.get(active_key) or "")
290
291
  enabled = [card for card in cards if bool(card.get("enabled", True))]
291
292
  if active_id:
292
293
  enabled.sort(key=lambda item: 0 if str(item.get("id")) == active_id else 1)
@@ -363,16 +364,28 @@ def route_json_request(
363
364
  max_attempts: int | None = None,
364
365
  cooldown_seconds: float | None = None,
365
366
  ) -> RoutedResponse:
366
- """Execute a JSON request over eligible cards with bounded, classified failover."""
367
+ """Execute a JSON request over eligible cards with classified priority failover."""
367
368
  if pool not in POOLS:
368
369
  raise ProviderRoutingError(f"Pool de providers inválido: {pool}")
369
370
  candidates = [dict(item) for item in (cards if cards is not None else enabled_cards(settings, pool))]
371
+ if pool == POOL_LLM:
372
+ candidates = [
373
+ card
374
+ for _index, card in sorted(
375
+ enumerate(candidates),
376
+ key=lambda pair: (int(pair[1].get("priority", pair[0] + 1)), pair[0]),
377
+ )
378
+ ]
370
379
  if not candidates:
371
380
  raise ProviderRoutingError(f"Não existem providers activos no pool {pool}.")
372
381
  try:
373
- maximum = max(1, min(len(candidates), int(max_attempts or settings.get("provider_max_attempts", DEFAULT_MAX_ATTEMPTS))))
382
+ if pool == POOL_LLM and max_attempts is None:
383
+ maximum = len(candidates)
384
+ else:
385
+ configured_max_attempts = max_attempts if max_attempts is not None else settings.get("provider_max_attempts")
386
+ maximum = max(1, min(len(candidates), int(configured_max_attempts or DEFAULT_MAX_ATTEMPTS)))
374
387
  except (TypeError, ValueError):
375
- maximum = min(len(candidates), DEFAULT_MAX_ATTEMPTS)
388
+ maximum = len(candidates) if pool == POOL_LLM else min(len(candidates), DEFAULT_MAX_ATTEMPTS)
376
389
  cooldown = float(cooldown_seconds if cooldown_seconds is not None else settings.get("provider_cooldown_seconds", DEFAULT_COOLDOWN_SECONDS))
377
390
  attempts: list[dict[str, Any]] = []
378
391
  for card in candidates[:maximum]:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.3.46",
3
+ "version": "0.3.47",
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",