From f29e61f3350c5a341038975068de1a2a3fa0e2ec Mon Sep 17 00:00:00 2001 From: root Date: Tue, 17 Mar 2026 11:28:43 -0300 Subject: [PATCH] =?UTF-8?q?chore:=20sync=20prod=20state=20=E2=80=94=20Lite?= =?UTF-8?q?LLM/LLMFit=20integration=20+=20compose=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker-compose.prod.yml: LiteLLM na rede coolify, LLMFIT_BASE_URL/API_KEY, rede coolify external - docker/litellm-config.yaml: TIER 1 LLMFit ativo, fallback Ollama configurado - Dockerfile: ajustes de build - server/: novos módulos SOE, plus-sync, schemas compartilhados --- Dockerfile | 9 ++-- client/src/contexts/SoeMotorContext.tsx | 17 +++++++ client/src/pages/SOE.tsx | 7 +++ docker-compose.prod.yml | 18 +++++-- docker/litellm-config.yaml | 66 +++++++++++-------------- server/bi/upload.ts | 6 +-- server/erp/routes.ts | 3 ++ server/index.ts | 2 +- server/modules/loader.ts | 6 +++ server/retail/plus-sync.ts | 9 ++++ shared/schemas/index.ts | 3 ++ 11 files changed, 96 insertions(+), 50 deletions(-) create mode 100644 client/src/contexts/SoeMotorContext.tsx create mode 100644 client/src/pages/SOE.tsx create mode 100644 server/modules/loader.ts create mode 100644 server/retail/plus-sync.ts create mode 100644 shared/schemas/index.ts diff --git a/Dockerfile b/Dockerfile index ddb0688..ddf659c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ -RUN npm ci --ignore-scripts +RUN npm ci COPY . . RUN npm run build @@ -18,16 +18,19 @@ ENV NODE_ENV=production # Deps de produção apenas COPY package*.json ./ -RUN npm ci --omit=dev --ignore-scripts +RUN npm ci --omit=dev # Artefatos do build COPY --from=builder /app/dist ./dist COPY --from=builder /app/shared ./shared COPY --from=builder /app/migrations ./migrations +# Arquivos de runtime necessários (caminhos quebrados pelo bundler) +RUN cp /app/node_modules/connect-pg-simple/table.sql /app/dist/table.sql + EXPOSE 5000 HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ - CMD wget -qO- http://localhost:5000/api/health || exit 1 + CMD wget -qO- http://127.0.0.1:5000/ || exit 1 CMD ["node", "dist/index.cjs"] diff --git a/client/src/contexts/SoeMotorContext.tsx b/client/src/contexts/SoeMotorContext.tsx new file mode 100644 index 0000000..996a6ce --- /dev/null +++ b/client/src/contexts/SoeMotorContext.tsx @@ -0,0 +1,17 @@ +import { createContext, useContext, ReactNode } from "react"; + +interface SoeMotorContextType {} + +const SoeMotorContext = createContext({}); + +export function SoeMotorProvider({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} + +export function useSoeMotor() { + return useContext(SoeMotorContext); +} diff --git a/client/src/pages/SOE.tsx b/client/src/pages/SOE.tsx new file mode 100644 index 0000000..ca173a7 --- /dev/null +++ b/client/src/pages/SOE.tsx @@ -0,0 +1,7 @@ +export default function SOE() { + return ( +
+

SOE — em desenvolvimento

