Coverage for src / osiris_cli / prompts.py: 0%
75 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-27 17:41 +0200
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-27 17:41 +0200
1import json
2from pathlib import Path
3from .config import CONFIG_DIR
5PROMPTS_FILE = CONFIG_DIR / "prompts.json"
7DEFAULT_PROMPTS = [
8 {"text": "Summarize the purpose of this file", "category": "Analysis"},
9 {"text": "Identify potential bugs or security issues", "category": "Code Quality"},
10 {"text": "Refactor this code to be more idiomatic", "category": "Refactoring"},
11 {"text": "Write unit tests for the selected code", "category": "Testing"},
12 {"text": "Explain how this works step-by-step", "category": "Learning"},
13]
15class PromptManager:
16 def __init__(self):
17 self.prompts = []
18 self.recents = []
19 self.load()
21 def load(self):
22 if PROMPTS_FILE.exists():
23 try:
24 data = json.loads(PROMPTS_FILE.read_text())
25 self.prompts = data.get("saved", DEFAULT_PROMPTS)
26 self.recents = data.get("recents", [])
27 except:
28 self.prompts = DEFAULT_PROMPTS
29 self.recents = []
30 else:
31 self.prompts = DEFAULT_PROMPTS
32 self.recents = []
33 self.save()
35 def save(self):
36 data = {
37 "saved": self.prompts,
38 "recents": self.recents
39 }
40 PROMPTS_FILE.write_text(json.dumps(data, indent=2))
42 def add_custom(self, text: str):
43 # Dedupe
44 if any(p["text"] == text for p in self.prompts):
45 return
46 self.prompts.append({"text": text, "category": "Custom"})
47 self.save()
49 def add_recent(self, text: str):
50 # Ignore short/common commands
51 if len(text) < 5 or text.startswith("/"):
52 return
54 # Dedupe
55 if text in self.recents:
56 self.recents.remove(text)
58 self.recents.insert(0, text)
59 # Keep last 10
60 self.recents = self.recents[:10]
61 self.save()
63 def delete_prompt(self, text: str):
64 """Deletes a prompt from saved prompts."""
65 original_len = len(self.prompts)
66 self.prompts = [p for p in self.prompts if p["text"] != text]
67 if len(self.prompts) < original_len:
68 self.save()
69 return True
70 return False
72 def get_all(self):
73 """Return list of (label, text) tuples for UI."""
74 options = []
76 # Recents first (Top 3)
77 if self.recents:
78 options.append(("-- Recent --", None))
79 for r in self.recents[:3]:
80 options.append((f"🕒 {r[:40]}...", r))
82 # Saved
83 options.append(("-- Library --", None))
84 for p in self.prompts:
85 icon = "📝"
86 if p["category"] == "Analysis": icon = "🔍"
87 elif p["category"] == "Refactoring": icon = "🔧"
88 elif p["category"] == "Testing": icon = "🧪"
90 options.append((f"{icon} {p['text']}", p['text']))
92 return options
94 def export_prompts(self, file_path: Path):
95 """Exports saved prompts to a JSON file."""
96 with open(file_path, "w") as f:
97 json.dump(self.prompts, f, indent=2)
99 def import_prompts(self, file_path: Path):
100 """Imports prompts from a JSON file, adding new ones and avoiding duplicates."""
101 if not file_path.exists():
102 raise FileNotFoundError(f"Prompt file not found: {file_path}")
104 with open(file_path, "r") as f:
105 new_prompts = json.load(f)
107 added_count = 0
108 for new_p in new_prompts:
109 if "text" in new_p and not any(p["text"] == new_p["text"] for p in self.prompts):
110 self.prompts.append(new_p)
111 added_count += 1
112 self.save()
113 return added_count
115prompt_manager = PromptManager()