feat: AI-generated title+tldr, subfolder structure, backlinks in transkript/zusammenfassung

- llm: generate_title_and_tldr() returns concise title and 2-3 sentence summary
- output: index in root, transkript+zusammenfassung in {base}/ subdir with backlinks
- pipeline: call generate_title_and_tldr for both solo and meeting recordings
- router: mirror subdir structure when copying to Obsidian vault

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-02 12:07:54 +02:00
parent 1cfb9c127b
commit 336628341b
6 changed files with 1072 additions and 27 deletions
+9 -5
View File
@@ -223,22 +223,26 @@ async def open_file(body: dict, user: dict = Depends(current_user)):
from urllib.parse import quote
cfg = load_config()
vault = cfg.get("obsidian", {}).get("vault", "").strip()
# If only the index was passed, also include sibling transkript/zusammenfassung
# If only the index was passed, also include siblings from subdir
all_paths = list(paths)
for p in paths:
if p.endswith("-index.md"):
base = p[: -len("-index.md")]
base = os.path.basename(p)[: -len("-index.md")]
subdir = os.path.join(os.path.dirname(p), base)
for suffix in ("-transkript.md", "-zusammenfassung.md"):
sibling = base + suffix
sibling = os.path.join(subdir, base + suffix)
if os.path.exists(sibling) and sibling not in all_paths:
all_paths.append(sibling)
open_target = all_paths[0]
if vault and os.path.isdir(vault):
# Mirror directory structure: index → vault root, others → vault/{base}/
for p in all_paths:
dest = os.path.join(vault, os.path.basename(p))
rel = os.path.relpath(p, abs_user_dir)
dest = os.path.join(vault, rel)
os.makedirs(os.path.dirname(dest), exist_ok=True)
shutil.copy2(p, dest)
open_target = os.path.join(vault, os.path.basename(all_paths[0]))
open_target = os.path.join(vault, os.path.relpath(all_paths[0], abs_user_dir))
vault_name = os.path.basename(vault.rstrip("/")) if vault else ""
file_name = os.path.basename(open_target)
if vault_name: