docs & fixes
All checks were successful
Mindforge Cronjob Build and Deploy / Build Mindforge Cronjob Image (push) Successful in 4m12s
Mindforge Cronjob Build and Deploy / Deploy Mindforge Cronjob (internal) (push) Successful in 36s
Mindforge Web Build and Deploy (internal) / Build Mindforge Web Image (push) Successful in 5m30s
Mindforge Web Build and Deploy (internal) / Deploy Mindforge Web (internal) (push) Successful in 8s
All checks were successful
Mindforge Cronjob Build and Deploy / Build Mindforge Cronjob Image (push) Successful in 4m12s
Mindforge Cronjob Build and Deploy / Deploy Mindforge Cronjob (internal) (push) Successful in 36s
Mindforge Web Build and Deploy (internal) / Build Mindforge Web Image (push) Successful in 5m30s
Mindforge Web Build and Deploy (internal) / Deploy Mindforge Web (internal) (push) Successful in 8s
This commit is contained in:
27
AGENTS.md
27
AGENTS.md
@@ -1,15 +1,18 @@
|
||||
# Agents
|
||||
# Agentes
|
||||
|
||||
Have a read in `project-context.md` file, it will be the main source of truth for the project. Always keep it up to date with the latest project specs and architecture decisions.
|
||||
Leia o arquivo `project-context.md`, pois ele é a principal fonte de verdade do projeto.
|
||||
|
||||
## UI specs
|
||||
- All UI needs to be have a glassy-look, with a not-so-dark background
|
||||
- Buttons needs to appear iOS-like and modern
|
||||
- All text inputs, displays and content should appear with a modern typefont
|
||||
- All texts needs to be in Brazilian Portuguese
|
||||
## Manutenção do project-context
|
||||
- Mantenha o `project-context.md` sempre atualizado com o estado atual do projeto, sem transformá-lo em histórico de mudanças.
|
||||
- Sempre que houver alteração em arquitetura, endpoints, contratos de API, variáveis de ambiente, UI/UX, fluxos de produto ou decisões técnicas, atualize o `project-context.md` na mesma entrega.
|
||||
|
||||
## Testing
|
||||
Follow strictly the testing requirements:
|
||||
- It should NOT have any form of integration testing, nor unit testing, or any kind of testing.
|
||||
- The only type of testing that should be done is building the project - make sure it compiles, and it's enough.
|
||||
- Don't create random tests or any kind of files that is related to testing. All testing will be done by a human later on.
|
||||
## Especificações de UI
|
||||
- Toda a interface precisa ter aparência de vidro, com um fundo não tão escuro.
|
||||
- Os botões precisam parecer modernos, no estilo iOS.
|
||||
- Todos os campos de texto, exibições e conteúdos devem ter uma tipografia moderna.
|
||||
- Todos os textos precisam estar em português brasileiro.
|
||||
|
||||
## Testes
|
||||
- Não deve haver nenhuma forma de teste de integração, nem teste unitário, nem qualquer outro tipo de teste.
|
||||
- O único tipo de validação que deve ser feito é compilar o projeto - basta verificar se ele compila.
|
||||
- Toda a validação será feita por um humano depois.
|
||||
|
||||
@@ -98,7 +98,7 @@ export function SpacedReviewComponent() {
|
||||
const [dashboard, setDashboard] = useState<FlashcardRagDashboardResponse | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [selectedStatuses, setSelectedStatuses] = useState<FlashcardRagStatus[]>(['Red', 'Amber']);
|
||||
const [selectedStatuses, setSelectedStatuses] = useState<FlashcardRagStatus[]>(['Red', 'Amber', 'Green', 'Grey']);
|
||||
const [selectedLibraryIds, setSelectedLibraryIds] = useState<number[]>([]);
|
||||
const [startingSession, setStartingSession] = useState(false);
|
||||
const [sessionCards, setSessionCards] = useState<FlashcardCard[]>([]);
|
||||
@@ -129,6 +129,14 @@ export function SpacedReviewComponent() {
|
||||
const kept = current.filter((libraryId) => available.has(libraryId));
|
||||
return kept.length > 0 ? kept : allLibraryIds;
|
||||
});
|
||||
|
||||
setSelectedStatuses((current) => {
|
||||
if (current.length > 0) {
|
||||
return current;
|
||||
}
|
||||
|
||||
return ['Red', 'Amber', 'Green', 'Grey'];
|
||||
});
|
||||
} catch (err: any) {
|
||||
setError(err?.message || 'Falha ao carregar status de revisao espacada.');
|
||||
} finally {
|
||||
@@ -214,7 +222,7 @@ export function SpacedReviewComponent() {
|
||||
}
|
||||
|
||||
if (selectedRagLibraries.length === 0) {
|
||||
setError('Nenhum arquivo encontrado com os filtros selecionados.');
|
||||
setError('Nenhum arquivo encontrado com os filtros atuais. Ajuste os status ou os arquivos selecionados.');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -400,7 +408,7 @@ export function SpacedReviewComponent() {
|
||||
</p>
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={startingSession || selectedRagLibraries.length === 0}
|
||||
disabled={startingSession || loading}
|
||||
onClick={startSession}
|
||||
>
|
||||
{startingSession ? 'Iniciando...' : 'Iniciar Revisao Espacada'}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
## Mindforge Architecture
|
||||
# Arquitetura do Mindforge
|
||||
|
||||
This is a project that will be used to aid the user in making notes and studying for hard exams and tests.
|
||||
Este é um projeto que será usado para ajudar o usuário a fazer anotações e estudar para provas e testes difíceis.
|
||||
|
||||
11
dev.ps1
11
dev.ps1
@@ -1,11 +0,0 @@
|
||||
# Starting Mindforge Development Environment
|
||||
|
||||
# Start API
|
||||
Write-Host "Starting Mindforge.API..." -ForegroundColor Cyan
|
||||
Start-Process powershell -ArgumentList "-NoExit", "-Command", "dotnet run --project Mindforge.API"
|
||||
|
||||
# Start Web
|
||||
Write-Host "Starting Mindforge.Web..." -ForegroundColor Cyan
|
||||
Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd Mindforge.Web; npm run dev"
|
||||
|
||||
Write-Host "Both projects are starting in separate windows." -ForegroundColor Green
|
||||
19
dev.sh
19
dev.sh
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Function to handle script termination
|
||||
cleanup() {
|
||||
echo "Shutting down..."
|
||||
kill $(jobs -p)
|
||||
exit
|
||||
}
|
||||
|
||||
trap cleanup SIGINT SIGTERM
|
||||
|
||||
echo "Starting Mindforge.API..."
|
||||
(cd Mindforge.API && dotnet run) &
|
||||
|
||||
echo "Starting Mindforge.Web..."
|
||||
(cd Mindforge.Web && npm run dev) &
|
||||
|
||||
echo "Both projects are running. Press Ctrl+C to stop both."
|
||||
wait
|
||||
@@ -1,10 +1,11 @@
|
||||
# Mindforge.Cronjob
|
||||
The project is called Mindforge.Cronjob, it's a small part of a bigger project called **Mindforge**.
|
||||
|
||||
The main purpose of it is to create small summaries on `.md` documents in Brazilian Portuguese language using AI API calls.
|
||||
O projeto se chama Mindforge.Cronjob e faz parte de um projeto maior chamado **Mindforge**.
|
||||
|
||||
## How it works
|
||||
O objetivo principal dele é criar pequenos resumos de documentos `.md` em português brasileiro usando chamadas de API de IA.
|
||||
|
||||
This project will fetch all the changes in a Git repository from the last 7 days, and will create a summary of all the changes in a single `.md` file.
|
||||
## Como funciona
|
||||
|
||||
It will use either Gemini or ChatGPT API to create the summary.
|
||||
Este projeto busca todas as alterações em um repositório Git dos últimos 7 dias e cria um resumo de todas as mudanças em um único arquivo `.md`.
|
||||
|
||||
Ele usa a API do Gemini ou do ChatGPT para gerar o resumo.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Deploy
|
||||
# Implantação
|
||||
|
||||
## Setup environment
|
||||
## Configuração do ambiente
|
||||
|
||||
```bash
|
||||
kubectl create ns mindforge
|
||||
@@ -13,8 +13,8 @@ kubectl create secret generic mindforge-secrets -n mindforge \
|
||||
--from-literal=SSH_PRIVATE_KEY="your_ssh_private_key"
|
||||
```
|
||||
|
||||
## Deployment itself
|
||||
## Implantação
|
||||
|
||||
```bash
|
||||
kubectl apply -f mindforge-cronjob.yaml
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
# Mindforge
|
||||
|
||||
## Visao Geral (Overview)
|
||||
## Visão Geral
|
||||
|
||||
Mindforge e uma ferramenta de estudo para auxiliar na preparacao para concursos publicos brasileiros. O sistema permite validar e gerar materiais de estudo a partir de arquivos Markdown hospedados em repositorios Git, utilizando IA (OpenRouter/OpenAI-compatible API) para processamento.
|
||||
Mindforge é uma ferramenta de estudo para auxiliar na preparação para concursos públicos brasileiros. O sistema permite validar e gerar materiais de estudo a partir de arquivos Markdown hospedados em repositórios Git, utilizando IA (API compatível com OpenRouter/OpenAI) para processamento.
|
||||
|
||||
A interface e em **portugues brasileiro** e possui um tema escuro com efeito vidro ("glassy-look").
|
||||
A interface é em **português brasileiro** e possui um tema escuro com efeito vidro ("glassy-look").
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
## Stack Tecnológica
|
||||
|
||||
### Frontend (Mindforge.Web)
|
||||
| Tecnologia | Versao | Finalidade |
|
||||
| Tecnologia | Versão | Finalidade |
|
||||
|---|---|---|
|
||||
| **Preact** | ^10.29.0 | UI library (lightweight React alternative) |
|
||||
| **Vite** | ^8.0.1 | Build tool e dev server |
|
||||
| **TypeScript** | ~5.9.3 | Tipagem estatica |
|
||||
| **marked** | ^17.0.4 | Renderizacao Markdown -> HTML |
|
||||
| **Preact** | ^10.29.0 | Biblioteca de interface (alternativa leve ao React) |
|
||||
| **Vite** | ^8.0.1 | Ferramenta de build e servidor de desenvolvimento |
|
||||
| **TypeScript** | ~5.9.3 | Tipagem estática |
|
||||
| **marked** | ^17.0.4 | Renderização Markdown -> HTML |
|
||||
| **diff** | ^8.0.3 | Diff de texto (word-level) |
|
||||
| **Google Fonts (Lato)** | 300/400/700 | Tipografia da interface |
|
||||
|
||||
### Backend API (Mindforge.API)
|
||||
| Tecnologia | Versao | Finalidade |
|
||||
| Tecnologia | Versão | Finalidade |
|
||||
|---|---|---|
|
||||
| **.NET 9** | net9.0 | ASP.NET Core Web API |
|
||||
| **C#** | - | Linguagem |
|
||||
| **Microsoft.AspNetCore.OpenApi** | 9.0.12 | Suporte OpenAPI/Swagger |
|
||||
| **Dapper** | 2.1.66 | Acesso a dados do domínio de flashcards |
|
||||
| **Npgsql** | 9.0.4 | Driver PostgreSQL para persistência de flashcards |
|
||||
|
||||
### Cronjob (mindforge.cronjob)
|
||||
| Tecnologia | Versao | Finalidade |
|
||||
| Tecnologia | Versão | Finalidade |
|
||||
|---|---|---|
|
||||
| **Go** | 1.22 | Linguagem |
|
||||
| **godotenv** | v1.5.1 | Carregamento de arquivos .env |
|
||||
@@ -41,163 +43,37 @@ A interface e em **portugues brasileiro** e possui um tema escuro com efeito vid
|
||||
| **Gitea** | Git hosting + Container registry (`git.ivanch.me`) |
|
||||
| **Gitea Actions** | CI/CD (build & deploy no push para main) |
|
||||
| **Nginx Ingress** | K8s ingress controller |
|
||||
| **OpenRouter API** | Provedor LLM (endpoint OpenAI-compatible) |
|
||||
| **OpenRouter API** | Provedor LLM (endpoint compatível com OpenAI) |
|
||||
|
||||
---
|
||||
|
||||
## Arquitetura (Architecture)
|
||||
## Arquitetura
|
||||
|
||||
O projeto e um **monorepo** com tres servicos independentes e deployaveis separadamente.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Kubernetes Cluster │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
|
||||
│ │ mindforge-web │ │ mindforge-api│ │ cronjob │ │
|
||||
│ │ (Preact SPA) │──│ (.NET 9 API) │ │ (Go app) │ │
|
||||
│ │ port 80 │ │ port 8080 │ │ (weekly) │ │
|
||||
│ └──────────────┘ └──────┬───────┘ └─────┬─────┘ │
|
||||
│ │ │ │ │
|
||||
│ mindforge.haven api.mindforge.haven │ │
|
||||
└──────────────────────────┼─────────────────┼───────┘
|
||||
│ │
|
||||
┌──────┴───────┐ ┌──────┴───────┐
|
||||
│ OpenRouter │ │ Gitea │
|
||||
│ (OpenAI API)│ │ (Git repos) │
|
||||
└──────────────┘ └──────┬───────┘
|
||||
│
|
||||
┌────────┴────────┐
|
||||
│ Discord │
|
||||
│ Webhooks │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### Servicos
|
||||
|
||||
#### 1. Mindforge.Web (Frontend)
|
||||
- **Tipo**: Single Page Application (SPA)
|
||||
- **Funcao**: Interface do usuario para validacao de arquivos e geracao de flashcards
|
||||
- **Modulos**: Home, Verificador, Flashcards
|
||||
- **Roteamento**: State-based manual via `useState` (nao usa react-router). Componentes sao alternados com `display: block/none`.
|
||||
- **Estado**: Apenas `useState`/`useEffect` locais. Sem store global, sem Context API.
|
||||
|
||||
#### 2. Mindforge.API (Backend)
|
||||
- **Tipo**: REST API
|
||||
- **Padrao arquitetural**: Clean layered architecture
|
||||
- **Controllers** -> validacao e roteamento HTTP
|
||||
- **Services** -> logica de negocio (FileService, FlashcardService, AgentService, GiteaService)
|
||||
- **Providers** -> abstracao de APIs externas (OpenAIApiProvider implementa ILlmApiProvider)
|
||||
- **Middlewares** -> cross-cutting concerns (ExceptionHandlingMiddleware)
|
||||
- **Models** -> DTOs e tipos de request/response
|
||||
- **DI**: Todos servicos e providers registrados como Scoped
|
||||
- **CORS**: Allow all origins
|
||||
- **Auth**: Nenhuma no momento
|
||||
|
||||
#### 3. Mindforge.Cronjob (Background Worker)
|
||||
- **Tipo**: Kubernetes CronJob
|
||||
- **Schedule**: Sabados as 9:00 AM
|
||||
- **Pipeline**:
|
||||
1. Clona repositorio Git via SSH
|
||||
2. Encontra arquivos modificados nos ultimos 7 dias (`.md`, exceto `Conteudos.md`)
|
||||
3. Filtra commits de "refactor" via `git log`
|
||||
4. Ranqueia por linhas alteradas, seleciona top N (default 10)
|
||||
5. Gera resumo em texto com IA para cada arquivo
|
||||
6. Formata resumo em Markdown
|
||||
7. Envia para Discord via webhook (chunked em 1800 chars)
|
||||
- **Error handling**: Reporta ao Haven Notify
|
||||
|
||||
### Decisoes de Arquitetura (Architecture Decisions)
|
||||
|
||||
1. **Sem banco de dados**: Totalmente stateless. Conteudo de estudo vive em repositorios Git, acessados via Gitea API em tempo de request.
|
||||
2. **Git como content store**: Nao ha upload de arquivos - o conteudo e lido diretamente do repositorio Git.
|
||||
3. **IA como engine de processamento**: Toda validacao e geracao e delegada ao LLM via OpenRouter.
|
||||
4. **Provider abstraction**: `ILlmApiProvider` permite trocar o backend de IA sem alterar a logica de negocio.
|
||||
5. **Monorepo com deploys independentes**: Cada servico tem seu proprio Dockerfile, manifesto K8s e pipeline CI.
|
||||
6. **Roteamento manual no frontend**: Sem lib de router, toggle de visibilidade via estado.
|
||||
7. **Preact em vez de React**: Bundle size menor.
|
||||
O projeto é um monorepo com três serviços independentes.
|
||||
- `Mindforge.Web`: SPA em Preact/Vite com navegação manual por estado e sem `react-router`.
|
||||
- `Mindforge.API`: REST API em camadas com Controllers, Services, Repositories, Providers, Middlewares e Models; o domínio de flashcards é persistido em PostgreSQL (`mindforge`) via `Dapper` + `Npgsql`, com schema criado no startup.
|
||||
- `mindforge.cronjob`: worker em Go executado semanalmente para resumir alterações recentes em arquivos `.md`.
|
||||
- Integrações principais: OpenRouter para IA, Gitea como repositório de conteúdo e Discord via webhook para notificações.
|
||||
- Deploy: cada serviço possui Dockerfile, manifesto Kubernetes e pipeline independente no Gitea Actions.
|
||||
- Decisões-chave: Git como content store, revisão espaçada calculada em leitura e Preact em vez de React.
|
||||
|
||||
---
|
||||
|
||||
## Estrutura do Projeto (Project Structure)
|
||||
## Estrutura do Projeto
|
||||
|
||||
```
|
||||
mindforge/
|
||||
├── AGENTS.md # Instrucoes para agentes AI
|
||||
├── project-context.md # Este arquivo - fonte da verdade do projeto
|
||||
├── README.md
|
||||
├── mindforge.png # Logo do projeto
|
||||
├── dev.ps1 / dev.sh # Scripts de inicializacao dev
|
||||
├── .gitea/workflows/ # CI/CD pipelines
|
||||
│ ├── mindforge-api.yaml
|
||||
│ ├── mindforge-web.yaml
|
||||
│ └── mindforge-cronjob.yaml
|
||||
│
|
||||
├── Mindforge.API/ # Backend .NET 9
|
||||
│ ├── Program.cs # Entry point: DI, CORS, middleware
|
||||
│ ├── Controllers/
|
||||
│ │ ├── FileController.cs # POST /api/v1/file/check
|
||||
│ │ ├── FlashcardController.cs # POST /api/v1/flashcard/generate
|
||||
│ │ └── RepositoryController.cs # GET /api/v1/repository/*
|
||||
│ ├── Services/ # Logica de negocio
|
||||
│ │ ├── AgentService.cs
|
||||
│ │ ├── FileService.cs
|
||||
│ │ ├── FlashcardService.cs
|
||||
│ │ ├── GiteaService.cs
|
||||
│ │ └── Interfaces/
|
||||
│ ├── Providers/
|
||||
│ │ ├── ILlmApiProvider.cs # Interface do provedor LLM
|
||||
│ │ └── OpenAIApiProvider.cs # Implementacao OpenAI/OpenRouter com retry
|
||||
│ ├── Middlewares/
|
||||
│ │ └── ExceptionHandlingMiddleware.cs
|
||||
│ ├── Models/
|
||||
│ │ ├── FileTreeNode.cs
|
||||
│ │ └── Requests/ # DTOs de request
|
||||
│ ├── Exceptions/
|
||||
│ │ └── UserException.cs # 400 Bad Request customizado
|
||||
│ └── deploy/
|
||||
│ └── mindforge-api.yaml # Manifest K8s (Deployment + Service + Ingress)
|
||||
│
|
||||
├── Mindforge.Web/ # Frontend Preact + Vite
|
||||
│ ├── vite.config.ts
|
||||
│ ├── tsconfig.app.json # Target ES2023, JSX preact, strict mode
|
||||
│ ├── .env # VITE_API_BASE_URL=http://localhost:5123
|
||||
│ ├── src/
|
||||
│ │ ├── main.tsx # Entry point
|
||||
│ │ ├── app.tsx # Componente raiz: header, sidebar, modulos
|
||||
│ │ ├── app.css # Estilos hero, animacoes
|
||||
│ │ ├── index.css # CSS variables, reset, layout base
|
||||
│ │ ├── services/
|
||||
│ │ │ └── MindforgeApiService.ts # Cliente API (fetch, interfaces tipadas)
|
||||
│ │ └── components/
|
||||
│ │ ├── Button.tsx / .css # Botao reutilizavel (primary/secondary)
|
||||
│ │ ├── Header.tsx / .css # Header fixo com logo + nome do repo
|
||||
│ │ ├── Sidebar.tsx / .css # Navegacao lateral
|
||||
│ │ ├── VerificadorComponent.tsx / .css # Validador de arquivos
|
||||
│ │ ├── FlashcardComponent.tsx / .css # Gerador de flashcards
|
||||
│ │ └── FileTreeComponent.tsx / .css # Arvore de arquivos do repo
|
||||
│ └── deploy/
|
||||
│ └── mindforge-web.yaml # Manifest K8s
|
||||
│
|
||||
└── mindforge.cronjob/ # CronJob em Go
|
||||
├── cmd/mindforge.cronjob/main.go # Entry point
|
||||
├── internal/
|
||||
│ ├── agent/agent.go # Cria e formata resumos
|
||||
│ ├── llm/ # Servico LLM
|
||||
│ ├── git/git.go # Clone, diff, SSH
|
||||
│ ├── errors/errors.go # Reporte de erros
|
||||
│ └── message/messages.go # Notificacoes Discord
|
||||
└── deploy/
|
||||
└── mindforge-cronjob.yaml # Manifest K8s CronJob
|
||||
```
|
||||
- `mindforge/`: raiz do projeto com documentação, scripts, logo e workflows do Gitea.
|
||||
- `Mindforge.API/`: backend .NET 9 com controllers, services, repositories, providers, models e deploy Kubernetes.
|
||||
- `Mindforge.Web/`: frontend Preact + Vite com componentes de interface, cliente de API e deploy Kubernetes.
|
||||
- `mindforge.cronjob/`: worker em Go com lógica de IA, Git, erros e mensagens do Discord, além do deploy Kubernetes.
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
## Endpoints da API
|
||||
|
||||
### File Controller (`/api/v1/file`)
|
||||
| Metodo | Rota | Descricao |
|
||||
### Controller de Arquivos (`/api/v1/file`)
|
||||
| Método | Rota | Descrição |
|
||||
|---|---|---|
|
||||
| POST | `/api/v1/file/check` | Valida linguagem ou conteudo de um arquivo |
|
||||
| POST | `/api/v1/file/check` | Valida a linguagem ou o conteúdo de um arquivo |
|
||||
|
||||
```json
|
||||
// Request
|
||||
@@ -213,64 +89,59 @@ mindforge/
|
||||
}
|
||||
```
|
||||
|
||||
### Flashcard Controller (`/api/v1/flashcard`)
|
||||
| Metodo | Rota | Descricao |
|
||||
### Controller de Flashcards (`/api/v1/flashcard`)
|
||||
| Método | Rota | Descrição |
|
||||
|---|---|---|
|
||||
| POST | `/api/v1/flashcard/generate` | Gera flashcards em CSV |
|
||||
| POST | `/api/v1/flashcard/generate` | Gera ou substitui bibliotecas de flashcards a partir dos arquivos selecionados |
|
||||
| GET | `/api/v1/flashcard/libraries` | Lista todas as bibliotecas persistidas |
|
||||
| GET | `/api/v1/flashcard/libraries/{id}` | Retorna uma biblioteca específica com seus cards |
|
||||
| POST | `/api/v1/flashcard/review-session` | Inicia uma sessão de revisão com bibliotecas selecionadas |
|
||||
| POST | `/api/v1/flashcard/review-answer` | Registra se a resposta do card estava correta |
|
||||
| GET | `/api/v1/flashcard/rag-status` | Retorna o dashboard de revisão espaçada por matéria/submatéria |
|
||||
|
||||
```json
|
||||
// Request
|
||||
{
|
||||
"fileContent": "string",
|
||||
"fileName": "string",
|
||||
"amount": 10,
|
||||
"mode": "Basic" | "Simple" | "Detailed" | "Hyper"
|
||||
}
|
||||
Formas de requisição principais:
|
||||
- `POST /api/v1/flashcard/generate`: `{ filePaths: string[], amount: 10-30, difficulty: "Easy" | "Hard" }`
|
||||
- `POST /api/v1/flashcard/review-session`: `{ libraryIds: number[] }`
|
||||
- `POST /api/v1/flashcard/review-answer`: `{ cardId: number, correct: boolean }`
|
||||
|
||||
// Response
|
||||
{
|
||||
"result": "string (CSV: Frente;Verso\nFrente;Verso\n...)"
|
||||
}
|
||||
```
|
||||
|
||||
### Repository Controller (`/api/v1/repository`)
|
||||
| Metodo | Rota | Descricao |
|
||||
### Controller de Repositório (`/api/v1/repository`)
|
||||
| Método | Rota | Descrição |
|
||||
|---|---|---|
|
||||
| GET | `/api/v1/repository/info` | Nome do repositorio |
|
||||
| GET | `/api/v1/repository/tree` | Arvore de arquivos do repositorio |
|
||||
| GET | `/api/v1/repository/file?path=...` | Conteudo de um arquivo especifico |
|
||||
| GET | `/api/v1/repository/info` | Nome do repositório |
|
||||
| GET | `/api/v1/repository/tree` | Árvore de arquivos do repositório |
|
||||
| GET | `/api/v1/repository/file?path=...` | Conteúdo de um arquivo específico |
|
||||
|
||||
---
|
||||
|
||||
## Convencoes de Desenvolvimento (Development Conventions)
|
||||
## Convenções de Desenvolvimento
|
||||
|
||||
### Frontend (Preact/TypeScript)
|
||||
- **Componentes**: Funcoes nomeadas exportadas com `export function Nome()`. Sem `export default`.
|
||||
- **Componentes**: Funções nomeadas exportadas com `export function Nome()`. Sem `export default`.
|
||||
- **Props**: Interfaces TypeScript definidas no mesmo arquivo do componente.
|
||||
- **Hooks**: `useState`, `useEffect` importados de `preact/hooks`.
|
||||
- **Hooks**: `useState` e `useEffect` importados de `preact/hooks`.
|
||||
- **Children**: Tipados como `ComponentChildren` de `preact`.
|
||||
- **CSS**: Um arquivo `.css` por componente, importado diretamente. **Sem CSS Modules.**
|
||||
- **Estado**: Apenas estado local (`useState`). Sem store global, sem Context API.
|
||||
- **Roteamento**: Alternancia de componentes via `display: block/none` com estado `activeModule`. Nao usa react-router.
|
||||
- **API**: Chamadas via `MindforgeApiService` (objeto singleton com metodos estaticos usando `fetch`).
|
||||
- **TypeScript**: Strict mode, `erasableSyntaxOnly`, `verbatimModuleSyntax`, `noUnusedLocals`, `noUnusedParameters`.
|
||||
- **Roteamento**: Alternância de componentes via `display: block/none` com o estado `activeModule`. Não usa `react-router`.
|
||||
- **API**: Chamadas via `MindforgeApiService` (objeto singleton com métodos estáticos usando `fetch`).
|
||||
- **TypeScript**: Modo estrito, `erasableSyntaxOnly`, `verbatimModuleSyntax`, `noUnusedLocals`, `noUnusedParameters`.
|
||||
- **Alias**: `react` e `react-dom` mapeados para `preact/compat/` no tsconfig.
|
||||
|
||||
### Backend (C#/.NET 9)
|
||||
- **Namespaces**: `Mindforge.API.Controllers`, `Mindforge.API.Services`, etc.
|
||||
- **Interfaces**: Prefixo `I` (ex: `IFileService`, `ILlmApiProvider`).
|
||||
- **DI**: Todos servicos registrados como `Scoped` em `Program.cs`.
|
||||
- **Controllers**: Atributo `[Route("api/v1/...")]`. Metodos retornam `IActionResult`.
|
||||
- **Tratamento de erros**: `ExceptionHandlingMiddleware` captura `UserException` (400) e excecoes genericas (500).
|
||||
- **Interfaces**: Prefixo `I` (ex.: `IFileService`, `ILlmApiProvider`).
|
||||
- **DI**: Todos os serviços registrados como `Scoped` em `Program.cs`.
|
||||
- **Controllers**: Atributo `[Route("api/v1/...")]`. Métodos retornam `IActionResult`.
|
||||
- **Tratamento de erros**: `ExceptionHandlingMiddleware` captura `UserException` (400) e exceções genéricas (500).
|
||||
|
||||
### UI/UX
|
||||
- **Idioma**: Todo texto em **portugues brasileiro**.
|
||||
- **Idioma**: Todo texto em **português brasileiro**.
|
||||
- **Tema**: Escuro com efeito vidro (glassy). `backdrop-filter: blur()`, fundos `rgba` semitransparentes.
|
||||
- **Botoes**: Estilo iOS-like, modernos. Variantes `primary` (com blur) e `secondary` (transparente).
|
||||
- **Botões**: Estilo iOS-like, modernos. Variantes `primary` (com blur) e `secondary` (transparente).
|
||||
- **Tipografia**: Lato (Google Fonts), pesos 300/400/700.
|
||||
- **Background**: `#005873` (azul petroleo escuro). Nao muito escuro.
|
||||
- **Background**: `#005873` (azul petróleo escuro). Não muito escuro.
|
||||
|
||||
### CSS Variables (definidas em `index.css`)
|
||||
### Variáveis CSS (definidas em `index.css`)
|
||||
```css
|
||||
--color-bg: #005873;
|
||||
--color-header: #0f0f0f;
|
||||
@@ -283,129 +154,49 @@ mindforge/
|
||||
```
|
||||
|
||||
### Git
|
||||
- Branches: `main` (producao)
|
||||
- CI/CD: Gitea Actions dispara no push para main, build com Docker Buildx multi-arch, push para Gitea Container Registry, deploy no K8s.
|
||||
- Branches: `main` (produção)
|
||||
- CI/CD: Gitea Actions dispara no push para `main`, faz build com Docker Buildx multi-arch, envia para o Gitea Container Registry e faz o deploy no K8s.
|
||||
|
||||
---
|
||||
|
||||
## Configuracao & Environment Variables
|
||||
## Configuração e Variáveis de Ambiente
|
||||
|
||||
### API (Mindforge.API)
|
||||
| Variavel | Descricao |
|
||||
| Variável | Descrição |
|
||||
|---|---|
|
||||
| `OPENAI_API_URL` | URL do endpoint OpenAI-compatible (OpenRouter) |
|
||||
| `OPENAI_TOKEN` | Token de autenticacao da API |
|
||||
| `OPENAI_API_URL` | URL do endpoint compatível com OpenAI (OpenRouter) |
|
||||
| `OPENAI_TOKEN` | Token de autenticação da API |
|
||||
| `OPENAI_MODEL` | Modelo LLM a ser usado |
|
||||
| `GITEA_REPO_URL` | URL do repositorio Gitea |
|
||||
| `GITEA_REPO_URL` | URL do repositório Gitea |
|
||||
| `GITEA_ACCESS_TOKEN` | Token de acesso ao Gitea |
|
||||
| `ConnectionStrings:MindforgeDb` | Conexão PostgreSQL usada pelo domínio de flashcards |
|
||||
|
||||
Fallback local/padrão para o banco de flashcards:
|
||||
`Host=localhost;Port=3307;Database=mindforge;Username=root;Password=root`.
|
||||
|
||||
### Web (Mindforge.Web)
|
||||
| Variavel | Descricao |
|
||||
| Variável | Descrição |
|
||||
|---|---|
|
||||
| `VITE_API_BASE_URL` | URL base da API (default: `http://localhost:5123`) |
|
||||
| `VITE_API_BASE_URL` | URL base da API (padrão: `http://localhost:5123`) |
|
||||
|
||||
### Cronjob
|
||||
| Variavel | Descricao |
|
||||
| Variável | Descrição |
|
||||
|---|---|
|
||||
| `GIT_REPOSITORY` | URL do repo Git a clonar |
|
||||
| `DISCORD_WEBHOOK_URL` | Webhook do Discord para notificacoes |
|
||||
| `GIT_REPOSITORY` | URL do repositório Git a clonar |
|
||||
| `DISCORD_WEBHOOK_URL` | Webhook do Discord para notificações |
|
||||
| `OPENAI_API_URL` | URL do endpoint OpenAI |
|
||||
| `OPENAI_TOKEN` | Token de autenticacao |
|
||||
| `HAVEN_NOTIFY_URL` | URL do servico de reporte de erros |
|
||||
| `OPENAI_TOKEN` | Token de autenticação |
|
||||
| `HAVEN_NOTIFY_URL` | URL do serviço de reporte de erros |
|
||||
|
||||
## Repositório base para os arquivos
|
||||
A base do repositório para os arquivos de estudo (compartilhado pelo Obsidian) é https://git.ivanch.me/ivanch/concurso.
|
||||
Ele segue o padrão `[base]/concurso/[Matéria]/[SubMatéria*]/[Arquivo]`, onde [base] é a URL do git, concurso é o nome da pasta dentro do git base, Matéria é o nome da matéria (ex: `Direito Constitucional`), SubMatéria é o nome da submatéria (ex. `Poder Legislativo`) - podendo ser opcional e com múltiplas submatérias -, e Arquivo é o nome do arquivo (ex: `Câmara dos Deputados.md`).
|
||||
Ele segue o padrão `[base]/concurso/[Matéria]/[SubMatéria*]/[Arquivo]`, onde [base] é a URL do Git, `concurso` é o nome da pasta dentro do Git base, `Matéria` é o nome da matéria (ex.: `Direito Constitucional`), `SubMatéria` é o nome da submatéria (ex.: `Poder Legislativo`) - podendo ser opcional e com múltiplas submatérias - e `Arquivo` é o nome do arquivo (ex.: `Câmara dos Deputados.md`).
|
||||
|
||||
Exemplos:
|
||||
- [base]/Concursos/Direito Constitucional/Poder Legislativo/Câmara dos Deputados.md
|
||||
- [base]/Concursos/Direito Constitucional/Poder Legislativo/CPIs.md
|
||||
- [base]/Concursos/Direito Constitucional/Ciência, Meio Ambiente e Índios.md
|
||||
- [base]/Concursos/Direito Constitucional/Ciência, Meio Ambiente e Índios.md
|
||||
- [base]/Concursos/TI/Analise e Engenharia de Dados/Data Lake e Data Warehouse.md
|
||||
- [base]/Concursos/TI/Análise e Engenharia de Dados/Data Lake e Data Warehouse.md
|
||||
- [base]/Concursos/TI/Rede/VLAN.md
|
||||
- [base]/Concursos/TI/Rede/Email/IMAP e POP3.md
|
||||
|
||||
---
|
||||
|
||||
## Atualizacao - Flashcards Persistidos (2026-05-30)
|
||||
|
||||
### Mudancas de Arquitetura
|
||||
- A API deixa de ser totalmente stateless para o dominio de flashcards.
|
||||
- Flashcards agora sao persistidos em PostgreSQL (`mindforge`) via `Dapper` + `Npgsql`.
|
||||
- O schema e criado de forma idempotente no startup da API.
|
||||
|
||||
### Tabelas de Flashcard
|
||||
- `flashcard_libraries`: `id`, `file_path` (unico), `file_name`, `subject`, `difficulty`, `card_count`, `created_at`, `updated_at`.
|
||||
- `flashcards`: `id`, `library_id`, `front`, `back`, `position`, `correct_count`, `incorrect_count`, `last_reviewed_at`, `created_at`.
|
||||
|
||||
### API de Flashcards (v1)
|
||||
- `POST /api/v1/flashcard/generate`
|
||||
Request: `{ filePaths: string[], amount: 10-30, difficulty: "Easy" | "Hard" }`
|
||||
Comportamento: gera por arquivo selecionado, substitui biblioteca anterior do mesmo `file_path` e retorna bibliotecas com cards.
|
||||
- `GET /api/v1/flashcard/libraries`
|
||||
Lista todas as bibliotecas persistidas, com `subject` para agrupamento na UI.
|
||||
- `GET /api/v1/flashcard/libraries/{id}`
|
||||
Retorna detalhes de uma biblioteca com seus cards.
|
||||
- `POST /api/v1/flashcard/review-session`
|
||||
Request: `{ libraryIds: number[] }`
|
||||
Retorna os cards combinados para sessao de revisao (sem repeticao espaciada nesta fase).
|
||||
- `POST /api/v1/flashcard/review-answer`
|
||||
Request: `{ cardId: number, correct: boolean }`
|
||||
Registra no banco o resultado da revisao (`Acertei`/`Errei`) por card.
|
||||
|
||||
### Frontend
|
||||
- Modulo `Flashcards` atualizado para:
|
||||
- selecionar multiplos arquivos;
|
||||
- definir quantidade fixa por arquivo (10-30);
|
||||
- definir dificuldade (`Facil`/`Dificil`);
|
||||
- gerar e exibir resumo das bibliotecas salvas (sem download CSV).
|
||||
- Novo modulo `Revisao Flashcards`:
|
||||
- lista bibliotecas agrupadas por materia (`subject`);
|
||||
- permite selecionar multiplas bibliotecas;
|
||||
- embaralha aleatoriamente os cards ao iniciar a sessao de revisao;
|
||||
- inicia sessao estilo Anki simplificada (frente, revelar verso, acertei/errei, anterior, progresso visual).
|
||||
- ao gerar novamente uma biblioteca, os contadores `correct_count` e `incorrect_count` dos cards sao resetados para zero.
|
||||
|
||||
### Novas Configuracoes
|
||||
- `ConnectionStrings:MindforgeDb` para conexao PostgreSQL.
|
||||
- Fallback local/default:
|
||||
`Host=localhost;Port=3307;Database=mindforge;Username=root;Password=root`.
|
||||
|
||||
---
|
||||
|
||||
## Atualizacao - Revisao Espacada RAG (2026-06-01)
|
||||
|
||||
### Mudancas de Arquitetura
|
||||
- O dominio de flashcards guarda `last_reviewed_at` por card.
|
||||
- O status RAG da revisao espacada e calculado em tempo de leitura **por biblioteca/arquivo** (grupo de cards), nao por card.
|
||||
- O agrupamento de dashboard usa `subject` + `subSubject`, onde `subSubject` vem dos segmentos do caminho apos a materia e antes do arquivo.
|
||||
|
||||
### Regras RAG por Arquivo (biblioteca)
|
||||
- `Grey`: nenhum card da biblioteca possui `last_reviewed_at`.
|
||||
- `Red`: ultima revisao da biblioteca ha 40 dias ou mais **ou** desempenho agregado `< 40%`.
|
||||
- `Amber`: ultima revisao da biblioteca ha 30 dias ou mais **ou** desempenho agregado `<= 60%`.
|
||||
- `Green`: ultima revisao da biblioteca abaixo de 30 dias **e** desempenho agregado `> 60%`.
|
||||
- Desempenho agregado: `sum(correct_count) / (sum(correct_count) + sum(incorrect_count))`.
|
||||
|
||||
### Banco e Repositorio
|
||||
- Tabela `flashcards` recebeu coluna `last_reviewed_at TIMESTAMPTZ NULL` (migracao idempotente no startup).
|
||||
- `POST /api/v1/flashcard/review-answer` agora atualiza `correct_count`/`incorrect_count` e define `last_reviewed_at = NOW()`.
|
||||
|
||||
### API de Flashcards (v1)
|
||||
- Novo endpoint `GET /api/v1/flashcard/rag-status`:
|
||||
- Retorna dashboard de revisao espacada com grupos por materia/submateria.
|
||||
- Inclui bibliotecas/arquivos com `ragStatus`, `performanceRate`, `totalAnswers` e `lastReviewedAt`.
|
||||
- Inclui sumarios por materia/submateria com percentuais:
|
||||
- Verde = `green / (green + amber + red)`
|
||||
- Atencao = `(amber + red) / (green + amber + red)`
|
||||
- Arquivos cinza ficam fora do denominador.
|
||||
|
||||
### Frontend
|
||||
- Novo modulo `Revisao Espacada` abaixo de `Revisao Flashcards` na sidebar.
|
||||
- O painel mostra:
|
||||
- status agregados por materia e submateria;
|
||||
- status por arquivo com destaque visual (cores e icones);
|
||||
- filtros por status RAG (Vermelho, Amarelo, Verde, Cinza);
|
||||
- total de arquivos selecionados para revisao.
|
||||
- A sessao de revisao espacada reutiliza o fluxo de resposta (`Acertei`/`Errei`) e prioriza cards de arquivos por status (Red, Amber, Green, Grey).
|
||||
- [base]/Concursos/TI/Rede/E-mail/IMAP e POP3.md
|
||||
|
||||
12
re-deploy.ps1
Normal file
12
re-deploy.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# Exit on any error
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
docker login git.ivanch.me
|
||||
|
||||
Write-Host "Building and pushing Docker images..."
|
||||
docker buildx bake --set '*.platform=linux/amd64,linux/arm64' --push
|
||||
|
||||
Write-Host "Build and push completed successfully."
|
||||
|
||||
kubectl delete -f ./deploy/deployment.yaml
|
||||
kubectl apply -f ./deploy/deployment.yaml
|
||||
Reference in New Issue
Block a user