+
+ ); +} diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index af01a8c..ddb2cd6 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -72,12 +72,15 @@ services: condition: service_started networks: - arcadia-internal - - arcadia-public + - coolify labels: - "traefik.enable=true" + - "traefik.docker.network=coolify" + - "traefik.http.routers.arcadia.entrypoints=https" - "traefik.http.routers.arcadia.rule=Host(`${DOMAIN}`)" - "traefik.http.routers.arcadia.tls=true" - "traefik.http.routers.arcadia.tls.certresolver=letsencrypt" + - "traefik.http.services.arcadia.loadbalancer.server.port=5000" # ── Microserviços Python ───────────────────────────────────────────────────── contabil: @@ -153,6 +156,9 @@ services: SERVICE_NAME: embeddings SERVICE_PORT: 8001 DATABASE_URL: postgresql://${PGUSER:-arcadia}:${PGPASSWORD}@db:5432/${PGDATABASE:-arcadia} + LITELLM_BASE_URL: http://litellm:4000 + LITELLM_API_KEY: ${LITELLM_API_KEY} + OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://ollama:11434} depends_on: db: condition: service_healthy @@ -170,12 +176,13 @@ services: environment: OPENAI_API_KEY: ${OPENAI_API_KEY:-} LITELLM_MASTER_KEY: ${LITELLM_API_KEY} - DATABASE_URL: postgresql://${PGUSER:-arcadia}:${PGPASSWORD}@db:5432/${PGDATABASE:-arcadia} + DATABASE_URL: postgresql://${PGUSER:-arcadia}:${PGPASSWORD}@db:5432/litellm # Ollama: se instalado no host use http://host-gateway:11434 # Se usar container Docker, mantém http://ollama:11434 OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://ollama:11434} # LLMFit: URL do serviço de modelos fine-tuned LLMFIT_BASE_URL: ${LLMFIT_BASE_URL:-} + LLMFIT_API_KEY: ${LLMFIT_API_KEY:-} # Providers externos opcionais (soberania: só habilitados se configurados) ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} GROQ_API_KEY: ${GROQ_API_KEY:-} @@ -184,6 +191,7 @@ services: condition: service_healthy networks: - arcadia-internal + - coolify # ── Ollama (LLMs locais — soberania total) ──────────────────────────────────── # OPÇÃO A (padrão): Ollama como container Docker @@ -215,7 +223,7 @@ services: - litellm networks: - arcadia-internal - - arcadia-public + - coolify labels: - "traefik.enable=true" - "traefik.http.routers.webui.rule=Host(`ai.${DOMAIN}`)" @@ -227,8 +235,8 @@ services: networks: arcadia-internal: driver: bridge - arcadia-public: - driver: bridge + coolify: + external: true volumes: pgdata: diff --git a/docker/litellm-config.yaml b/docker/litellm-config.yaml index 336d872..0085857 100644 --- a/docker/litellm-config.yaml +++ b/docker/litellm-config.yaml @@ -13,35 +13,22 @@ model_list: # ── TIER 1: LLMFit (modelos fine-tuned locais — máxima soberania) ──────────── - # Descomente quando o LLMFit estiver rodando no servidor - # O LLMFit expõe API compatível com OpenAI — basta apontar a URL - # - # - model_name: arcadia-finetuned - # litellm_params: - # model: openai/arcadia-v1 # nome do modelo no LLMFit - # api_base: os.environ/LLMFIT_BASE_URL - # api_key: llmfit-internal - # - # - model_name: arcadia-embed - # litellm_params: - # model: openai/arcadia-embed-v1 # modelo de embeddings fine-tuned - # api_base: os.environ/LLMFIT_BASE_URL - # api_key: llmfit-internal + - model_name: arcadia-finetuned + litellm_params: + model: openai/llama3.2:3b + api_base: os.environ/LLMFIT_BASE_URL + api_key: os.environ/LLMFIT_API_KEY + + - model_name: arcadia-embed + litellm_params: + model: openai/nomic-embed-text:latest + api_base: os.environ/LLMFIT_BASE_URL + api_key: os.environ/LLMFIT_API_KEY # ── TIER 2: Ollama (LLMs locais — soberania total) ─────────────────────────── - - model_name: llama3.3 + - model_name: llama3.2 litellm_params: - model: ollama/llama3.3 - api_base: os.environ/OLLAMA_BASE_URL - - - model_name: qwen2.5-coder - litellm_params: - model: ollama/qwen2.5-coder:7b - api_base: os.environ/OLLAMA_BASE_URL - - - model_name: deepseek-r1 - litellm_params: - model: ollama/deepseek-r1:7b + model: ollama/llama3.2:3b api_base: os.environ/OLLAMA_BASE_URL - model_name: nomic-embed-text @@ -49,6 +36,12 @@ model_list: model: ollama/nomic-embed-text api_base: os.environ/OLLAMA_BASE_URL + # Alias OpenAI-compatible para embedding (Manus usa este nome por padrão) + - model_name: text-embedding-3-small + litellm_params: + model: ollama/nomic-embed-text + api_base: os.environ/OLLAMA_BASE_URL + # ── TIER 3: OpenAI (opt-in — só ativo se OPENAI_API_KEY configurado) ───────── - model_name: gpt-4o litellm_params: @@ -73,29 +66,26 @@ model_list: # api_key: os.environ/GROQ_API_KEY # ── Modelo padrão do Arcádia (Manus usa este) ───────────────────────────────── - # Prioridade: LLMFit → OpenAI (se configurado) → Ollama (sempre disponível) - # Para soberania total: remova o fallback para gpt-4o-mini + # Prioridade: LLMFit (TIER 1) → Ollama (TIER 2 — fallback) - model_name: arcadia-default litellm_params: - model: ollama/llama3.3 - api_base: os.environ/OLLAMA_BASE_URL - model_info: - # fallbacks: ["gpt-4o-mini"] # descomente para habilitar fallback externo + model: openai/llama3.2:3b + api_base: os.environ/LLMFIT_BASE_URL + api_key: os.environ/LLMFIT_API_KEY router_settings: routing_strategy: least-busy fallbacks: - - {"gpt-4o": ["llama3.3"]} - - {"gpt-4o-mini": ["llama3.3"]} - - {"arcadia-default": ["llama3.3"]} + - {"gpt-4o": ["llama3.2"]} + - {"gpt-4o-mini": ["llama3.2"]} + - {"arcadia-default": ["llama3.2"]} + - {"arcadia-finetuned": ["llama3.2"]} + - {"arcadia-embed": ["nomic-embed-text"]} litellm_settings: drop_params: true request_timeout: 120 set_verbose: false - # Loga todas as chamadas no banco — essencial para auditoria e soberania - success_callback: ["langfuse"] - failure_callback: ["langfuse"] general_settings: master_key: os.environ/LITELLM_MASTER_KEY diff --git a/server/bi/upload.ts b/server/bi/upload.ts index 5ebe16f..f270556 100644 --- a/server/bi/upload.ts +++ b/server/bi/upload.ts @@ -2,15 +2,15 @@ import type { Express, Request, Response } from "express"; import multer from "multer"; import path from "path"; import fs from "fs"; -import { createRequire } from "module"; + import AdmZip from "adm-zip"; import * as BSON from "bson"; import { db } from "../../db/index"; import { biDatasets, stagedTables } from "@shared/schema"; import { sql } from "drizzle-orm"; -const require = createRequire(import.meta.url); -const XLSX = require("xlsx"); + +import * as XLSX from "xlsx"; const uploadDir = path.join(process.cwd(), "uploads"); if (!fs.existsSync(uploadDir)) { diff --git a/server/erp/routes.ts b/server/erp/routes.ts index f8d36ba..1280db7 100644 --- a/server/erp/routes.ts +++ b/server/erp/routes.ts @@ -1136,3 +1136,6 @@ export function registerErpRoutes(app: Express): void { } }); } +// SOE routes — placeholder + +export function registerSoeRoutes(_app: Express): void {} diff --git a/server/index.ts b/server/index.ts index 20654ef..f980fb9 100644 --- a/server/index.ts +++ b/server/index.ts @@ -346,7 +346,7 @@ export function log(message: string, source = "express") { password: hashedPassword, name: "Administrador Master", email: "admin@arcadia.suite", - role: "master", + role: "admin", status: "active", }); console.log("[Seed] Usuário master 'admin' criado com sucesso"); diff --git a/server/modules/loader.ts b/server/modules/loader.ts new file mode 100644 index 0000000..2c8b310 --- /dev/null +++ b/server/modules/loader.ts @@ -0,0 +1,6 @@ +import type { Express } from "express"; + +// Carregador de rotas modulares — placeholder +export async function loadModuleRoutes(_app: Express): Promise { + // Módulos serão registrados aqui conforme forem criados +} diff --git a/server/retail/plus-sync.ts b/server/retail/plus-sync.ts new file mode 100644 index 0000000..b633698 --- /dev/null +++ b/server/retail/plus-sync.ts @@ -0,0 +1,9 @@ +// Serviço de sincronização com Plus — placeholder +export const retailPlusSyncService = { + async getPlusStatus() { return { connected: false }; }, + async syncAllPersonsToPlus(_tenantId: any, _empresaId: any) { return { synced: 0 }; }, + async syncSaleToPlus(_saleId: any) { return { synced: false }; }, + async emitirNFeSale(_saleId: any, _tipo?: string) { return { emitted: false }; }, + async importClientesFromPlus(_tenantId: any, _empresaId: any) { return { imported: 0 }; }, + async importProdutosFromPlus(_tenantId: any, _empresaId: any) { return { imported: 0 }; }, +}; diff --git a/shared/schemas/index.ts b/shared/schemas/index.ts new file mode 100644 index 0000000..41a9f22 --- /dev/null +++ b/shared/schemas/index.ts @@ -0,0 +1,3 @@ +// Schemas modulares — gerados pelo Dev Center +// Arquivo placeholder: adicione exports conforme módulos forem criados +export {};