77 lines
3.1 KiB
Python
77 lines
3.1 KiB
Python
"""
|
|
===============================================================================
|
|
FILE: services/prompts/diff_engine.py
|
|
PROJECT: SCUD Orion AI (Unified Architecture)
|
|
MODULE: services / prompts
|
|
ROLE: Формирование превью изменений промпта и генерация визуального HTML-Diff.
|
|
|
|
AI-CONTEXT-ANCHORS:
|
|
- ANCHOR[PROMPT_DIFF_BUILDER]: Генерация черновика и HTML-разметки изменений.
|
|
===============================================================================
|
|
"""
|
|
|
|
from typing import Tuple, Dict
|
|
from core.connection import get_connection
|
|
|
|
|
|
# ANCHOR[PROMPT_DIFF_BUILDER]
|
|
def build_prompt_diff(action: str, section_id: int, item_id: int, content: str = "", prompt_name: str = "main_agent") -> Tuple[str, str]:
|
|
"""
|
|
Возвращает кортеж (merged_draft_text, diff_html_for_ui).
|
|
"""
|
|
act = (action or "ADD").upper()
|
|
|
|
with get_connection(row_factory=True) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute("""
|
|
SELECT section_id, item_id, content
|
|
FROM system_prompt_nodes
|
|
WHERE prompt_name = ? AND is_active = 1
|
|
ORDER BY section_id, item_id
|
|
""", (prompt_name,))
|
|
existing_nodes = cursor.fetchall()
|
|
|
|
nodes_dict = {(r["section_id"], r["item_id"]): r["content"] for r in existing_nodes}
|
|
|
|
# Формируем словарь для чистого текста
|
|
nodes_dict_for_draft = {k: v for k, v in nodes_dict.items() if k != (section_id, item_id)} if act == "DELETE" else dict(nodes_dict)
|
|
if act != "DELETE":
|
|
nodes_dict_for_draft[(section_id, item_id)] = content
|
|
|
|
draft_lines = []
|
|
curr_sec = None
|
|
for (s_id, i_id), txt in sorted(nodes_dict_for_draft.items()):
|
|
if i_id == 0:
|
|
if curr_sec is not None:
|
|
draft_lines.append("")
|
|
draft_lines.append(f"{s_id}. {txt}")
|
|
curr_sec = s_id
|
|
else:
|
|
draft_lines.append(f" {s_id}.{i_id}. {txt}")
|
|
merged_prompt = "\n".join(draft_lines)
|
|
|
|
# Формируем HTML Diff
|
|
diff_lines = []
|
|
curr_sec = None
|
|
display_nodes = dict(nodes_dict)
|
|
if act != "DELETE":
|
|
display_nodes[(section_id, item_id)] = content
|
|
|
|
for (s_id, i_id), txt in sorted(display_nodes.items()):
|
|
if i_id == 0:
|
|
if curr_sec is not None:
|
|
diff_lines.append("")
|
|
diff_lines.append(f"{s_id}. {txt}")
|
|
curr_sec = s_id
|
|
else:
|
|
if s_id == section_id and i_id == item_id:
|
|
if act == "DELETE":
|
|
line_str = f' <span class="line-through text-rose-600 font-bold bg-rose-50 px-1.5 py-0.5 rounded border border-rose-300 opacity-80">{s_id}.{i_id}. {txt} [УДАЛЕНИЕ]</span>'
|
|
else:
|
|
line_str = f' <span class="text-rose-600 font-bold bg-rose-50 px-1.5 py-0.5 rounded border border-rose-300">{s_id}.{i_id}. {txt}</span>'
|
|
else:
|
|
line_str = f" {s_id}.{i_id}. {txt}"
|
|
diff_lines.append(line_str)
|
|
|
|
diff_html = "\n".join(diff_lines)
|
|
return merged_prompt, diff_html |