From 3298cd8c5d90176e910ce4492925485058584333 Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Tue, 23 Jun 2026 18:40:41 +0000 Subject: [PATCH] feat: implement Hybrid AI architecture for admin norm builder --- App.tsx | 19 +++++++++++++ components/AdminPanel.tsx | 3 ++ components/AdminStandards.tsx | 53 +++++++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/App.tsx b/App.tsx index 19204c5..9342aab 100644 --- a/App.tsx +++ b/App.tsx @@ -19,6 +19,8 @@ const App: React.FC = () => { const [endpoint, setEndpoint] = useState(''); const [provider, setProvider] = useState('gemini'); const [model, setModel] = useState('gemini-2.5-flash'); + const [adminApiKey, setAdminApiKey] = useState(''); + const [adminModel, setAdminModel] = useState('claude-3.5-sonnet-20241022'); const [hasKey, setHasKey] = useState(false); const [reportsData, setReportsData] = useState(null); const [isLoading, setIsLoading] = useState(false); @@ -50,6 +52,9 @@ const App: React.FC = () => { fetch('/api/config') .then(res => res.json()) .then(config => { + if (config.adminApiKey) setAdminApiKey(config.adminApiKey); + if (config.adminModel) setAdminModel(config.adminModel); + if (config.provider) { setProvider(config.provider); if (config.apiKey) setApiKey(config.apiKey); @@ -224,6 +229,20 @@ const App: React.FC = () => { apiKey={apiKey} model={model} endpoint={endpoint} + adminApiKey={adminApiKey} + adminModel={adminModel} + onAdminConfigSave={(key, mdl) => { + setAdminApiKey(key); + setAdminModel(mdl); + fetch('/api/config', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + provider, apiKey, model, endpoint, + adminApiKey: key, adminModel: mdl + }) + }); + }} /> ) : (!hasKey || showSetup) ? ( setShowSetup(false) : undefined} /> diff --git a/components/AdminPanel.tsx b/components/AdminPanel.tsx index 6a44a6f..6b0172d 100644 --- a/components/AdminPanel.tsx +++ b/components/AdminPanel.tsx @@ -8,6 +8,9 @@ interface AdminPanelProps { provider: AIProvider; model: string; endpoint?: string; + adminApiKey: string; + adminModel: string; + onAdminConfigSave: (key: string, model: string) => void; } export const AdminPanel: React.FC = (props) => { diff --git a/components/AdminStandards.tsx b/components/AdminStandards.tsx index a054a45..10f5a72 100644 --- a/components/AdminStandards.tsx +++ b/components/AdminStandards.tsx @@ -8,9 +8,12 @@ interface AdminStandardsProps { provider: AIProvider; model: string; endpoint?: string; + adminApiKey: string; + adminModel: string; + onAdminConfigSave: (key: string, model: string) => void; } -export const AdminStandards: React.FC = ({ apiKey, provider, model, endpoint }) => { +export const AdminStandards: React.FC = ({ apiKey, provider, model, endpoint, adminApiKey, adminModel, onAdminConfigSave }) => { const [categories, setCategories] = useState([]); const [selectedCategory, setSelectedCategory] = useState(''); const [standards, setStandards] = useState([]); @@ -21,6 +24,9 @@ export const AdminStandards: React.FC = ({ apiKey, provider const [generatedJson, setGeneratedJson] = useState(''); const [jsonError, setJsonError] = useState(null); + const [localAdminKey, setLocalAdminKey] = useState(adminApiKey); + const [localAdminModel, setLocalAdminModel] = useState(adminModel); + useEffect(() => { fetchCategories(); }, []); @@ -66,7 +72,8 @@ export const AdminStandards: React.FC = ({ apiKey, provider setJsonError(null); try { const jsonObj = await buildStandardWithAI( - { provider, apiKey, model, endpoint }, + // Use the admin config if provided, otherwise fallback to the global one + localAdminKey ? { provider: 'openrouter', apiKey: localAdminKey, model: localAdminModel } : { provider, apiKey, model, endpoint }, standardName, cat.description ); @@ -113,6 +120,42 @@ export const AdminStandards: React.FC = ({ apiKey, provider return (
+ {/* Admin Engine Config */} +
+

Motor de Engenharia IA (Opcional)

+

+ Para criar normas perfeitamente estruturadas, recomendamos utilizar um modelo avançado como Claude 3.5 Sonnet ou GPT-4o via OpenRouter, separado do modelo de leitura rápida usado na página inicial. +

+
+
+ + setLocalAdminKey(e.target.value)} + placeholder="sk-or-v1-..." + className="w-full rounded-md border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 px-3 py-1.5 text-sm" + /> +
+
+ + setLocalAdminModel(e.target.value)} + placeholder="ex: anthropic/claude-3.5-sonnet" + className="w-full rounded-md border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 px-3 py-1.5 text-sm font-mono" + /> +
+
+ +
+ {/* Selector */}
@@ -152,14 +195,14 @@ export const AdminStandards: React.FC = ({ apiKey, provider - {!apiKey && ( -

Configure a Chave da API no painel inicial primeiro.

+ {!(localAdminKey || apiKey) && ( +

Configure uma Chave de IA (Admin ou Global) primeiro.

)} {jsonError && (