revengelibrary 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ from .agents import DEFAULT_AGENT, AgentProfile, get_agent, list_agents
1
2
  from .chat import (
2
3
  APIError,
3
4
  DEFAULT_MEMORY_FILE,
@@ -12,5 +13,9 @@ __all__ = [
12
13
  "DEFAULT_OPENROUTER_API_KEY",
13
14
  "DEFAULT_MODEL",
14
15
  "DEFAULT_MEMORY_FILE",
16
+ "DEFAULT_AGENT",
17
+ "AgentProfile",
18
+ "list_agents",
19
+ "get_agent",
15
20
  ]
16
- __version__ = "0.1.5"
21
+ __version__ = "0.1.6"
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ DEFAULT_AGENT = "general"
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class AgentProfile:
10
+ name: str
11
+ title: str
12
+ system_prompt: str
13
+
14
+
15
+ AGENT_PROFILES: dict[str, AgentProfile] = {
16
+ "general": AgentProfile(
17
+ name="general",
18
+ title="Универсальный ассистент",
19
+ system_prompt="You are a helpful assistant.",
20
+ ),
21
+ "frontend": AgentProfile(
22
+ name="frontend",
23
+ title="Senior Frontend + Mobile Design",
24
+ system_prompt=(
25
+ "Ты senior frontend-разработчик с сильной экспертизой в дизайне "
26
+ "мобильных приложений. Пиши ответы как практический инженер: "
27
+ "mobile-first, доступность, понятная архитектура компонентов, "
28
+ "чистый UI/UX, адаптив под iOS/Android, хорошая типографика и "
29
+ "согласованная дизайн-система."
30
+ ),
31
+ ),
32
+ "backend": AgentProfile(
33
+ name="backend",
34
+ title="Backend Engineer",
35
+ system_prompt=(
36
+ "Ты senior backend-разработчик. Предлагай надежные API-контракты, "
37
+ "чистую архитектуру, контроль ошибок, безопасность и масштабируемость."
38
+ ),
39
+ ),
40
+ "qa": AgentProfile(
41
+ name="qa",
42
+ title="QA Engineer",
43
+ system_prompt=(
44
+ "Ты senior QA-инженер. Фокус: тест-кейсы, граничные условия, "
45
+ "регрессия, воспроизводимость багов и риски релиза."
46
+ ),
47
+ ),
48
+ }
49
+
50
+
51
+ def list_agents() -> list[AgentProfile]:
52
+ return list(AGENT_PROFILES.values())
53
+
54
+
55
+ def get_agent(agent_name: str) -> AgentProfile:
56
+ name = (agent_name or DEFAULT_AGENT).strip().lower()
57
+ if name not in AGENT_PROFILES:
58
+ available = ", ".join(sorted(AGENT_PROFILES))
59
+ raise ValueError(f"Unknown agent '{agent_name}'. Available: {available}")
60
+ return AGENT_PROFILES[name]
revengelibrary/chat.py CHANGED
@@ -176,7 +176,7 @@ class FreeNeuroChatClient:
176
176
  value = file_path if file_path is not None else self.memory_file
177
177
  if not value:
178
178
  return None
179
- return Path(value).expanduser()
179
+ return _normalize_memory_path(value)
180
180
 
181
181
  @staticmethod
182
182
  def _normalize_messages(data: Any) -> list[dict[str, str]]:
@@ -205,3 +205,10 @@ class FreeNeuroChatClient:
205
205
  return content
206
206
  except (KeyError, TypeError, IndexError):
207
207
  raise APIError(f"Unexpected API response: {data}") from None
208
+
209
+
210
+ def _normalize_memory_path(value: str) -> Path:
211
+ path = Path(value).expanduser()
212
+ if path.suffix:
213
+ return path
214
+ return path.with_suffix(".json")
revengelibrary/cli.py CHANGED
@@ -2,7 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  import argparse
4
4
  import os
5
+ from pathlib import Path
5
6
 
7
+ from .agents import DEFAULT_AGENT, get_agent, list_agents
6
8
  from .chat import (
7
9
  APIError,
8
10
  DEFAULT_MEMORY_FILE,
@@ -29,8 +31,18 @@ def _build_parser() -> argparse.ArgumentParser:
29
31
  )
30
32
  parser.add_argument(
31
33
  "--system",
32
- default="You are a helpful assistant.",
33
- help="System prompt.",
34
+ default=None,
35
+ help="System prompt override. If omitted, selected agent prompt is used.",
36
+ )
37
+ parser.add_argument(
38
+ "--agent",
39
+ default=os.getenv("REVENGELIBRARY_AGENT", DEFAULT_AGENT),
40
+ help="Agent role. Use --list-agents to view available roles.",
41
+ )
42
+ parser.add_argument(
43
+ "--list-agents",
44
+ action="store_true",
45
+ help="Show available agent roles and exit.",
34
46
  )
35
47
  parser.add_argument(
36
48
  "--memory-file",
@@ -47,11 +59,24 @@ def main() -> int:
47
59
  parser = _build_parser()
48
60
  args = parser.parse_args()
49
61
 
62
+ if args.list_agents:
63
+ for profile in list_agents():
64
+ print(f"{profile.name}: {profile.title}")
65
+ return 0
66
+
67
+ try:
68
+ agent = get_agent(args.agent)
69
+ except ValueError as exc:
70
+ parser.error(str(exc))
71
+
72
+ system_prompt = args.system if args.system else agent.system_prompt
73
+ memory_file = _agent_memory_file(args.memory_file, agent.name)
74
+
50
75
  client = FreeNeuroChatClient(
51
76
  api_key=args.api_key or DEFAULT_OPENROUTER_API_KEY,
52
77
  model=args.model,
53
- system_prompt=args.system,
54
- memory_file=args.memory_file,
78
+ system_prompt=system_prompt,
79
+ memory_file=memory_file,
55
80
  )
56
81
 
57
82
  print(
@@ -89,5 +114,17 @@ def main() -> int:
89
114
  print(f"unexpected error: {exc}")
90
115
 
91
116
 
117
+ def _agent_memory_file(memory_file: str | None, agent_name: str) -> str | None:
118
+ if not memory_file:
119
+ return None
120
+ if agent_name == DEFAULT_AGENT:
121
+ return memory_file
122
+
123
+ path = Path(memory_file).expanduser()
124
+ suffix = path.suffix or ".json"
125
+ stem = path.stem if path.suffix else path.name
126
+ return str(path.with_name(f"{stem}__{agent_name}{suffix}"))
127
+
128
+
92
129
  if __name__ == "__main__":
93
130
  raise SystemExit(main())
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: revengelibrary
3
- Version: 0.1.5
4
- Summary: Python chat library and CLI for free LLM models via OpenRouter.
3
+ Version: 0.1.6
4
+ Summary: Не нейросеть
5
5
  Author: revengebibliotek contributors
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/example/revengelibrary
@@ -0,0 +1,11 @@
1
+ revengelibrary/__init__.py,sha256=2eUolZgyW421WD9ABtUVRSIsauzY7IZJ-6YMveHcoi8,448
2
+ revengelibrary/agents.py,sha256=GTrO_rsONJiSiIE09turpERnE34vYBLWkLtp5dzDj0o,2230
3
+ revengelibrary/chat.py,sha256=1UyJ9HZNea_oglsYMVqg3VdR2ASJvn4IPTBdUjNQ03k,7542
4
+ revengelibrary/cli.py,sha256=oCJlIIwZf97CtIG4jOMOk55EFSFR7_nYfeqQ2ONwMuI,3741
5
+ revengelibrary/memory_store.json,sha256=N1F-Xz3GaBn2H1p7uKzhkhKCQV8QVR0t76XD6wmFtXA,3
6
+ revengelibrary-0.1.6.dist-info/licenses/LICENSE,sha256=UgqQ8UtVfIOP8-clGkGAylmb9AUbT4-Ue49N_WjIpi4,1073
7
+ revengelibrary-0.1.6.dist-info/METADATA,sha256=UnzJRFbbSLm_FKE9fsmnIKBsUaNPfTxIM96IxYn379w,822
8
+ revengelibrary-0.1.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
9
+ revengelibrary-0.1.6.dist-info/entry_points.txt,sha256=299WMDffRchuwIlqEIjW-DwHYkBvRZQwGjiASIVofYE,59
10
+ revengelibrary-0.1.6.dist-info/top_level.txt,sha256=gfUsAxA-IgliQakMoupLAAjrTEYtUJurH5n29eHhUBE,15
11
+ revengelibrary-0.1.6.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- revengelibrary/__init__.py,sha256=HWDxVkOjWf65-SM4JIm0p3aNyDoEByCuCjTJCiFgBD4,299
2
- revengelibrary/chat.py,sha256=a1crCvwW9L3w3YYstE_OFtCM4khrPoGtr8eZFL6-EnQ,7374
3
- revengelibrary/cli.py,sha256=zllHMGN8EHJCSzMI5kpT8wk2-h9sD_38ysJ9zY6NxO0,2543
4
- revengelibrary/memory_store.json,sha256=N1F-Xz3GaBn2H1p7uKzhkhKCQV8QVR0t76XD6wmFtXA,3
5
- revengelibrary-0.1.5.dist-info/licenses/LICENSE,sha256=UgqQ8UtVfIOP8-clGkGAylmb9AUbT4-Ue49N_WjIpi4,1073
6
- revengelibrary-0.1.5.dist-info/METADATA,sha256=bqiA6Mi7yblgWF42hGOXMO2gDgcExiPNUIEL-U4O6gQ,862
7
- revengelibrary-0.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
8
- revengelibrary-0.1.5.dist-info/entry_points.txt,sha256=299WMDffRchuwIlqEIjW-DwHYkBvRZQwGjiASIVofYE,59
9
- revengelibrary-0.1.5.dist-info/top_level.txt,sha256=gfUsAxA-IgliQakMoupLAAjrTEYtUJurH5n29eHhUBE,15
10
- revengelibrary-0.1.5.dist-info/RECORD,,