neuroncli 2.1.0__tar.gz → 2.2.0__tar.gz
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.
- {neuroncli-2.1.0 → neuroncli-2.2.0}/PKG-INFO +13 -6
- {neuroncli-2.1.0 → neuroncli-2.2.0}/README.md +12 -5
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/auth.py +63 -11
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/config.py +1 -1
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli.egg-info/PKG-INFO +13 -6
- {neuroncli-2.1.0 → neuroncli-2.2.0}/pyproject.toml +1 -1
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/__init__.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/__main__.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/agent.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/cli.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/git_integration.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/ollama_client.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/openrouter_client.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/prompts.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/provider.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/session.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/tools.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli/ui.py +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli.egg-info/SOURCES.txt +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli.egg-info/dependency_links.txt +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli.egg-info/entry_points.txt +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli.egg-info/requires.txt +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/neuroncli.egg-info/top_level.txt +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/setup.cfg +0 -0
- {neuroncli-2.1.0 → neuroncli-2.2.0}/tests/test_agent.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuroncli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: AI Coding Agent — Free Claude Code alternative powered by Kimi K2.5 + Ollama
|
|
5
5
|
Author-email: Rahul S <rahultech72216@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -34,17 +34,24 @@ Requires-Dist: requests>=2.28.0
|
|
|
34
34
|
## Install
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
#
|
|
37
|
+
# Windows
|
|
38
38
|
pip install neuroncli
|
|
39
39
|
|
|
40
|
-
#
|
|
40
|
+
# Linux / macOS (modern distros use pipx)
|
|
41
|
+
pipx install neuroncli
|
|
42
|
+
|
|
43
|
+
# If pipx not installed:
|
|
44
|
+
# sudo apt install pipx && pipx ensurepath (Debian/Ubuntu)
|
|
45
|
+
# sudo dnf install pipx && pipx ensurepath (Fedora)
|
|
46
|
+
# brew install pipx && pipx ensurepath (macOS)
|
|
47
|
+
|
|
48
|
+
# From source (any platform)
|
|
41
49
|
git clone https://github.com/RAHUL-DevelopeRR/neuroncli.git
|
|
42
|
-
cd neuroncli
|
|
43
|
-
pip install -e .
|
|
50
|
+
cd neuroncli && pip install -e .
|
|
44
51
|
```
|
|
45
52
|
|
|
46
53
|
```bash
|
|
47
|
-
# Linux/macOS
|
|
54
|
+
# Linux/macOS auto-install script
|
|
48
55
|
curl -fsSL https://raw.githubusercontent.com/RAHUL-DevelopeRR/neuroncli/master/install.sh | bash
|
|
49
56
|
```
|
|
50
57
|
|
|
@@ -9,17 +9,24 @@
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
#
|
|
12
|
+
# Windows
|
|
13
13
|
pip install neuroncli
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Linux / macOS (modern distros use pipx)
|
|
16
|
+
pipx install neuroncli
|
|
17
|
+
|
|
18
|
+
# If pipx not installed:
|
|
19
|
+
# sudo apt install pipx && pipx ensurepath (Debian/Ubuntu)
|
|
20
|
+
# sudo dnf install pipx && pipx ensurepath (Fedora)
|
|
21
|
+
# brew install pipx && pipx ensurepath (macOS)
|
|
22
|
+
|
|
23
|
+
# From source (any platform)
|
|
16
24
|
git clone https://github.com/RAHUL-DevelopeRR/neuroncli.git
|
|
17
|
-
cd neuroncli
|
|
18
|
-
pip install -e .
|
|
25
|
+
cd neuroncli && pip install -e .
|
|
19
26
|
```
|
|
20
27
|
|
|
21
28
|
```bash
|
|
22
|
-
# Linux/macOS
|
|
29
|
+
# Linux/macOS auto-install script
|
|
23
30
|
curl -fsSL https://raw.githubusercontent.com/RAHUL-DevelopeRR/neuroncli/master/install.sh | bash
|
|
24
31
|
```
|
|
25
32
|
|
|
@@ -27,8 +27,10 @@ from pathlib import Path
|
|
|
27
27
|
|
|
28
28
|
CONFIG_DIR = Path.home() / ".neuroncli"
|
|
29
29
|
CONFIG_FILE = CONFIG_DIR / "config.json"
|
|
30
|
-
CALLBACK_PORT = 19284 #
|
|
31
|
-
|
|
30
|
+
CALLBACK_PORT = 19284 # Local server port to catch the redirect from zero-x.live
|
|
31
|
+
LOCAL_CALLBACK = f"http://localhost:{CALLBACK_PORT}"
|
|
32
|
+
# OpenRouter callback → zero-x.live → redirects to localhost with ?code=
|
|
33
|
+
CALLBACK_URL = "https://zero-x.live/neuroncli/callback"
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
# ── PKCE helpers ──────────────────────────────────────────────────
|
|
@@ -78,10 +80,22 @@ def store_api_key(key: str) -> None:
|
|
|
78
80
|
# ── OAuth PKCE flow ──────────────────────────────────────────────
|
|
79
81
|
|
|
80
82
|
class _OAuthCallbackHandler(http.server.BaseHTTPRequestHandler):
|
|
81
|
-
"""Tiny HTTP handler that captures the OAuth redirect code.
|
|
83
|
+
"""Tiny HTTP handler that captures the OAuth redirect code.
|
|
84
|
+
Handles redirects from zero-x.live callback page."""
|
|
82
85
|
|
|
83
86
|
auth_code: str | None = None
|
|
84
87
|
|
|
88
|
+
def _send_cors_headers(self):
|
|
89
|
+
"""Allow cross-origin requests from zero-x.live."""
|
|
90
|
+
self.send_header("Access-Control-Allow-Origin", "*")
|
|
91
|
+
self.send_header("Access-Control-Allow-Methods", "GET, OPTIONS")
|
|
92
|
+
|
|
93
|
+
def do_OPTIONS(self):
|
|
94
|
+
"""Handle CORS preflight."""
|
|
95
|
+
self.send_response(200)
|
|
96
|
+
self._send_cors_headers()
|
|
97
|
+
self.end_headers()
|
|
98
|
+
|
|
85
99
|
def do_GET(self):
|
|
86
100
|
parsed = urllib.parse.urlparse(self.path)
|
|
87
101
|
params = urllib.parse.parse_qs(parsed.query)
|
|
@@ -93,6 +107,7 @@ class _OAuthCallbackHandler(http.server.BaseHTTPRequestHandler):
|
|
|
93
107
|
# Show success page
|
|
94
108
|
self.send_response(200)
|
|
95
109
|
self.send_header("Content-Type", "text/html")
|
|
110
|
+
self._send_cors_headers()
|
|
96
111
|
self.end_headers()
|
|
97
112
|
self.wfile.write(b"""
|
|
98
113
|
<html>
|
|
@@ -112,7 +127,7 @@ class _OAuthCallbackHandler(http.server.BaseHTTPRequestHandler):
|
|
|
112
127
|
border-radius: 24px;
|
|
113
128
|
backdrop-filter: blur(20px);
|
|
114
129
|
}
|
|
115
|
-
h1 { color: #
|
|
130
|
+
h1 { color: #f0a028; font-size: 2em; }
|
|
116
131
|
p { color: #aaa; font-size: 1.1em; }
|
|
117
132
|
</style>
|
|
118
133
|
</head>
|
|
@@ -189,7 +204,12 @@ def run_oauth_flow() -> str | None:
|
|
|
189
204
|
)
|
|
190
205
|
|
|
191
206
|
# Start callback server in background
|
|
192
|
-
|
|
207
|
+
try:
|
|
208
|
+
server = http.server.HTTPServer(("127.0.0.1", CALLBACK_PORT), _OAuthCallbackHandler)
|
|
209
|
+
except OSError:
|
|
210
|
+
# Port in use — another instance is running
|
|
211
|
+
print(f"\n \033[91m[X] Port {CALLBACK_PORT} is in use. Close other instances first.\033[0m")
|
|
212
|
+
return None
|
|
193
213
|
server.timeout = 120 # 2 minute timeout
|
|
194
214
|
|
|
195
215
|
print("\n \033[96m\033[1m[AUTH]\033[0m Opening browser for OpenRouter login...")
|
|
@@ -197,7 +217,10 @@ def run_oauth_flow() -> str | None:
|
|
|
197
217
|
print(f" \033[90m{auth_url[:80]}...\033[0m\n")
|
|
198
218
|
|
|
199
219
|
# Open browser
|
|
200
|
-
|
|
220
|
+
try:
|
|
221
|
+
webbrowser.open(auth_url)
|
|
222
|
+
except Exception:
|
|
223
|
+
print(" \033[90m(Browser could not be opened. Use the URL above.)\033[0m")
|
|
201
224
|
|
|
202
225
|
print(" \033[93mWaiting for authentication...\033[0m", end="", flush=True)
|
|
203
226
|
|
|
@@ -211,10 +234,10 @@ def run_oauth_flow() -> str | None:
|
|
|
211
234
|
|
|
212
235
|
code = _OAuthCallbackHandler.auth_code
|
|
213
236
|
if not code:
|
|
214
|
-
print(f"\n \033[91m[X]
|
|
215
|
-
return
|
|
237
|
+
print(f"\n \033[91m[X] OAuth timed out or failed.\033[0m")
|
|
238
|
+
return _manual_key_fallback()
|
|
216
239
|
|
|
217
|
-
print(f" \033[
|
|
240
|
+
print(f" \033[92mv\033[0m")
|
|
218
241
|
print(" \033[96mExchanging code for API key...\033[0m", end="", flush=True)
|
|
219
242
|
|
|
220
243
|
# Exchange code for key
|
|
@@ -222,16 +245,43 @@ def run_oauth_flow() -> str | None:
|
|
|
222
245
|
api_key = _exchange_code_for_key(code, code_verifier)
|
|
223
246
|
except RuntimeError as e:
|
|
224
247
|
print(f"\n \033[91m[X] {e}\033[0m")
|
|
225
|
-
return
|
|
248
|
+
return _manual_key_fallback()
|
|
226
249
|
|
|
227
250
|
# Store
|
|
228
251
|
store_api_key(api_key)
|
|
229
|
-
print(f" \033[
|
|
252
|
+
print(f" \033[92mv\033[0m")
|
|
230
253
|
print(f" \033[92m\033[1m[OK] API key saved to {CONFIG_FILE}\033[0m\n")
|
|
231
254
|
|
|
232
255
|
return api_key
|
|
233
256
|
|
|
234
257
|
|
|
258
|
+
def _manual_key_fallback() -> str | None:
|
|
259
|
+
"""Fallback: let user manually paste their OpenRouter API key."""
|
|
260
|
+
print(f"\n \033[96m\033[1m[MANUAL SETUP]\033[0m")
|
|
261
|
+
print(f" \033[90mOAuth didn't work. You can paste your key instead:\033[0m")
|
|
262
|
+
print(f" \033[90m1. Go to: https://openrouter.ai/settings/keys\033[0m")
|
|
263
|
+
print(f" \033[90m2. Click 'Create Key'\033[0m")
|
|
264
|
+
print(f" \033[90m3. Copy the key (starts with sk-or-...)\033[0m\n")
|
|
265
|
+
|
|
266
|
+
try:
|
|
267
|
+
key = input(" \033[93mPaste your API key (or Enter to skip): \033[0m").strip()
|
|
268
|
+
except (EOFError, KeyboardInterrupt):
|
|
269
|
+
return None
|
|
270
|
+
|
|
271
|
+
if not key:
|
|
272
|
+
print(f"\n \033[90mSkipped. Using Ollama fallback if available.\033[0m\n")
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
if key.startswith("sk-or-") or key.startswith("sk-"):
|
|
276
|
+
store_api_key(key)
|
|
277
|
+
print(f" \033[92m\033[1m[OK] API key saved to {CONFIG_FILE}\033[0m\n")
|
|
278
|
+
return key
|
|
279
|
+
else:
|
|
280
|
+
print(f" \033[91m[X] Invalid key format. Expected 'sk-or-...' \033[0m")
|
|
281
|
+
print(f" \033[90mGet one at: https://openrouter.ai/settings/keys\033[0m\n")
|
|
282
|
+
return None
|
|
283
|
+
|
|
284
|
+
|
|
235
285
|
# ── Public API ────────────────────────────────────────────────────
|
|
236
286
|
|
|
237
287
|
def ensure_api_key() -> str | None:
|
|
@@ -240,6 +290,7 @@ def ensure_api_key() -> str | None:
|
|
|
240
290
|
1. OPENROUTER_API_KEY env var
|
|
241
291
|
2. ~/.neuroncli/config.json
|
|
242
292
|
3. Interactive OAuth PKCE flow (first-run)
|
|
293
|
+
4. Manual key paste (fallback if OAuth fails)
|
|
243
294
|
|
|
244
295
|
Returns the API key or None if all methods fail.
|
|
245
296
|
"""
|
|
@@ -261,3 +312,4 @@ def ensure_api_key() -> str | None:
|
|
|
261
312
|
print(" ╚════════════════════════════════════════════════╝\033[0m")
|
|
262
313
|
|
|
263
314
|
return run_oauth_flow()
|
|
315
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuroncli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: AI Coding Agent — Free Claude Code alternative powered by Kimi K2.5 + Ollama
|
|
5
5
|
Author-email: Rahul S <rahultech72216@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -34,17 +34,24 @@ Requires-Dist: requests>=2.28.0
|
|
|
34
34
|
## Install
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
#
|
|
37
|
+
# Windows
|
|
38
38
|
pip install neuroncli
|
|
39
39
|
|
|
40
|
-
#
|
|
40
|
+
# Linux / macOS (modern distros use pipx)
|
|
41
|
+
pipx install neuroncli
|
|
42
|
+
|
|
43
|
+
# If pipx not installed:
|
|
44
|
+
# sudo apt install pipx && pipx ensurepath (Debian/Ubuntu)
|
|
45
|
+
# sudo dnf install pipx && pipx ensurepath (Fedora)
|
|
46
|
+
# brew install pipx && pipx ensurepath (macOS)
|
|
47
|
+
|
|
48
|
+
# From source (any platform)
|
|
41
49
|
git clone https://github.com/RAHUL-DevelopeRR/neuroncli.git
|
|
42
|
-
cd neuroncli
|
|
43
|
-
pip install -e .
|
|
50
|
+
cd neuroncli && pip install -e .
|
|
44
51
|
```
|
|
45
52
|
|
|
46
53
|
```bash
|
|
47
|
-
# Linux/macOS
|
|
54
|
+
# Linux/macOS auto-install script
|
|
48
55
|
curl -fsSL https://raw.githubusercontent.com/RAHUL-DevelopeRR/neuroncli/master/install.sh | bash
|
|
49
56
|
```
|
|
50
57
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|