cite-agent 1.0.4__py3-none-any.whl → 1.2.3__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.
Potentially problematic release.
This version of cite-agent might be problematic. Click here for more details.
- cite_agent/__init__.py +1 -1
- cite_agent/account_client.py +19 -46
- cite_agent/agent_backend_only.py +30 -4
- cite_agent/cli.py +397 -64
- cite_agent/cli_conversational.py +294 -0
- cite_agent/cli_workflow.py +276 -0
- cite_agent/enhanced_ai_agent.py +3222 -117
- cite_agent/session_manager.py +215 -0
- cite_agent/setup_config.py +5 -21
- cite_agent/streaming_ui.py +252 -0
- cite_agent/updater.py +50 -17
- cite_agent/workflow.py +427 -0
- cite_agent/workflow_integration.py +275 -0
- cite_agent-1.2.3.dist-info/METADATA +442 -0
- cite_agent-1.2.3.dist-info/RECORD +54 -0
- {cite_agent-1.0.4.dist-info → cite_agent-1.2.3.dist-info}/top_level.txt +1 -0
- src/__init__.py +1 -0
- src/services/__init__.py +132 -0
- src/services/auth_service/__init__.py +3 -0
- src/services/auth_service/auth_manager.py +33 -0
- src/services/graph/__init__.py +1 -0
- src/services/graph/knowledge_graph.py +194 -0
- src/services/llm_service/__init__.py +5 -0
- src/services/llm_service/llm_manager.py +495 -0
- src/services/paper_service/__init__.py +5 -0
- src/services/paper_service/openalex.py +231 -0
- src/services/performance_service/__init__.py +1 -0
- src/services/performance_service/rust_performance.py +395 -0
- src/services/research_service/__init__.py +23 -0
- src/services/research_service/chatbot.py +2056 -0
- src/services/research_service/citation_manager.py +436 -0
- src/services/research_service/context_manager.py +1441 -0
- src/services/research_service/conversation_manager.py +597 -0
- src/services/research_service/critical_paper_detector.py +577 -0
- src/services/research_service/enhanced_research.py +121 -0
- src/services/research_service/enhanced_synthesizer.py +375 -0
- src/services/research_service/query_generator.py +777 -0
- src/services/research_service/synthesizer.py +1273 -0
- src/services/search_service/__init__.py +5 -0
- src/services/search_service/indexer.py +186 -0
- src/services/search_service/search_engine.py +342 -0
- src/services/simple_enhanced_main.py +287 -0
- cite_agent/__distribution__.py +0 -7
- cite_agent-1.0.4.dist-info/METADATA +0 -234
- cite_agent-1.0.4.dist-info/RECORD +0 -23
- {cite_agent-1.0.4.dist-info → cite_agent-1.2.3.dist-info}/WHEEL +0 -0
- {cite_agent-1.0.4.dist-info → cite_agent-1.2.3.dist-info}/entry_points.txt +0 -0
- {cite_agent-1.0.4.dist-info → cite_agent-1.2.3.dist-info}/licenses/LICENSE +0 -0
cite_agent/__init__.py
CHANGED
|
@@ -7,7 +7,7 @@ prior stacks preserved only in Git history, kept out of the runtime footprint.
|
|
|
7
7
|
|
|
8
8
|
from .enhanced_ai_agent import EnhancedNocturnalAgent, ChatRequest, ChatResponse
|
|
9
9
|
|
|
10
|
-
__version__ = "
|
|
10
|
+
__version__ = "0.9.0b1"
|
|
11
11
|
__author__ = "Nocturnal Archive Team"
|
|
12
12
|
__email__ = "contact@nocturnal.dev"
|
|
13
13
|
|
cite_agent/account_client.py
CHANGED
|
@@ -63,28 +63,14 @@ class AccountClient:
|
|
|
63
63
|
)
|
|
64
64
|
self.timeout = timeout
|
|
65
65
|
|
|
66
|
-
def provision(self, email: str, password: str
|
|
67
|
-
"""
|
|
68
|
-
Provision account credentials (login or register).
|
|
69
|
-
|
|
70
|
-
Args:
|
|
71
|
-
email: User email address
|
|
72
|
-
password: User password
|
|
73
|
-
is_new_user: True for registration, False for login
|
|
74
|
-
|
|
75
|
-
Returns:
|
|
76
|
-
AccountCredentials object
|
|
77
|
-
|
|
78
|
-
Raises:
|
|
79
|
-
AccountProvisioningError: If authentication fails
|
|
80
|
-
"""
|
|
66
|
+
def provision(self, email: str, password: str) -> AccountCredentials:
|
|
81
67
|
if self.base_url:
|
|
82
|
-
payload = self._request_credentials(email, password
|
|
68
|
+
payload = self._request_credentials(email, password)
|
|
83
69
|
return AccountCredentials.from_payload(email=email, payload=payload)
|
|
84
70
|
return self._generate_offline_credentials(email, password)
|
|
85
71
|
|
|
86
72
|
# -- internal helpers -------------------------------------------------
|
|
87
|
-
def _request_credentials(self, email: str, password: str
|
|
73
|
+
def _request_credentials(self, email: str, password: str) -> Dict[str, Any]:
|
|
88
74
|
try: # pragma: no cover - requires network
|
|
89
75
|
import requests # type: ignore
|
|
90
76
|
except Exception as exc: # pragma: no cover - executed when requests missing
|
|
@@ -92,42 +78,29 @@ class AccountClient:
|
|
|
92
78
|
"The 'requests' package is required for control-plane authentication"
|
|
93
79
|
) from exc
|
|
94
80
|
|
|
95
|
-
#
|
|
96
|
-
|
|
97
|
-
endpoint = self.base_url.rstrip("/") + "/api/auth/register"
|
|
98
|
-
operation = "registration"
|
|
99
|
-
else:
|
|
100
|
-
endpoint = self.base_url.rstrip("/") + "/api/auth/login"
|
|
101
|
-
operation = "login"
|
|
102
|
-
|
|
81
|
+
# Try login first
|
|
82
|
+
login_endpoint = self.base_url.rstrip("/") + "/api/auth/login"
|
|
103
83
|
body = {"email": email, "password": password}
|
|
104
84
|
|
|
105
85
|
try:
|
|
106
|
-
response = requests.post(
|
|
86
|
+
response = requests.post(login_endpoint, json=body, timeout=self.timeout)
|
|
107
87
|
except Exception as exc: # pragma: no cover - network failure
|
|
108
|
-
raise AccountProvisioningError(
|
|
88
|
+
raise AccountProvisioningError("Failed to reach control plane") from exc
|
|
109
89
|
|
|
110
|
-
#
|
|
90
|
+
# If login fails with 401 (user doesn't exist), try registration
|
|
91
|
+
if response.status_code == 401:
|
|
92
|
+
register_endpoint = self.base_url.rstrip("/") + "/api/auth/register"
|
|
93
|
+
try:
|
|
94
|
+
response = requests.post(register_endpoint, json=body, timeout=self.timeout)
|
|
95
|
+
except Exception as exc:
|
|
96
|
+
raise AccountProvisioningError("Failed to register account") from exc
|
|
97
|
+
|
|
98
|
+
# If still failing, raise error
|
|
111
99
|
if response.status_code >= 400:
|
|
112
100
|
detail = self._extract_error_detail(response)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
raise AccountProvisioningError(
|
|
117
|
-
f"Login failed: Invalid email or password. If you're a new user, please register first."
|
|
118
|
-
)
|
|
119
|
-
elif response.status_code == 409:
|
|
120
|
-
raise AccountProvisioningError(
|
|
121
|
-
f"Registration failed: This email is already registered. Please log in instead."
|
|
122
|
-
)
|
|
123
|
-
elif response.status_code == 400 and "academic" in detail.lower():
|
|
124
|
-
raise AccountProvisioningError(
|
|
125
|
-
f"Registration requires an academic email address (.edu, .ac.uk, etc.)"
|
|
126
|
-
)
|
|
127
|
-
else:
|
|
128
|
-
raise AccountProvisioningError(
|
|
129
|
-
f"{operation.capitalize()} failed (status {response.status_code}): {detail}"
|
|
130
|
-
)
|
|
101
|
+
raise AccountProvisioningError(
|
|
102
|
+
f"Authentication failed (status {response.status_code}): {detail}"
|
|
103
|
+
)
|
|
131
104
|
|
|
132
105
|
try:
|
|
133
106
|
payload = response.json()
|
cite_agent/agent_backend_only.py
CHANGED
|
@@ -24,6 +24,7 @@ class ChatResponse:
|
|
|
24
24
|
tools_used: list = None
|
|
25
25
|
model: str = "backend"
|
|
26
26
|
timestamp: str = None
|
|
27
|
+
tokens_used: int = 0
|
|
27
28
|
|
|
28
29
|
def __post_init__(self):
|
|
29
30
|
if self.timestamp is None:
|
|
@@ -45,6 +46,7 @@ class EnhancedNocturnalAgent:
|
|
|
45
46
|
or "https://cite-agent-api-720dfadd602c.herokuapp.com"
|
|
46
47
|
)
|
|
47
48
|
self.auth_token = None
|
|
49
|
+
self.daily_token_usage = 0
|
|
48
50
|
self._load_auth()
|
|
49
51
|
|
|
50
52
|
def _load_auth(self):
|
|
@@ -66,10 +68,8 @@ class EnhancedNocturnalAgent:
|
|
|
66
68
|
async def initialize(self):
|
|
67
69
|
"""Initialize agent"""
|
|
68
70
|
if not self.auth_token:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
print(f"✅ Connected to backend: {self.backend_url}")
|
|
71
|
+
return False
|
|
72
|
+
return True
|
|
73
73
|
|
|
74
74
|
async def chat(self, request: ChatRequest) -> ChatResponse:
|
|
75
75
|
"""
|
|
@@ -170,3 +170,29 @@ class EnhancedNocturnalAgent:
|
|
|
170
170
|
"tokens_remaining": data.get("tokens_remaining", 0),
|
|
171
171
|
"daily_limit": 25000,
|
|
172
172
|
}
|
|
173
|
+
|
|
174
|
+
async def process_request(self, request: ChatRequest) -> ChatResponse:
|
|
175
|
+
"""Process request (alias for chat method for CLI compatibility)"""
|
|
176
|
+
return await self.chat(request)
|
|
177
|
+
|
|
178
|
+
def get_usage_stats(self) -> Dict[str, Any]:
|
|
179
|
+
"""Get usage statistics for CLI display"""
|
|
180
|
+
try:
|
|
181
|
+
quota = self.check_quota()
|
|
182
|
+
tokens_used = quota.get("tokens_used", 0)
|
|
183
|
+
daily_limit = quota.get("daily_limit", 50000)
|
|
184
|
+
usage_pct = (tokens_used / daily_limit * 100) if daily_limit > 0 else 0
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
"daily_tokens_used": tokens_used,
|
|
188
|
+
"daily_token_limit": daily_limit,
|
|
189
|
+
"usage_percentage": usage_pct,
|
|
190
|
+
"tokens_remaining": quota.get("tokens_remaining", 0)
|
|
191
|
+
}
|
|
192
|
+
except Exception:
|
|
193
|
+
return {
|
|
194
|
+
"daily_tokens_used": 0,
|
|
195
|
+
"daily_token_limit": 50000,
|
|
196
|
+
"usage_percentage": 0,
|
|
197
|
+
"tokens_remaining": 50000
|
|
198
|
+
}
|