Files
linear-coding-agent/generations/library_rag/templates/base.html
David Blanc Brioir 187ba4854e chore: Major cleanup - archive migration scripts and remove temp files
CLEANUP ACTIONS:
- Archived 11 migration/optimization scripts to archive/migration_scripts/
- Archived 11 phase documentation files to archive/documentation/
- Moved backups/, docs/, scripts/ to archive/
- Deleted 30+ temporary debug/test/fix scripts
- Cleaned Python cache (__pycache__/, *.pyc)
- Cleaned log files (*.log)

NEW FILES:
- CHANGELOG.md: Consolidated project history and migration documentation
- Updated .gitignore: Added *.log, *.pyc, archive/ exclusions

FINAL ROOT STRUCTURE (19 items):
- Core framework: agent.py, autonomous_agent_demo.py, client.py, security.py, progress.py, prompts.py
- Config: requirements.txt, package.json, .gitignore
- Docs: README.md, CHANGELOG.md, project_progress.md
- Directories: archive/, generations/, memory/, prompts/, utils/

ARCHIVED SCRIPTS (in archive/migration_scripts/):
01-11: Migration & optimization scripts (migrate, schema, rechunk, vectorize, etc.)

ARCHIVED DOCS (in archive/documentation/):
PHASE_0-8: Detailed phase summaries
MIGRATION_README.md, PLAN_MIGRATION_WEAVIATE_GPU.md

Repository is now clean and production-ready with all important files preserved in archive/.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 18:05:43 +01:00

