""" =============================================================================== 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' {s_id}.{i_id}. {txt} [УДАЛЕНИЕ]' elif act == "ADD" and s_id == section_id and i_id == item_id: line_str = f' {s_id}.{i_id}. {txt}' else: line_str = f" {s_id}.{i_id}. {txt}" diff_lines.append(line_str) return merged_prompt, "\n".join(diff_lines)