refactor: step 2 - extract domain services (tasks, prompts, snapshots, knowledge)
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
"""
|
||||
===============================================================================
|
||||
FILE: services/prompts/repository.py
|
||||
PROJECT: SCUD Orion AI (Unified Architecture)
|
||||
MODULE: services / prompts
|
||||
ROLE: Реляционное хранилище узлов системного промпта (таблица system_prompt_nodes).
|
||||
|
||||
AI-CONTEXT-ANCHORS:
|
||||
- ANCHOR[PROMPT_REPO_GET_ACTIVE]: Сборка активного промпта из узлов БД.
|
||||
- ANCHOR[PROMPT_REPO_APPLY_ACTION]: Точечная вставка / изменение / удаление узла.
|
||||
===============================================================================
|
||||
"""
|
||||
|
||||
import re
|
||||
import logging
|
||||
from typing import List, Tuple, Dict, Any
|
||||
from core.connection import get_connection
|
||||
|
||||
logger = logging.getLogger("PROMPT_REPO")
|
||||
|
||||
|
||||
# ANCHOR[PROMPT_REPO_GET_ACTIVE]
|
||||
def repo_get_active_prompt(prompt_name: str = "main_agent") -> str:
|
||||
"""Собирает структурированный текст системного промпта из активных узлов."""
|
||||
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 ASC, item_id ASC
|
||||
""", (prompt_name,))
|
||||
rows = cursor.fetchall()
|
||||
|
||||
if not rows:
|
||||
return "Ты — ИИ-ассистент SCUD Orion AI."
|
||||
|
||||
lines = []
|
||||
current_section = None
|
||||
|
||||
for r in rows:
|
||||
sec_id = r["section_id"]
|
||||
itm_id = r["item_id"]
|
||||
content = r["content"]
|
||||
|
||||
if itm_id == 0:
|
||||
if current_section is not None:
|
||||
lines.append("")
|
||||
lines.append(f"{sec_id}. {content}")
|
||||
current_section = sec_id
|
||||
else:
|
||||
lines.append(f" {sec_id}.{itm_id}. {content}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
# ANCHOR[PROMPT_REPO_APPLY_ACTION]
|
||||
def repo_apply_prompt_action(action: str, section_id: int, item_id: int, content: str = "", prompt_name: str = "main_agent") -> None:
|
||||
"""Точечно применяет действие (ADD / UPDATE / DELETE) над узлом промпта."""
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
action_clean = (action or "").upper()
|
||||
if action_clean in ["ADD", "UPDATE", "EDIT"]:
|
||||
cursor.execute("""
|
||||
INSERT INTO system_prompt_nodes (prompt_name, section_id, item_id, content, is_active, updated_at)
|
||||
VALUES (?, ?, ?, ?, 1, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT(prompt_name, section_id, item_id) DO UPDATE SET
|
||||
content = excluded.content,
|
||||
is_active = 1,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
""", (prompt_name, section_id, item_id, content))
|
||||
elif action_clean == "DELETE":
|
||||
cursor.execute("""
|
||||
DELETE FROM system_prompt_nodes
|
||||
WHERE prompt_name = ? AND section_id = ? AND item_id = ?
|
||||
""", (prompt_name, section_id, item_id))
|
||||
conn.commit()
|
||||
|
||||
|
||||
def repo_save_full_prompt(prompt_text: str, prompt_name: str = "main_agent") -> None:
|
||||
"""Парсит и полностью перезаписывает все узлы промпта из сырого текста."""
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DELETE FROM system_prompt_nodes WHERE prompt_name = ?", (prompt_name,))
|
||||
|
||||
current_sec = 1
|
||||
current_itm = 0
|
||||
|
||||
for raw_line in prompt_text.splitlines():
|
||||
clean_line = re.sub(r'<[^>]+>', '', raw_line).strip()
|
||||
if not clean_line:
|
||||
continue
|
||||
|
||||
sub_match = re.match(r'^(\d+)[\.\s]+(\d+)[\.\s\:\-]+(.*)$', clean_line)
|
||||
sec_match = re.match(r'^(\d+)[\.\s\:\-]+(.*)$', clean_line)
|
||||
|
||||
if sub_match:
|
||||
current_sec = int(sub_match.group(1))
|
||||
current_itm = int(sub_match.group(2))
|
||||
content = sub_match.group(3).strip()
|
||||
elif sec_match and not any(c.islower() for c in sec_match.group(2)[:15]):
|
||||
current_sec = int(sec_match.group(1))
|
||||
current_itm = 0
|
||||
content = sec_match.group(2).strip()
|
||||
else:
|
||||
current_itm += 1
|
||||
content = clean_line
|
||||
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO system_prompt_nodes (prompt_name, section_id, item_id, content, is_active)
|
||||
VALUES (?, ?, ?, ?, 1)
|
||||
""", (prompt_name, current_sec, current_itm, content))
|
||||
|
||||
conn.commit()
|
||||
Reference in New Issue
Block a user