Spaces:
Sleeping
Sleeping
Commit History
-
feat: add in-app Guide page with 8 sections (IT/EN)
Fabio Antonini +1: Claude Sonnet 4.6Implements the Help/Guida page accessible from the user dropdown menu. Includes Quick Start, Features, AI Models, Agent Command Examples, FAQ, Glossary, Requirements and Privacy sections — fully bilingual via i18next. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>401e56e -
feat: move language toggle into Settings dialog
Fabio Antonini +1: Claude Sonnet 4.6Language switch moved from the sidebar dropdown menu into the Settings modal, below the OpenAI key section — keeps the dropdown lean and groups all preferences in one place. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>13c1698 -
feat: ChatGPT-style sidebar footer with Settings dialog
Fabio Antonini +1: Claude Sonnet 4.6- Replace bottom config section with a user avatar + name button that opens a dropdown menu (Impostazioni, Guida, lingua, Esci) - Extract all model/key configuration into a new SettingsDialog modal - Add Dialog shadcn component wrapping @radix-ui/react-dialog - Add nav.settings and nav.help i18n keys (it/en) - Sidebar is now cleaner; config is accessible via Impostazioni Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>de10826 -
feat: per-user OpenAI key + model preferences persisted in DB
Fabio Antonini +1: Claude Sonnet 4.6- UserSettings table stores encrypted OpenAI key (Fernet) and last-selected models (rag, vlm, ocr, embed) per user - ContextVar propagates the user's decrypted key to all core modules without changing function signatures; global OPENAI_API_KEY env var as fallback - set_openai_context FastAPI dependency injected in rag, compliance, agent routers - GET/PUT /users/me/settings and PATCH /users/me/settings/models endpoints - DELETE /users/me/settings/openai-key to revoke personal key - Sidebar restores saved model selections on login and persists changes - Inline DB migration in init_db() adds new columns to existing user_settings table - docker-compose: OPENAI_API_KEY and SETTINGS_ENCRYPTION_KEY passed as env vars - Remove PUT /rag/openai-key (global key is env-only, never written to file) - Sidebar: uppercase removed from section headers; "Configurazione" now title-case Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>413c3b1 -
feat: add OpenAI API support (gpt-5.4 family) alongside Ollama
Fabio Antonini +1: Claude Sonnet 4.6- New core/providers.py: provider abstraction layer with model detection, OpenAI client factory, API key management and model catalogue - core/rag.py: provider-aware _embed()/_embed_batch()/stream_llm() wrappers; set_embed_model() with NPZ cache invalidation on provider switch - core/compliance.py, ocr.py, document_layout.py, agent.py: OpenAI branches for all LLM/VLM call sites; max_tokens → max_completion_tokens for gpt-5.4 - core/pipeline.py: Step 7 title shows active provider and model name - backend: new /rag/openai-key and /rag/embed-model endpoints; /rag/status returns OpenAI model lists when key is configured - frontend: Sidebar dropdowns use <optgroup> Ollama/OpenAI; OpenAI key UI; embedding model selector; i18n keys for en/it Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f1196cf
-
feat: add Conformità ENFSI as agent tool with inline report and PDF download
Fabio Antonini +1: Claude Sonnet 4.6- Add verifica_conformita_enfsi @tool in core/agent.py: runs compliance_check_stream, embeds structured data as HTML comment marker in tool output - Extract shared ComplianceReport.tsx component (StructuredReport, ReqCard, StatCard, parseComplianceMarker, ComplianceDownloadButton) from CompliancePage - Render structured ENFSI report + PDF download button inline in agent chat (AgentPage and AgentProjectPage detect the marker after streaming ends) - Fix OCR spam on structured PDFs: extract_perizia_text skips EasyOCR unless total extracted text is under 200 chars (scanned document heuristic) - Emit immediate yield at agent start to exit frontend loading state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>9124e72 -
fix: render NER table correctly in agent chat
Fabio Antonini +1: Claude Sonnet 4.6- core/agent.py: extract markdown tables from tool results verbatim and append to final response, bypassing the LLM which collapses newlines; strip mangled pipe-rows from LLM answer when clean tables are available; add remarkGfm-compatible _extract_tables() helper - frontend/AgentProjectPage.tsx: enable remark-gfm plugin on ReactMarkdown so markdown tables are rendered as HTML tables (was missing, all tables rendered as plain text) - backend/routers/agent.py: improve project context note to prevent LLM from using bare filenames as paths Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>167611e -
fix: agent session isolation, audit rollback, persistent images, legacy endpoint
Fabio Antonini +1: Claude Sonnet 4.6- core/agent.py: use UUID session subfolder for temp files; keep original filenames so the LLM knows which file is which; clean up in finally block - core/document_layout.py: drop LayoutDetection entirely, use PPStructure directly (PaddleOCR 3.x on Windows — LayoutDetection broken due to oneDNN) - backend/audit.py: rollback session after flush error to avoid PendingRollbackError on subsequent ORM calls (was causing 500 on doc delete) - backend/routers/agent.py: GET /agent/images/{filename} serves persistent agent images from data/uploads/agent/images/; GET /agent/temp-image/ returns 410 Gone with cache header to stop browser retrying old URLs - frontend/src/pages/AgentProjectPage.tsx: refresh document list immediately after POST /agent/chat (before streaming ends) so uploaded files appear in the panel without waiting for the full agent response Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>3559e28 -
fix: sidebar UX — move Projects under Agent, remove duplicate + in New chat
Fabio Antonini +1: Claude Sonnet 4.6- Rename nav.agent_projects to "Projects" / "Progetti" (shorter label) - Move the Projects collapsible section directly below the Agente Documentale link instead of at the bottom of the nav - Remove leading "+ " from agent.new_chat i18n keys — the button already renders a Plus icon, causing a double "+" in the UI Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>ad2e396
-
feat: agent projects with persistent chats and reusable documents
Fabio Antonini +1: Claude Sonnet 4.6- Add AgentChat and AgentMessage models (cascade delete from Project) - Extend /agent/chat to persist messages and save uploads to MinIO - New endpoints: agent projects, chats, documents CRUD - New AgentProjectPage: 3-column layout (chat list / chat / documents) - Sidebar: Agent Projects section with inline project creation - Documents panel: click to reuse without re-uploading - i18n: new keys for agent project UI (EN + IT) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f9c4034 -
fix: dropdown menu opaque background and auto-positioning
Fabio Antonini +1: Claude Sonnet 4.6- Replace bg-popover (transparent) with bg-white/dark:bg-zinc-900 so menu covers underlying chat content like ChatGPT - Remove side="top" so Radix auto-positions with collision detection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>8d5cc38 -
feat: add ChatGPT-style '+' actions menu with multi-prompt selection
Fabio Antonini +1: Claude Sonnet 4.6- New dropdown-menu.tsx UI component (Radix UI wrapper) - Replace paperclip button with '+' menu: attach files, new conversation - Prompts section in menu (visible when file attached): toggle multi-select with checkmark - Selected prompts appear as removable chips above textarea - Multiple prompts concatenated and sent together to the agent - Live streaming activity log shows tool calls in real time before final answer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>4d5407b -
fix: replace hardcoded strings with i18n keys
Fabio Antonini +1: Claude Sonnet 4.6- AdminPage.tsx: use t("auth.password") instead of hardcoded "Password" - ProjectDetailPage.tsx: use t("project.image_alt") instead of hardcoded "Immagine annotata" - i18n: add project.image_alt key to it.json and en.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>de40856 -
feat: show extracted signature image inline in agent chat
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/agent.py: add GET /agent/temp-image/{filename} endpoint to serve files from %TEMP%/gl/ with JWT auth and path traversal protection - core/agent.py: rileva_firma tool saves crop to gl/firma_estratta.png and returns markdown image syntax; agent_stream extracts image markdown from tool results and injects into final answer; fix: import re inside stream - frontend/src/pages/AgentPage.tsx: add AuthImage component (JWT-authenticated blob URL); wire as ReactMarkdown img renderer; fix SSE line buffer to avoid losing chunks split across read() calls (restores tool log dropdown) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>390c120 -
feat: delete single analysis artefact in Perizie page
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/analysis.py: add DELETE /analysis/{id} endpoint with project access check and audit log - frontend/src/lib/api.ts: add analysisApi.deleteOne() - frontend/src/pages/ProjectDetailPage.tsx: add Trash2 button to each AnalysisCard (red on hover), handleDeleteAnalysis() removes from local state without full reload - i18n: add delete_analysis key (it/en) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a617713 -
feat: separate LLM and VLM model slots + fix agent OCR model routing
Fabio Antonini +1: Claude Sonnet 4.6- core/rag.py: separate _rag_model (text, default qwen3:4b) from _vlm_model (vision, default qwen3-vl:8b); add get/set_vlm_model + _persist_vlm_model_to_env; load both from .env at startup via _load_model_from_env() - core/agent.py: AGENT_MODEL = qwen3:4b (was qwen3-vl:8b); trascrivi_documento now uses htr_transcribe() respecting OCR model selector instead of hardcoded VLM - core/document_layout.py: _get_active_model() reads _vlm_model instead of _rag_model - core/ocr.py: _vlm_transcribe() reads _vlm_model instead of _rag_model - backend/routers/rag.py: add GET/PUT /rag/vlm-model endpoints - frontend: add VLM model selector in sidebar (Sidebar.tsx, api.ts, i18n) - backend/config.py + .env.example: add vlm_model field, update defaults - README.md: document three model slots (LLM/VLM/OCR) with GPU impact table Result: text-only tasks (transcribe+NER+dating with OCR=easyocr) use only qwen3:4b; qwen3-vl:8b is loaded only for image analysis (table/figure/vlm-ocr). Co-Authored-By: Cl…3c9c028 -
feat: Agente Documentale LangChain + OCR selector + stop + SQLite WAL
Fabio Antonini +1: Claude Sonnet 4.6- core/agent.py: LangChain agent con 10 tool forensi (OCR, NER, firma, grafologia, scrittore, datazione, layout, RAG), streaming SSE, stop via threading.Event, short-path workaround per path truncation LLM - core/document_layout.py: wrapper PaddleOCR lazy-loaded con call_vision_model streaming (timeout=(10,300), stream=True) - backend/routers/agent.py: endpoint POST /agent/chat (SSE), GET /agent/status, GET /agent/prompts; cancellazione via GeneratorExit → stop_event - frontend/src/pages/AgentPage.tsx: chat page stile ChatGPT con upload file, streaming SSE, badge azioni tool collassabili, Stop button (AbortController) - core/ocr.py: selettore modello OCR (easyocr/vlm/paddleocr/trocr), persistenza .env, _vlm_transcribe streaming, EasyOCR senza preprocessing - backend/routers/rag.py: GET/PUT /rag/ocr-model endpoints - frontend/src/components/layout/Sidebar.tsx: dropdown OCR model in sidebar - backend/database.py: SQLite WAL mode + busy_timeout=10000 via event listener - core/…e1f6f2b
-
feat: compliance PDF export + UI structured report
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/compliance.py: POST /compliance/pdf generates a 4-page PDF with stat boxes, proportional score bar, judgment banner, summary table and per-REQ detail cards with colored left bar and suggestion boxes; adaptive colophon positioning - frontend: CompliancePage fully rewritten — streaming shows rendered markdown, on completion parses verdicts and renders structured cards with stat panels, filter tabs (Tutti/Conformi/Parziali/Mancanti), per-REQ cards with color-coded borders and lightbulb suggestions, and a Download PDF button - api.ts: complianceApi.pdf() method - i18n: compliance.download_pdf key (it/en) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>723e81b -
feat: ENFSI compliance checker + sidebar model selector
Fabio Antonini +1: Claude Sonnet 4.6- core/compliance.py: new module with 20-item ENFSI BPM checklist, streaming Ollama analysis (system/prompt separation, num_ctx=16384, /no_think for qwen3), and Python-side deterministic summary parsing (verdicts extracted via regex → counts/grid always correct) - backend/routers/compliance.py: POST /compliance/check (PDF upload → SSE) and GET /compliance/status - backend/routers/rag.py: GET /rag/model and PUT /rag/model endpoints for runtime model selection - frontend: CompliancePage, Sidebar configurazione section with model selector dropdown and refresh button, i18n keys (it/en) - docker-compose.yml: add GPU passthrough to ollama service - requirements.txt: add CUDA 12.1 extra-index-url for PyTorch GPU wheels Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>c23bac8
-
fix: RAG chat fully functional in FastAPI backend
Fabio Antonini +1: Claude Sonnet 4.6- backend/main.py: launch rag_load_docs in background thread at startup so _rag_ready becomes True - backend/routers/rag.py: fix history schema (list[dict] with role/content), JSON-encode SSE payloads to handle embedded newlines, combine partial+sources_footer in one event (mirrors Gradio wrapper) - core/rag.py: increase retrieval top-k from 2 to 5 user chunks for better recall on sparse mentions; switch embed model to nomic-embed-text; add keep_alive to Ollama calls - frontend/src/pages/RagPage.tsx: read auth token via getState() (not stale React state), send history as [{role,content}], JSON.parse SSE data, fix assistantText = (not +=) since stream yields full accumulated text Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>1355325 -
fix: rag_doc_list() call signature and frontend Docker npm install
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/rag.py: rag_doc_list() takes no args and returns [[name, count]] rows, not dicts — fixed call and response mapping - frontend/Dockerfile: switch npm ci → npm install to handle platform-specific deps missing from Windows-generated lockfile Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>905b464 -
feat: persist language preference in localStorage
Fabio Antonini +1: Claude Sonnet 4.6i18n detection order: localStorage → navigator. Key: grapholab_lang. Survives page refresh. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>4cc2a5b -
feat: password reset via admin (no SMTP required)
Fabio Antonini +1: Claude Sonnet 4.6Backend: - auth/jwt.py: add TokenType.reset + create_reset_token() (24h) - routers/auth.py: POST /auth/reset-password/generate (admin only) and POST /auth/reset-password/confirm (public) - models/audit.py: add password_reset_generate / password_reset_confirm actions Frontend: - ResetPasswordPage.tsx: new public page at /reset-password?token=xxx - AdminPage.tsx: KeyRound button per user → modal with copyable reset link - App.tsx: add /reset-password route - api.ts: authApi.generateResetToken() + authApi.confirmReset() - i18n/it.json + en.json: all new strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f4fd404
-
feat: immutable audit log for forensic chain-of-custody
Fabio Antonini +1: Claude Sonnet 4.6Backend: - AuditLog model (append-only, no UPDATE/DELETE) with action enum, user snapshot, resource type/id, detail, ip_address - log_event() helper — silently swallows errors so logging never breaks the main request flow - Integrated in all key endpoints: login, project create/delete, document upload/delete, all analysis types, PDF download, clear analyses - GET /audit/ (admin only) with filters by action and user email, pagination (page/page_size) Frontend: - AdminPage with two tabs: Users and Activity Log - Audit tab: filter by action and email, paginated table with color-coded action badges, timestamp, user, resource, detail, IP - auditApi in api.ts - i18n keys for audit log (IT + EN) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b59af0d -
feat: PDF report with images, formatted tables and clean layout
Fabio Antonini +1: Claude Sonnet 4.6- Embed pipeline images (sig detection, graphology) via _download_sync - Render markdown tables as proper PDF cells with borders and striped rows - Fix title/date layout with explicit vertical spacing - Skip duplicate H2 title already rendered as page header - Strip orphaned asterisks left by LLM bold patterns (**label**: style) - Add PDF download button on pipeline analysis cards - Add fpdf2 to requirements-backend.txt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>4e50c56 -
fix: keep first document selected after subsequent uploads
Fabio Antonini +1: Claude Sonnet 4.6Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b96954d -
feat: optional reference signature for full forensic pipeline
Fabio Antonini +1: Claude Sonnet 4.6- Backend: PipelineRequest with optional reference_document_id - Backend: load and pass ref_sig image to run_pipeline_steps when provided - Frontend: picker modal before running pipeline (skip or select reference doc) - i18n: add pipeline_ref_* keys in it/en Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>0bd285f -
feat: pipeline images, markdown rendering and running spinner
Fabio Antonini +1: Claude Sonnet 4.6- Pipeline: save sig_detect and grapho images, embed as authenticated inline images in report - Add GET /analysis/{id}/image/{slot} endpoint for pipeline image slots - Frontend: AuthImage component fetches images with JWT token - ReactMarkdown with remark-gfm renders tables and inline images - Loader2 spinner on active analysis button Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>86766f3 -
feat: show annotated images in analysis cards with markdown rendering
Fabio Antonini +1: Claude Sonnet 4.6- Save annotated image to storage for signature-detection and graphology - Add GET /analysis/{id}/image endpoint (JWT-authenticated) - Frontend: fetch image via axios (with auth token) and render as blob URL - Render result_text as markdown with remark-gfm for table support - Add upload_fileobj import to analysis router Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>5b1ac36 -
feat: add Clear analyses button to project detail page
Fabio Antonini +1: Claude Sonnet 4.6- Backend: DELETE /analysis/project/{project_id} endpoint - Frontend: Cancella analisi button with confirm dialog (visible only when analyses exist) - i18n: add clear_analyses and clear_analyses_confirm keys in it/en Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>01c12ca
-
chore: gitignore local dev artifacts and add utils.ts
Fabio Antonini +1: Claude Sonnet 4.6- Ignore data/uploads/ (MinIO local fallback) and grapholab_dev.db - Add frontend/src/lib/utils.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>47887c5 -
feat: signature verification UI and analysis route fixes
Fabio Antonini +1: Claude Sonnet 4.6- Add reference document picker modal for signature verification - Fix writer_identification path mapping (backend uses /writer not /writer-identification) - Add missing common.cancel translation in it/en Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>818c0d8 -
fix: local dev storage fallback and analysis URL normalization
Fabio Antonini +1: Claude Sonnet 4.6- minio_client: fall back to data/uploads/ filesystem when MinIO unreachable - api.ts: normalize analysis type underscores to hyphens to match backend routes - .gitignore: exempt frontend/src/lib/ from Python lib/ exclusion rule Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>c8c71aa -
fix: resolve local dev issues found during first test run
Fabio Antonini +1: Claude Sonnet 4.6- Replace passlib with bcrypt directly (passlib 1.7 incompatible with bcrypt 4.x) - Fix SQLite engine config: disable pool_pre_ping, add check_same_thread=False - Import all models in __init__.py so SQLAlchemy resolves relationships - Change dev proxy port to 8001 (port 8000 occupied by Wacom service on dev machine) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>3d87cee -
feat: add React frontend (feature/frontend)
Fabio Antonini +1: Claude Sonnet 4.6Vite + React 19 + TypeScript SPA with: - Tailwind CSS + shadcn/ui-compatible components (Button, Input, Card, Badge) - react-router-dom v7 with protected routes and AppLayout sidebar - zustand auth store (access + refresh token, persisted to localStorage) - axios API client with auto-refresh interceptor on 401 - react-i18next with IT/EN locale files (full translation coverage) - Pages: LoginPage, ProjectsPage, ProjectDetailPage, RagPage - Sidebar with role-aware nav (admin link only for admin role) + language toggle - vite proxy: /api → http://localhost:8000 (dev), nginx proxy (Docker) - Dockerfile: multi-stage build (node:20 → nginx:alpine) with SPA fallback - docker-compose.yml: added frontend service on port 3000 Build: 384 kB JS + 13 kB CSS (gzip: 124 kB + 3.7 kB) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>977221f