feat: add vault download button and markdown viewer PRD to /files page
All checks were successful
Deploy / deploy (push) Successful in 12s

Adds GET /files/download endpoint that streams all vault files (excl.
.git) as a deflate-compressed vault.zip. Adds Download All button to
the /files page header. Also adds FILES_VIEWER_PRD.md planning doc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 19:35:25 +01:00
parent 9e143a8156
commit 49ab2a1599
2 changed files with 185 additions and 1 deletions

View File

@@ -12,11 +12,13 @@ Module-level VAULT_DIR and SETTINGS_PATH can be overridden by tests.
import asyncio
import base64
import difflib
import io
import json
import os
import re
import subprocess
import uuid
import zipfile
from pathlib import Path
from typing import Optional
@@ -797,6 +799,23 @@ async def sync_history(request: Request):
# File browser
# ---------------------------------------------------------------------------
@app.get("/files/download")
async def download_vault():
if not VAULT_DIR.exists():
raise HTTPException(status_code=404, detail="Vault directory not found")
buf = io.BytesIO()
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
for file_path in sorted(VAULT_DIR.rglob("*")):
if file_path.is_file() and ".git" not in file_path.parts:
zf.write(file_path, file_path.relative_to(VAULT_DIR))
buf.seek(0)
return StreamingResponse(
buf,
media_type="application/zip",
headers={"Content-Disposition": 'attachment; filename="vault.zip"'},
)
@app.get("/files", response_class=HTMLResponse)
async def file_browser():
tree_html = _get_vault_tree_html()
@@ -811,7 +830,10 @@ async def file_browser():
<div class="card">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
<h2 style="margin:0">Vault Files ({file_count})</h2>
<small style="color:#999"><code>{VAULT_DIR}</code></small>
<div style="display:flex;align-items:center;gap:12px">
<a href="/files/download" class="btn btn-secondary" style="font-size:.8rem;padding:6px 14px">&#x2B73; Download All</a>
<small style="color:#999"><code>{VAULT_DIR}</code></small>
</div>
</div>
<div style="font-size:.9rem;line-height:1.6">{tree_html}</div>
</div>"""