804 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Philosophia{% endblock %} Visualiseur Weaviate</title>
<!-- Google Fonts: DM Sans + Lato -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Lato:ital,wght@0,300;0,400;0,700;1,400&display=swap" rel="stylesheet">
<style>
/* =========================================================
Charte graphique Site RAG Philosophie
Palette beige + contrastes doux
Typo : DM Sans (titres) + Lato (texte)
========================================================= */
/* Reset basique */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: 'Lato', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background-color: #F8F4EE;
color: #2B2B2B;
line-height: 1.6;
}
/* Variables CSS */
:root {
--color-bg-main: #F8F4EE;
--color-bg-secondary: #EAE5E0;
--color-text-main: #2B2B2B;
--color-text-strong: #1F1F1F;
--color-accent: #7D6E58;
--color-accent-alt: #556B63;
--max-content-width: 1100px;
--font-title: 'DM Sans', system-ui, sans-serif;
--font-body: 'Lato', system-ui, sans-serif;
}
/* Conteneur principal */
.wrapper {
max-width: var(--max-content-width);
margin: 0 auto;
padding: 1.5rem 1.5rem;
padding-top: 90px; /* Espace pour le header fixe */
padding-left: calc(1rem + 48px + 1rem); /* Aligner avec le header */
}
@media (min-width: 992px) {
.wrapper {
padding: 2.5rem 3rem;
padding-top: 90px; /* Conserver l'espace pour le header fixe */
padding-left: calc(1rem + 48px + 1rem); /* Aligner avec le header */
}
}
/* Titres & textes */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-title);
color: var(--color-text-strong);
margin-bottom: 0.75rem;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
letter-spacing: 0.02em;
}
h2 {
font-size: 2rem;
font-weight: 600;
}
h3 {
font-size: 1.5rem;
font-weight: 500;
}
p {
margin-bottom: 1.5rem;
font-family: var(--font-body);
font-size: 1rem;
color: var(--color-text-main);
}
strong {
font-weight: 600;
}
.lead {
font-size: 1.1rem;
font-style: italic;
color: var(--color-accent-alt);
margin-bottom: 2rem;
}
.caption {
font-size: 0.9rem;
font-weight: 300;
color: var(--color-accent);
margin-top: 0.25rem;
}
/* Liens */
a {
color: var(--color-accent);
text-decoration: none;
transition: color 0.2s ease, text-decoration-color 0.2s ease;
}
a:hover,
a:focus {
text-decoration: underline;
text-decoration-thickness: 1px;
}
/* Boutons */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.65rem 1.6rem;
border-radius: 8px;
border: 1.5px solid var(--color-accent);
background-color: transparent;
color: var(--color-accent);
font-family: var(--font-body);
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
text-decoration: none;
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.btn:hover,
.btn:focus {
background-color: var(--color-accent);
color: var(--color-bg-main);
text-decoration: none;
}
.btn-primary {
background-color: var(--color-accent);
color: var(--color-bg-main);
}
.btn-primary:hover,
.btn-primary:focus {
background-color: var(--color-accent-alt);
border-color: var(--color-accent-alt);
}
.btn-sm {
padding: 0.4rem 1rem;
font-size: 0.85rem;
}
/* Sidebar Navigation */
.nav-sidebar {
position: fixed;
left: 0;
top: 0;
width: 260px;
height: 100vh;
background-color: #fff;
border-right: 1px solid rgba(125, 110, 88, 0.15);
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.03);
transform: translateX(-100%);
transition: transform 0.3s ease;
z-index: 1000;
overflow-y: auto;
}
.nav-sidebar.visible {
transform: translateX(0);
}
.sidebar-header {
padding: 1.75rem 1.5rem;
border-bottom: 1px solid rgba(125, 110, 88, 0.1);
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.sidebar-header-text {
flex: 1;
}
.sidebar-title {
font-family: var(--font-title);
font-size: 1.3rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--color-text-strong);
margin-bottom: 0.25rem;
}
.sidebar-subtitle {
font-family: var(--font-body);
font-size: 0.85rem;
color: var(--color-accent-alt);
}
.sidebar-close-btn {
background: none;
border: none;
font-size: 1.5rem;
color: var(--color-accent);
cursor: pointer;
padding: 0.25rem;
line-height: 1;
transition: transform 0.2s ease, color 0.2s ease;
}
.sidebar-close-btn:hover {
transform: scale(1.1);
color: var(--color-accent-alt);
}
.sidebar-nav {
padding: 1rem 0;
}
.sidebar-nav a {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.85rem 1.5rem;
font-family: var(--font-title);
font-size: 0.95rem;
font-weight: 500;
color: var(--color-accent-alt);
text-decoration: none;
border-left: 3px solid transparent;
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.sidebar-nav a:hover {
background-color: rgba(125, 110, 88, 0.05);
color: var(--color-accent);
}
.sidebar-nav a.active {
background-color: rgba(125, 110, 88, 0.08);
border-left-color: var(--color-accent);
color: var(--color-accent);
}
.sidebar-nav a .icon {
font-size: 1.1rem;
width: 20px;
text-align: center;
}
/* Sidebar overlay */
.sidebar-overlay {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.3);
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
z-index: 999;
}
.sidebar-overlay.visible {
opacity: 1;
visibility: visible;
}
/* Hamburger button */
.hamburger-btn {
position: fixed;
left: 1rem;
top: 1rem;
width: 48px;
height: 48px;
background-color: #fff;
border: 1px solid rgba(125, 110, 88, 0.2);
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 5px;
cursor: pointer;
z-index: 1001;
transition: background-color 0.2s ease, transform 0.2s ease, opacity 0.3s ease, visibility 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.hamburger-btn.active {
opacity: 0;
visibility: hidden;
}
.hamburger-btn:hover {
background-color: rgba(125, 110, 88, 0.05);
transform: scale(1.05);
}
.hamburger-btn span {
width: 22px;
height: 2px;
background-color: var(--color-accent);
border-radius: 2px;
transition: transform 0.3s ease, opacity 0.3s ease;
}
/* Header */
.site-header {
position: fixed;
top: 0;
left: 0;
right: 0;
padding: 1.5rem 1.5rem;
padding-left: calc(1rem + 48px + 1rem); /* left menu (1rem) + width (48px) + marge (1rem) = 80px */
border-bottom: 1px solid rgba(0, 0, 0, 0.04);
background-color: var(--color-bg-main);
z-index: 100;
}
.site-title {
font-family: var(--font-title);
font-size: 1.4rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--color-text-strong);
}
.site-subtitle {
font-family: var(--font-body);
font-size: 0.9rem;
color: var(--color-accent-alt);
margin-top: 0.2rem;
}
.header-inner {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
/* Hide old navigation in header */
.nav-links {
display: none;
}
/* Sections */
.section {
padding: 2.5rem 0;
}
.section--alt {
background-color: var(--color-bg-secondary);
}
/* Cards */
.card {
background-color: rgba(255, 255, 255, 0.06);
border-radius: 12px;
padding: 1.75rem;
border: 1px solid rgba(125, 110, 88, 0.25);
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.03);
}
/* Passage cards */
.passage-card {
background-color: rgba(255, 255, 255, 0.06);
border-radius: 12px;
padding: 1.75rem;
border: 1px solid rgba(125, 110, 88, 0.25);
border-left: 3px solid var(--color-accent);
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.03);
margin-bottom: 1.25rem;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.passage-card:hover {
transform: translateX(4px);
box-shadow: 0 18px 50px rgba(0, 0, 0, 0.06);
}
.passage-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 1rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.passage-text {
font-family: var(--font-body);
font-size: 1rem;
line-height: 1.65;
color: var(--color-text-main);
font-style: italic;
margin-bottom: 1rem;
}
.passage-meta {
font-family: var(--font-body);
font-size: 0.85rem;
font-weight: 300;
color: var(--color-accent);
padding-top: 0.75rem;
border-top: 1px solid rgba(125, 110, 88, 0.15);
}
/* Badges */
.badge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.6rem;
border-radius: 999px;
border: 1px solid rgba(85, 107, 99, 0.4);
font-size: 0.75rem;
color: var(--color-accent-alt);
margin-right: 0.4rem;
margin-bottom: 0.3rem;
}
.badge-author {
background-color: var(--color-accent);
color: var(--color-bg-main);
border: none;
font-family: var(--font-title);
font-weight: 500;
}
.badge-work {
background-color: transparent;
border-color: var(--color-accent-alt);
color: var(--color-accent-alt);
}
.badge-similarity {
background-color: var(--color-accent-alt);
color: var(--color-bg-main);
border: none;
}
.keyword-tag {
display: inline-flex;
align-items: center;
padding: 0.2rem 0.5rem;
border-radius: 999px;
border: 1px solid rgba(85, 107, 99, 0.3);
font-size: 0.7rem;
color: var(--color-accent-alt);
margin: 0.1rem;
}
/* Stats grid */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1.25rem;
margin-bottom: 2rem;
}
.stat-box {
background-color: var(--color-bg-secondary);
border: 1px solid rgba(125, 110, 88, 0.25);
border-radius: 12px;
padding: 1.75rem;
text-align: center;
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.03);
}
.stat-number {
font-family: var(--font-title);
font-size: 2.5rem;
font-weight: 700;
color: var(--color-accent);
line-height: 1;
}
.stat-label {
font-family: var(--font-title);
font-size: 0.85rem;
font-weight: 500;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-accent-alt);
margin-top: 0.5rem;
}
/* Forms */
.form-group {
margin-bottom: 1.25rem;
}
.form-label {
display: block;
font-family: var(--font-title);
font-size: 0.9rem;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--color-accent-alt);
margin-bottom: 0.4rem;
}
.form-control {
width: 100%;
padding: 0.8rem 1rem;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.08);
background-color: #fff;
font-family: var(--font-body);
font-size: 0.95rem;
color: var(--color-text-main);
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.form-control:focus {
outline: none;
border-color: var(--color-accent);
box-shadow: 0 0 0 3px rgba(125, 110, 88, 0.1);
}
select.form-control {
cursor: pointer;
}
.form-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
/* Search box */
.search-box {
background-color: var(--color-bg-secondary);
border-radius: 12px;
padding: 2rem;
margin-bottom: 2rem;
border: 1px solid rgba(125, 110, 88, 0.2);
}
.search-input {
font-size: 1.1rem;
padding: 1rem 1.25rem;
}
/* Pagination */
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid rgba(125, 110, 88, 0.15);
}
.pagination-info {
font-family: var(--font-body);
font-size: 0.9rem;
color: var(--color-accent-alt);
}
/* Footer */
.site-footer {
margin-top: 4rem;
padding: 2rem 0 1.5rem;
border-top: 1px solid rgba(0, 0, 0, 0.04);
text-align: center;
}
.footer-quote {
font-family: var(--font-body);
font-style: italic;
font-size: 0.9rem;
color: var(--color-accent-alt);
}
/* Utilitaires */
.mt-1 { margin-top: 0.5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.5rem; }
.mt-4 { margin-top: 2rem; }
.mb-1 { margin-bottom: 0.5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 1.5rem; }
.mb-4 { margin-bottom: 2rem; }
.text-center { text-align: center; }
.text-muted { color: rgba(43, 43, 43, 0.7); }
/* Divider */
.divider {
border: none;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(125, 110, 88, 0.3), transparent);
margin: 2rem 0;
}
/* Empty state */
.empty-state {
text-align: center;
padding: 3rem 1rem;
color: var(--color-accent-alt);
}
.empty-state-icon {
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.5;
}
/* Lists */
.list-inline {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
list-style: none;
}
.list-inline li {
font-family: var(--font-body);
color: var(--color-text-main);
}
/* Alert */
.alert {
padding: 1rem 1.25rem;
border-radius: 8px;
margin-bottom: 1.5rem;
font-size: 0.95rem;
}
.alert-warning {
background-color: rgba(125, 110, 88, 0.1);
border: 1px solid rgba(125, 110, 88, 0.3);
color: var(--color-accent);
}
.alert-success {
background-color: rgba(85, 107, 99, 0.1);
border: 1px solid rgba(85, 107, 99, 0.3);
color: var(--color-accent-alt);
}
/* Ornament */
.ornament {
text-align: center;
color: var(--color-accent);
font-size: 1rem;
letter-spacing: 0.5em;
opacity: 0.4;
margin: 1.5rem 0;
}
</style>
</head>
<body>
<!-- Hamburger button -->
<button class="hamburger-btn" id="hamburger-btn" aria-label="Toggle navigation">
<span></span>
<span></span>
<span></span>
</button>
<!-- Sidebar overlay -->
<div class="sidebar-overlay" id="sidebar-overlay"></div>
<!-- Sidebar navigation -->
<nav class="nav-sidebar" id="nav-sidebar">
<div class="sidebar-header">
<div class="sidebar-header-text">
<div class="sidebar-title">Philosophia</div>
<div class="sidebar-subtitle">Base Weaviate</div>
</div>
<button class="sidebar-close-btn" id="sidebar-close-btn" aria-label="Fermer le menu"></button>
</div>
<div class="sidebar-nav">
<a href="/" class="{{ 'active' if request.endpoint == 'index' else '' }}">
<span class="icon">🏠</span>
<span>Accueil</span>
</a>
<a href="/passages" class="{{ 'active' if request.endpoint == 'passages' else '' }}">
<span class="icon">📄</span>
<span>Passages</span>
</a>
<a href="/search" class="{{ 'active' if request.endpoint == 'search' else '' }}">
<span class="icon">🔍</span>
<span>Recherche</span>
</a>
<a href="/chat" class="{{ 'active' if request.endpoint == 'chat' else '' }}">
<span class="icon">💬</span>
<span>Conversation</span>
</a>
<a href="/upload" class="{{ 'active' if request.endpoint == 'upload' else '' }}">
<span class="icon">📤</span>
<span>Parser PDF</span>
</a>
<a href="/documents" class="{{ 'active' if request.endpoint == 'documents' else '' }}">
<span class="icon">📚</span>
<span>Documents</span>
</a>
<div style="margin: 1rem 0; border-top: 1px solid rgba(255,255,255,0.1);"></div>
<a href="/memories" class="{{ 'active' if request.endpoint == 'memories' else '' }}">
<span class="icon">🧠</span>
<span>Memory (Ikario)</span>
</a>
<a href="/conversations" class="{{ 'active' if request.endpoint == 'conversations' else '' }}">
<span class="icon">💭</span>
<span>Conversations</span>
</a>
</div>
</nav>
<!-- Header -->
<header class="site-header">
<div class="header-inner">
<div>
<a href="/" style="text-decoration: none;">
<div class="site-title">Philosophia</div>
</a>
</div>
<nav class="nav-links">
<a href="/" class="{{ 'active' if request.endpoint == 'index' else '' }}">Accueil</a>
<a href="/passages" class="{{ 'active' if request.endpoint == 'passages' else '' }}">Passages</a>
<a href="/search" class="{{ 'active' if request.endpoint == 'search' else '' }}">Recherche</a>
<a href="/chat" class="{{ 'active' if request.endpoint == 'chat' else '' }}">Conversation</a>
<a href="/upload" class="{{ 'active' if request.endpoint == 'upload' else '' }}">Parser PDF</a>
<a href="/documents" class="{{ 'active' if request.endpoint == 'documents' else '' }}">Documents</a>
<a href="/memories" class="{{ 'active' if request.endpoint == 'memories' else '' }}">Memory</a>
</nav>
</div>
</header>
<div class="wrapper">
<!-- Main Content -->
<main>
{% block content %}{% endblock %}
</main>
<!-- Footer -->
<footer class="site-footer">
<p class="footer-quote">« La philosophie est la médecine de l'âme. » — Cicéron</p>
</footer>
</div>
<!-- Sidebar toggle script -->
<script>
const hamburgerBtn = document.getElementById('hamburger-btn');
const navSidebar = document.getElementById('nav-sidebar');
const sidebarOverlay = document.getElementById('sidebar-overlay');
const sidebarCloseBtn = document.getElementById('sidebar-close-btn');
function toggleSidebar() {
hamburgerBtn.classList.toggle('active');
navSidebar.classList.toggle('visible');
sidebarOverlay.classList.toggle('visible');
}
function closeSidebar() {
hamburgerBtn.classList.remove('active');
navSidebar.classList.remove('visible');
sidebarOverlay.classList.remove('visible');
}
hamburgerBtn.addEventListener('click', toggleSidebar);
sidebarOverlay.addEventListener('click', closeSidebar);
sidebarCloseBtn.addEventListener('click', closeSidebar);
// Close sidebar on link click
const sidebarLinks = navSidebar.querySelectorAll('a');
sidebarLinks.forEach(link => {
link.addEventListener('click', closeSidebar);
});
// Close sidebar on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && navSidebar.classList.contains('visible')) {
closeSidebar();
}
});
</script>
</body>
</html>