79 lines
3.3 KiB
Python
79 lines
3.3 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, List, Set
|
|
from core.connection import get_connection
|
|
|
|
def build_prompt_diff(
|
|
action: str,
|
|
section_id: int = None,
|
|
item_id: int = None,
|
|
content: str = "",
|
|
delete_nodes: List[Tuple[int, int]] = None,
|
|
prompt_name: str = "main_agent"
|
|
) -> Tuple[str, str]:
|
|
act = (action or "ADD").upper()
|
|
nodes_to_delete: Set[Tuple[int, int]] = set()
|
|
|
|
if delete_nodes:
|
|
nodes_to_delete.update(delete_nodes)
|
|
elif act == "DELETE" and section_id is not None and item_id is not None:
|
|
nodes_to_delete.add((section_id, item_id))
|
|
|
|
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 not in nodes_to_delete}
|
|
|
|
if act not in ["DELETE", "BATCH_DELETE"] and section_id is not None and item_id is not None:
|
|
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)
|
|
|
|
diff_lines = []
|
|
curr_sec = None
|
|
display_nodes = dict(nodes_dict)
|
|
if act not in ["DELETE", "BATCH_DELETE"] and section_id is not None and item_id is not None:
|
|
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, i_id) in nodes_to_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>'
|
|
elif act == "ADD" and s_id == section_id and i_id == item_id:
|
|
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)
|
|
|
|
return merged_prompt, "\n".join(diff_lines) |