feat: points 11a + 11b — Indicateur AI Actif & Page d'accueil voute
CI / lint (push) Failing after 4s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / security (push) Successful in 8s

Point 11a — Indicateur AI Actif:
- Badge sync flashe en blanc pendant traitement AI (animation CSS)
- Événements ai-processing-start/end dans ai.js
- Section statut IA dans panneau sync (configurée/non configurée/en cours)
- Endpoint GET /api/ai/status vérifiant les clés API configurées

Point 11b — Page d'accueil de voute:
- Endpoint GET /api/vault/{vault}/files?dir=... (trié par mtime)
- Module vaulthome.js: affichage style résultats de recherche
- Breadcrumb navigable, mise à jour auto sur clic dossier dans tree
- Déclenché auto quand un vault spécifique est sélectionné
This commit is contained in:
2026-06-03 22:36:31 -04:00
parent d1ba15c3aa
commit 7a4b3d1329
7 changed files with 692 additions and 5 deletions
+91
View File
@@ -2162,6 +2162,21 @@ async def api_file_restore(
raise HTTPException(status_code=500, detail=f"Error restoring file: {str(e)}")
@app.get("/api/ai/status")
async def api_ai_status(current_user=Depends(require_auth)):
"""Return the AI configuration status.
Checks whether any AI provider API key is configured.
Does NOT expose the key itself, only a boolean 'configured' flag.
"""
providers = ["DEEPSEEK_API_KEY", "OPENROUTER_API_KEY", "GEMINI_API_KEY"]
configured = any(
os.environ.get(env_var, "").strip()
for env_var in providers
)
return {"configured": configured, "providers_checked": providers}
@app.get("/api/file/{vault_name}/backlinks")
async def api_file_backlinks(
vault_name: str,
@@ -3068,6 +3083,82 @@ async def api_update_vault_settings(vault_name: str, body: dict = Body(...), cur
return updated
@app.get("/api/vault/{vault_name}/files")
async def api_vault_recent_files(
vault_name: str,
dir: str = Query("", description="Directory path within the vault (empty = root)"),
limit: int = Query(100, description="Maximum number of files to return"),
current_user=Depends(require_auth),
):
"""List files in a vault directory sorted by modification time (newest first).
Returns file metadata suitable for a vault home page display.
Unlike /api/browse, this endpoint sorts by mtime and returns
additional metadata (size, modified time, extension).
Args:
vault_name: Name of the vault.
dir: Relative directory path within the vault (empty for root).
limit: Maximum files to return (default 100).
Returns:
JSON with vault, directory, and list of file entries.
"""
if not check_vault_access(vault_name, current_user):
raise HTTPException(status_code=403, detail=f"Accès refusé à la vault '{vault_name}'")
vault_data = get_vault_data(vault_name)
if not vault_data:
raise HTTPException(status_code=404, detail=f"Vault '{vault_name}' not found")
vault_root = Path(vault_data["path"])
dir_path = _resolve_safe_path(vault_root, dir) if dir else vault_root
if not dir_path.exists() or not dir_path.is_dir():
raise HTTPException(status_code=404, detail=f"Directory not found: {dir}")
files = []
ignored = {'.obsidian', '.trash', '.git', '.obsigate-backup', '__pycache__', 'node_modules'}
try:
for entry in dir_path.iterdir():
if entry.name.startswith('.') and entry.name not in ('.', '..'):
continue
if entry.name in ignored:
continue
if not entry.is_file():
continue
stat = entry.stat()
rel_path = str(entry.relative_to(vault_root)).replace("\\", "/")
ext = entry.suffix.lower() if entry.suffix else ""
files.append({
"name": entry.name,
"path": rel_path,
"vault": vault_name,
"size": stat.st_size,
"modified": stat.st_mtime,
"modified_iso": datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc).isoformat(),
"extension": ext.lstrip(".") if ext else "",
})
except PermissionError:
raise HTTPException(status_code=403, detail="Permission denied reading directory")
# Sort by modification time, newest first
files.sort(key=lambda f: f["modified"], reverse=True)
# Apply limit
files = files[:limit]
return {
"vault": vault_name,
"directory": dir,
"count": len(files),
"files": files,
}
@app.get("/api/vaults/settings/all")
async def api_get_all_vault_settings(current_user=Depends(require_auth)):
"""Get UI display settings for all vaults.