app/core/note_payload.py aktualisiert
Some checks failed
Deploy mindnet to llm-node / deploy (push) Failing after 2s

This commit is contained in:
Lars 2025-09-09 16:55:36 +02:00
parent 298c1fb180
commit 81c1400ef4

View File

@ -1,47 +1,36 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Modul: app/core/note_payload.py
# Version: 1.6.1
# Version: 1.6.3
# Datum: 2025-09-09
#
# Kurzbeschreibung
# ----------------
# Zweck
# -----
# Erzeugt den Qdrant-Payload für Notes inkl. robuster Hash-Bildung zur
# Änderungserkennung. Der vollständige Body wird unter "fulltext" persistiert;
# der Pfad ist relativ (für verlustfreien Export).
# Änderungserkennung. Der vollständige (parsed) Body wird unter "fulltext"
# persistiert; der Pfad ist relativ (für verlustfreien Export).
#
# Wichtige Punkte
# ---------------
# - Nur Inhalte fließen in den Hash ein (keine FS-Zeitstempel).
# - Vergleichsarten:
# Body -> nur Body
# Frontmatter -> nur Frontmatter
# Full -> Body + Frontmatter
# Steuerbar per CLI/ENV:
# Steuerung (CLI/ENV, vom Importer durchgereicht)
# -----------------------------------------------
# - Vergleichsmodus:
# --hash-mode body|frontmatter|full
# MINDNET_HASH_MODE / MINDNET_HASH_COMPARE (Body|Frontmatter|Full)
# ENV: MINDNET_HASH_MODE oder MINDNET_HASH_COMPARE (Body|Frontmatter|Full)
# "full" ist Alias für "body+frontmatter".
# - Hash-Quelle:
# parsed (Default) -> Parser-Body
# raw -> Rohdatei-Body (Frontmatter via Regex entfernt)
# Steuerbar per:
# --hash-source parsed|raw
# MINDNET_HASH_SOURCE
# --hash-source parsed|raw (ENV: MINDNET_HASH_SOURCE)
# - Normalisierung:
# canonical (Default) -> \r\n->\n, trailing spaces pro Zeile entfernt
# none -> keine Normalisierung (jede Kleinigkeit zählt)
# Steuerbar per:
# --hash-normalize canonical|none
# MINDNET_HASH_NORMALIZE
# --hash-normalize canonical|none (ENV: MINDNET_HASH_NORMALIZE)
#
# Neu in v1.6.x
# -------------
# - "hash_signature" im Payload, z. B. "body:raw:none:<hex>".
# - Optional (ENV MINDNET_HASH_RECORD_ALL=true): zusätzliches Hash-Set für Debug:
# payload["hashes"] = {
# "body_parsed": "...", "body_raw": "...",
# "frontmatter": "...",
# "full_parsed": "...", "full_raw": "..."
# }
# Payload-Felder (Auszug)
# -----------------------
# note_id, title, type, status, created, updated, path, tags,
# fulltext, references (Note-Level-Wikilinks),
# hash_fulltext (Primärhash), hash_signature (z. B. "body:raw:none:<hex>")
#
# Hinweise
# --------
# - Keine Abhängigkeit von FS-Zeitstempeln; nur Inhalte fließen in den Hash ein.
# - Abwärtskompatibel: Feldernamen bleiben stabil; zusätzliche Felder stören nicht.
from __future__ import annotations
@ -245,4 +234,76 @@ def make_note_payload(
except Exception:
pass
# Note-Level-Wikilinks
# Note-Level-Wikilinks (Fallback, wenn Chunks nicht geliefert werden)
note_level_refs = list(dict.fromkeys(extract_wikilinks(body_parsed))) if body_parsed else []
payload: Dict[str, Any] = {
"note_id": fm.get("id") or fm.get("note_id"),
"title": fm.get("title"),
"type": fm.get("type"),
"status": fm.get("status"),
"created": fm.get("created"),
"updated": fm.get("updated"),
"path": rel_path or fm.get("path"),
"tags": fm.get("tags"),
# Primärer Hash + Signatur (für Vergleich)
"hash_fulltext": primary_hash,
"hash_signature": hash_signature,
# Volltext persistieren (verlustfreie Rekonstruktion) parsed Body
"fulltext": body_parsed,
# Fallback-Refs auf Note-Ebene
"references": note_level_refs,
}
for k in ("area", "project", "source", "lang", "slug", "aliases"):
if k in fm:
payload[k] = fm[k]
# Optional: gesamtes Hash-Set persistieren (Debug/Monitoring)
if os.environ.get("MINDNET_HASH_RECORD_ALL", "false").strip().lower() == "true":
payload["hashes"] = compute_hash_set(
body_parsed=body_parsed, body_raw=raw_body, fm=fm, normalize=normalize
)
# Optional: Roh-Body-Hash separat (historische Kompatibilität)
if os.environ.get("MINDNET_HASH_STORE_RAW", "false").strip().lower() == "true" and src == "raw":
try:
payload["hash_raw_body"] = compute_hash(
body=raw_body, frontmatter=fm, mode="body", normalize="none"
)
except Exception:
pass
return payload
# ---------------------------------------------------------------------------
# CLI Sichtprüfung
# ---------------------------------------------------------------------------
def _cli() -> None:
ap = argparse.ArgumentParser(description="Note-Payload aus Markdown erzeugen und anzeigen")
ap.add_argument("--from-file", dest="src", required=True, help="Pfad zur Markdown-Datei")
ap.add_argument("--vault-root", dest="vault_root", default=None, help="Vault-Wurzel zur Pfad-Relativierung")
ap.add_argument("--print", dest="do_print", action="store_true", help="Payload auf stdout ausgeben")
ap.add_argument("--hash-mode", choices=["body", "frontmatter", "body+frontmatter", "full"], default=None)
ap.add_argument("--hash-normalize", choices=["canonical", "none"], default=None)
ap.add_argument("--hash-source", choices=["parsed", "raw"], default=None)
args = ap.parse_args()
parsed = read_markdown(args.src)
payload = make_note_payload(
parsed,
vault_root=args.vault_root,
hash_mode=args.hash_mode,
hash_normalize=args.hash_normalize,
hash_source=args.hash_source,
file_path=args.src,
)
if args.do_print:
print(json.dumps(payload, ensure_ascii=False, indent=2))
if __name__ == "__main__": # pragma: no cover
_cli()