cite-agent 1.0.3__py3-none-any.whl → 1.0.4__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 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__ = "1.0.3"
10
+ __version__ = "1.0.4"
11
11
  __author__ = "Nocturnal Archive Team"
12
12
  __email__ = "contact@nocturnal.dev"
13
13
 
@@ -63,14 +63,28 @@ class AccountClient:
63
63
  )
64
64
  self.timeout = timeout
65
65
 
66
- def provision(self, email: str, password: str) -> AccountCredentials:
66
+ def provision(self, email: str, password: str, is_new_user: bool = False) -> AccountCredentials:
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
+ """
67
81
  if self.base_url:
68
- payload = self._request_credentials(email, password)
82
+ payload = self._request_credentials(email, password, is_new_user=is_new_user)
69
83
  return AccountCredentials.from_payload(email=email, payload=payload)
70
84
  return self._generate_offline_credentials(email, password)
71
85
 
72
86
  # -- internal helpers -------------------------------------------------
73
- def _request_credentials(self, email: str, password: str) -> Dict[str, Any]:
87
+ def _request_credentials(self, email: str, password: str, is_new_user: bool = False) -> Dict[str, Any]:
74
88
  try: # pragma: no cover - requires network
75
89
  import requests # type: ignore
76
90
  except Exception as exc: # pragma: no cover - executed when requests missing
@@ -78,29 +92,42 @@ class AccountClient:
78
92
  "The 'requests' package is required for control-plane authentication"
79
93
  ) from exc
80
94
 
81
- # Try login first
82
- login_endpoint = self.base_url.rstrip("/") + "/api/auth/login"
95
+ # Choose endpoint based on is_new_user flag
96
+ if is_new_user:
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
+
83
103
  body = {"email": email, "password": password}
84
104
 
85
105
  try:
86
- response = requests.post(login_endpoint, json=body, timeout=self.timeout)
106
+ response = requests.post(endpoint, json=body, timeout=self.timeout)
87
107
  except Exception as exc: # pragma: no cover - network failure
88
- raise AccountProvisioningError("Failed to reach control plane") from exc
108
+ raise AccountProvisioningError(f"Failed to reach control plane for {operation}") from exc
89
109
 
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
110
+ # Handle errors
99
111
  if response.status_code >= 400:
100
112
  detail = self._extract_error_detail(response)
101
- raise AccountProvisioningError(
102
- f"Authentication failed (status {response.status_code}): {detail}"
103
- )
113
+
114
+ # Provide helpful error messages
115
+ if response.status_code == 401 and not is_new_user:
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
+ )
104
131
 
105
132
  try:
106
133
  payload = response.json()
cite_agent/cli.py CHANGED
@@ -442,7 +442,7 @@ Examples:
442
442
 
443
443
  # Handle version
444
444
  if args.version:
445
- print("Cite-Agent v1.0.3")
445
+ print("Cite-Agent v1.0.4")
446
446
  print("AI Research Assistant - Backend-Only Distribution")
447
447
  return
448
448
 
@@ -63,6 +63,18 @@ class NocturnalConfig:
63
63
  print("You'll use your institution-issued account to sign in. No invite codes or manual API keys required.")
64
64
  print()
65
65
 
66
+ # Ask if new user or returning user
67
+ print("Are you a new user or returning user?")
68
+ print(" 1. New user (register)")
69
+ print(" 2. Returning user (login)")
70
+ choice = input("Enter choice (1 or 2): ").strip()
71
+
72
+ is_new_user = choice == "1"
73
+ action = "Registration" if is_new_user else "Login"
74
+
75
+ print(f"\n{action}")
76
+ print("-" * 40)
77
+
66
78
  email = self._prompt_academic_email()
67
79
  if not email:
68
80
  return False
@@ -71,14 +83,18 @@ class NocturnalConfig:
71
83
  if not password:
72
84
  return False
73
85
 
74
- if not self._confirm_beta_terms():
86
+ if is_new_user and not self._confirm_beta_terms():
75
87
  print("❌ Terms must be accepted to continue")
76
88
  return False
77
89
 
78
90
  try:
79
- credentials = self._provision_account(email, password)
91
+ credentials = self._provision_account(email, password, is_new_user=is_new_user)
92
+ if is_new_user:
93
+ print(f"\n✅ Account created successfully for {email}")
94
+ else:
95
+ print(f"\n✅ Logged in successfully as {email}")
80
96
  except AccountProvisioningError as exc:
81
- print(f"❌ Could not verify your account: {exc}")
97
+ print(f"❌ {action} failed: {exc}")
82
98
  return False
83
99
 
84
100
  print("\n🛡️ Recap of beta limitations:")
@@ -163,9 +179,9 @@ class NocturnalConfig:
163
179
  print("❌ Could not confirm password after multiple attempts")
164
180
  return None
165
181
 
166
- def _provision_account(self, email: str, password: str) -> AccountCredentials:
182
+ def _provision_account(self, email: str, password: str, is_new_user: bool = False) -> AccountCredentials:
167
183
  client = AccountClient()
168
- return client.provision(email=email, password=password)
184
+ return client.provision(email=email, password=password, is_new_user=is_new_user)
169
185
 
170
186
  def _is_academic_email(self, email: str) -> bool:
171
187
  if "@" not in email:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cite-agent
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: AI Research Assistant - Backend-Only Distribution
5
5
  Home-page: https://github.com/Spectating101/cite-agent
6
6
  Author: Cite-Agent Team
@@ -1,23 +1,23 @@
1
1
  cite_agent/__distribution__.py,sha256=U7-p-qBMX7WrQD6WWjRC5b-PswXnlrqAox7EYnLogqI,178
2
- cite_agent/__init__.py,sha256=bIPMfQXuaDOCAZE9pWvqpRbuBlgOvfh9uLQ3pakBMOY,1643
3
- cite_agent/account_client.py,sha256=yLuzhIJoIZuXHXGbaVMzDxRATQwcy-wiaLnUrDuwUhI,5725
2
+ cite_agent/__init__.py,sha256=n12qGnmZ0th2OJTn5kBK-kzIEn_1EZgZ1qujT4-ZMeU,1643
3
+ cite_agent/account_client.py,sha256=kvILYFKGm6ktCdi7iKSP5dkOp7iOAcBEQ7giHOh711w,6723
4
4
  cite_agent/agent_backend_only.py,sha256=Rmi3cUCcTMSHRxZu6MK2rZwme5SCfilxqn0BsoIds_U,5375
5
5
  cite_agent/ascii_plotting.py,sha256=lk8BaECs6fmjtp4iH12G09-frlRehAN7HLhHt2crers,8570
6
6
  cite_agent/auth.py,sha256=CYBNv8r1_wfdhsx-YcWOiXCiKvPBymaMca6w7JV__FQ,9809
7
7
  cite_agent/backend_only_client.py,sha256=WqLF8x7aXTro2Q3ehqKMsdCg53s6fNk9Hy86bGxqmmw,2561
8
- cite_agent/cli.py,sha256=NYg-gCdV8M6WhUN9Y6TawsjdITfo_7WPOa6ZIknN4dc,18564
8
+ cite_agent/cli.py,sha256=T2zSv2ET3IKh1_ENfFIkW292KWC1lt-yUSdYn51Urw4,18564
9
9
  cite_agent/cli_enhanced.py,sha256=EAaSw9qtiYRWUXF6_05T19GCXlz9cCSz6n41ASnXIPc,7407
10
10
  cite_agent/dashboard.py,sha256=VGV5XQU1PnqvTsxfKMcue3j2ri_nvm9Be6O5aVays_w,10502
11
11
  cite_agent/enhanced_ai_agent.py,sha256=Rmi3cUCcTMSHRxZu6MK2rZwme5SCfilxqn0BsoIds_U,5375
12
12
  cite_agent/rate_limiter.py,sha256=-0fXx8Tl4zVB4O28n9ojU2weRo-FBF1cJo9Z5jC2LxQ,10908
13
- cite_agent/setup_config.py,sha256=kNZNr5cZmCXr43rGWNenNJXZ1Kfz7PrdLXpAqxM7WgM,16404
13
+ cite_agent/setup_config.py,sha256=fUVBxJ0CK7e5cGG4jBDpHbB2seC1RqEteneq-WslAw8,17064
14
14
  cite_agent/telemetry.py,sha256=55kXdHvI24ZsEkbFtihcjIfJt2oiSXcEpLzTxQ3KCdQ,2916
15
15
  cite_agent/ui.py,sha256=r1OAeY3NSeqhAjJYmEBH9CaennBuibFAz1Mur6YF80E,6134
16
16
  cite_agent/updater.py,sha256=kL2GYL1AKoZ9JoTXxFT5_AkvYvObcCrO2sIVyBw9JgU,7057
17
17
  cite_agent/web_search.py,sha256=j-BRhT8EBC6BEPgACQPeVwB1SVGKDz4XLM7sowacvSc,6587
18
- cite_agent-1.0.3.dist-info/licenses/LICENSE,sha256=XJkyO4IymhSUniN1ENY6lLrL2729gn_rbRlFK6_Hi9M,1074
19
- cite_agent-1.0.3.dist-info/METADATA,sha256=Ajj8pUFoOsTBQuNMRB6dELRoGhFi90CYbPSq1wQuO0I,6856
20
- cite_agent-1.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
- cite_agent-1.0.3.dist-info/entry_points.txt,sha256=bJ0u28nFIxQKH1PWQ2ak4PV-FAjhoxTC7YADEdDenFw,83
22
- cite_agent-1.0.3.dist-info/top_level.txt,sha256=NNfD8pxDZzBK8tjDIpCs2BW9Va-OQ5qUFbEx0SgmyIE,11
23
- cite_agent-1.0.3.dist-info/RECORD,,
18
+ cite_agent-1.0.4.dist-info/licenses/LICENSE,sha256=XJkyO4IymhSUniN1ENY6lLrL2729gn_rbRlFK6_Hi9M,1074
19
+ cite_agent-1.0.4.dist-info/METADATA,sha256=QklMsGqAD-NCLM1S4LHzCUSaeH58ld-IXG06NO24Bsw,6856
20
+ cite_agent-1.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
+ cite_agent-1.0.4.dist-info/entry_points.txt,sha256=bJ0u28nFIxQKH1PWQ2ak4PV-FAjhoxTC7YADEdDenFw,83
22
+ cite_agent-1.0.4.dist-info/top_level.txt,sha256=NNfD8pxDZzBK8tjDIpCs2BW9Va-OQ5qUFbEx0SgmyIE,11
23
+ cite_agent-1.0.4.dist-info/RECORD,,