@danhachuel/pandanews 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/backend/app/main.py +1 -1
- package/backend/app/routers/configuracoes.py +29 -1
- package/frontend/dist/assets/index-BLjBdAFC.js +70 -0
- package/frontend/dist/index.html +1 -1
- package/package.json +3 -2
- package/scripts/start.js +185 -76
- package/scripts/test-start-isolation.mjs +40 -0
- package/frontend/dist/assets/index-WDOmiBk4.js +0 -70
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Todas as versões publicadas são registradas aqui antes do publish (regra em AGENTS.md). A etiqueta visual usa PATCH de dois dígitos (ex.: 0.1.00); o registry npm normaliza para a versão canônica (ex.: 0.1.0).
|
|
4
4
|
|
|
5
|
+
## 0.4.02 (2026-11-08)
|
|
6
|
+
|
|
7
|
+
- **Seletor dinâmico de modelos NVIDIA NIM**: novo endpoint proxy `GET /api/v1/configuracoes/llm/nvidia/models` que consulta a NVIDIA em tempo real com a chave do usuário — a API key nunca é exposta ao frontend/Network tab
|
|
8
|
+
- Campo "Modelo" da NVIDIA em Configurações agora é um `<select>` populado automaticamente (5 min de cache, botão ↻ para recarregar) — o usuário não digita mais IDs
|
|
9
|
+
- Resiliência: sem chave, offline ou lista indisponível, o select mantém o modelo atual como opção (fallback) com aviso âmbar — nada de travar a tela
|
|
10
|
+
|
|
11
|
+
## 0.4.01 (2026-11-08)
|
|
12
|
+
|
|
13
|
+
- **Isolamento de processos (Windows/MobaXterm)**: o backend Python roda em grupo de processos próprio (`detached: true` → `CREATE_NEW_PROCESS_GROUP`) com `windowsHide: true` (sem janela fantasma) e `stdio` em fd do arquivo — um Ctrl+C no terminal agora derruba **apenas o launcher Node**; o backend e as gerações em andamento sobrevivem
|
|
14
|
+
- **Fim do processo órfão na porta 8000**: ao reabrir o app, o launcher detecta o backend vivo (`backend.pid` + probe de porta) e o **reaproveita**, em vez de subir uma segunda instância
|
|
15
|
+
- **Log sem terminal**: a inicialização do uvicorn e as requisições ficam registradas em `data/backend.log` mesmo com o terminal fechado (auditoria preservada)
|
|
16
|
+
- Encerramento do backend **sempre por código**: `taskkill /PID /F /T` no Windows, `kill` no grupo no Unix — sinais do terminal nunca chegam ao backend
|
|
17
|
+
- `unref()` no processo filho + watchdog de saúde (polling de porta a cada 10s; 3 falhas reerguem o backend silenciosamente)
|
|
18
|
+
- Teste de regressão `scripts/test-start-isolation.mjs` (`npm test`) roda no CI verificando as flags de isolamento — passo adicionado ao workflow de publish
|
|
19
|
+
|
|
5
20
|
## 0.4.00 (2026-10-30)
|
|
6
21
|
|
|
7
22
|
- **Supabase opcional (Fase 6)**: detecção automática de credenciais (`SUPABASE_URL`/`SUPABASE_SERVICE_ROLE_KEY` no ambiente ou em Configurações); teste de conexão real (`POST /configuracoes/testar-supabase`); schema SQL pronto para o SQL Editor (`GET /configuracoes/schema-supabase`); migração dos dados locais SQLite → Supabase (`POST /configuracoes/migrar-supabase`) com relatório por tabela. O app continua 100% local e funcional sem Supabase
|
package/backend/app/main.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Configurações (/api/v1/configuracoes) — API keys mascaradas, sem travas."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from fastapi import APIRouter, Depends
|
|
4
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
5
5
|
from sqlalchemy.orm import Session
|
|
6
6
|
|
|
7
7
|
from backend.app.schemas import ConfiguracoesPatch
|
|
@@ -43,6 +43,34 @@ def obter_configuracoes(db: Session = Depends(get_db)) -> dict:
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
@router.get("/llm/nvidia/models")
|
|
47
|
+
def listar_modelos_nvidia(db: Session = Depends(get_db)) -> dict:
|
|
48
|
+
"""Lista os modelos NVIDIA NIM disponíveis para a chave configurada.
|
|
49
|
+
|
|
50
|
+
Proxy: a API key fica no banco local e nunca é exposta ao frontend.
|
|
51
|
+
Retorna 400 sem chave; 502 em falha de consulta.
|
|
52
|
+
"""
|
|
53
|
+
import httpx
|
|
54
|
+
|
|
55
|
+
from backend.core.llm_router import provider_config
|
|
56
|
+
|
|
57
|
+
cfg = provider_config(db, "nvidia")
|
|
58
|
+
if not cfg["api_key"]:
|
|
59
|
+
raise HTTPException(status_code=400, detail="API Key da NVIDIA não configurada — adicione-a antes de listar os modelos.")
|
|
60
|
+
url = cfg["base_url"].rstrip("/") + "/models"
|
|
61
|
+
try:
|
|
62
|
+
resposta = httpx.get(url, headers={"Authorization": f"Bearer {cfg['api_key']}"}, timeout=20.0)
|
|
63
|
+
except httpx.HTTPError as exc:
|
|
64
|
+
raise HTTPException(status_code=502, detail=f"Erro ao consultar a NVIDIA: {exc}") from exc
|
|
65
|
+
if resposta.status_code != 200:
|
|
66
|
+
raise HTTPException(
|
|
67
|
+
status_code=502,
|
|
68
|
+
detail=f"NVIDIA respondeu {resposta.status_code}: {resposta.text[:200]}",
|
|
69
|
+
)
|
|
70
|
+
ids = sorted(str(m.get("id")) for m in resposta.json().get("data", []) if m.get("id"))
|
|
71
|
+
return {"models": ids, "modelo_atual": cfg["model"], "base_url": cfg["base_url"]}
|
|
72
|
+
|
|
73
|
+
|
|
46
74
|
@router.post("/testar-supabase")
|
|
47
75
|
def testar_supabase() -> dict:
|
|
48
76
|
from backend.core import supabase_db
|