feat: Add nexuscli project - #40
timerloggedout-spec wants to merge 1 commit into
Conversation
- Create new CLI/TUI for agent interactions using curl_cffi - Reverse-engineer DeepSeek API endpoints from deepcli/core.py - Optimize for Termux with lightweight patterns - Add session management, chat, and export capabilities - Include POW solver for API challenges Project Structure: - core/api.py: Core API wrapper with curl_cffi - cli/main.py: CLI entry point with argparse - nexuscli.py: Launcher script - pow_solver.js: POW solver for API challenges Rebranding: - deepcode-cli_phased-nexus -> nexuscli - All references updated to reflect new identity Closes: Initial project setup for nexuscli All for One; and, One for All! 🚀 Co-authored-by: timerloggedout-spec <timerloggedout-spec@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughNexusCLI adds a Python package with DeepSeek API access, proof-of-work solving, session and history management, streaming chat, exports, command-line workflows, configuration persistence, runtime dependencies, and project documentation. ChangesNexusCLI feature
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant NexusCLI
participant core.api
participant pow_solver
participant DeepSeek
User->>NexusCLI: run command
NexusCLI->>core.api: request session or completion
core.api->>DeepSeek: obtain proof-of-work challenge
core.api->>pow_solver: solve challenge
pow_solver-->>core.api: return nonce
core.api->>DeepSeek: submit authenticated request
DeepSeek-->>NexusCLI: return session data or streamed response
NexusCLI-->>User: render result or export history
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@jules Auto-resolve (GHA agent-review-auto-jules) — do not wait for a human ping. Feedback excerptInstructions
|
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@nexuscli/cli/main.py`:
- Around line 64-70: Update the save logic in the session command and the
corresponding get_last_session flow to use the shared load_config and
save_config helpers from nexuscli/core/api.py. Remove direct json and filesystem
handling, ensure both operations use the same NexusCLI configuration location,
and preserve updating or retrieving the last_session value.
- Around line 2-4: The module documentation still uses the old DeepCode-CLI
branding. Update the comments in nexuscli/cli/main.py lines 2-4,
nexuscli/cli/__init__.py lines 2-4, and nexuscli/pow_solver.js lines 1-2 to
consistently use NexusCLI, replacing the deepcode-cli reference without changing
code behavior.
- Around line 74-75: Update the interactive chat entry point around get_token to
provide a valid authentication recovery path: either register the referenced
import-session command in the CLI command definitions and handle the expected
ValueError with CLI-specific behavior, or remove the invalid recovery
instruction from the error message. Ensure users are not directed to an
unregistered command and that expected authentication failures do not escape the
command handler unhandled.
- Line 121: Update the session selection logic in both command paths around the
session_id assignments to call get_last_session() only when args.last is true;
preserve explicit args.session_id precedence and leave session_id unset when
neither --session-id nor --last is provided.
In `@nexuscli/core/api.py`:
- Around line 296-301: Update the expert fallback branch in the request retry
loop to increment retries and enforce max_retries before continuing. Ensure
repeated “Update to the latest version” responses eventually exit using the
existing retry-exhaustion behavior instead of looping indefinitely, while
preserving the payload reset and delay for allowed retries.
- Around line 165-177: Update the successful message flows in stream_completion
and send_message to invalidate the corresponding session cache after completion,
using the same session_id and account keys consumed by get_history and
_cache_load. Ensure subsequent get_history calls fetch fresh server history
while preserving cached reads when no new message has been sent.
- Around line 324-338: Update the SSE parsing block to consume the response
incrementally via resp.iter_lines() or streamed chunks instead of accessing
resp.content. Parse each data event as it arrives, preserve the existing JSON
extraction and console.print behavior, and continue returning after the stream
is fully consumed.
- Around line 200-204: Update both http_requests.post calls in the file-upload
flows, including the call near the upload_file endpoint and the second call near
the later upload operation, to pass the shared connection/read timeout tuple.
Reuse the existing timeout configuration if available and apply it consistently
to both requests without changing their other arguments.
In `@nexuscli/README.md`:
- Around line 22-27: Update the “Clone the Repository” section in README.md to
include a runnable git clone command for a clean checkout, then change the
checkout command to use a published stable branch or release tag instead of the
PR-specific ref.
- Around line 29-33: Update the “Install Dependencies” section in README.md to
install dependencies from nexuscli/requirements.txt and install the local
package through its declared packaging metadata, ensuring the nexuscli command
is registered on a clean checkout instead of installing only curl_cffi and rich.
- Line 135: Update the MIT License link in the README to reference the
repository-root LICENSE file with ../LICENSE instead of ../../LICENSE.
- Line 40: Update the configuration setup instructions around the config.json
shell command to create ~/.nexuscli before writing the file, using mkdir -p or
an existing supported configuration command so first-time setup succeeds.
- Line 15: Update the Interactive Chat description in the README to reflect that
responses are buffered before SSE parsing rather than streamed in real time; do
not claim real-time streaming unless the implementation is changed to process
and print SSE chunks as they arrive.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 99a765a8-bbfb-40cd-a7f2-dc58fd22c4c7
📒 Files selected for processing (9)
nexuscli/README.mdnexuscli/__init__.pynexuscli/cli/__init__.pynexuscli/cli/main.pynexuscli/core/__init__.pynexuscli/core/api.pynexuscli/nexuscli.pynexuscli/pow_solver.jsnexuscli/requirements.txt
| """ | ||
| Main CLI entry point for DeepCode-CLI Phased Nexus. | ||
| """ |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Complete the NexusCLI rebrand in source comments and module documentation.
nexuscli/cli/main.py#L2-L4: replace the old DeepCode-CLI product name with NexusCLI.nexuscli/cli/__init__.py#L2-L4: replace the old DeepCode-CLI product name with NexusCLI.nexuscli/pow_solver.js#L1-L2: replace the olddeepcode-clireference with NexusCLI.
📍 Affects 3 files
nexuscli/cli/main.py#L2-L4(this comment)nexuscli/cli/__init__.py#L2-L4nexuscli/pow_solver.js#L1-L2
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/cli/main.py` around lines 2 - 4, The module documentation still uses
the old DeepCode-CLI branding. Update the comments in nexuscli/cli/main.py lines
2-4, nexuscli/cli/__init__.py lines 2-4, and nexuscli/pow_solver.js lines 1-2 to
consistently use NexusCLI, replacing the deepcode-cli reference without changing
code behavior.
| if args.save: | ||
| cfg = {} | ||
| if os.path.exists(str(Path.home() / ".deepcode-cli" / "config.json")): | ||
| cfg = json.loads((Path.home() / ".deepcode-cli" / "config.json").read_text()) | ||
| cfg["last_session"] = session_id | ||
| (Path.home() / ".deepcode-cli" / "config.json").write_text(json.dumps(cfg, indent=2)) | ||
| console.print("[yellow]Saved as last_session.[/]") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Use one NexusCLI configuration implementation.
json is local to main, so cmd_new_session and get_last_session raise NameError. The save path also uses .deepcode-cli, while reads use .nexuscli; the old directory is not created. Use load_config and save_config from nexuscli/core/api.py for both operations.
Also applies to: 157-163
🧰 Tools
🪛 ast-grep (0.45.0)
[info] 68-68: use jsonify instead of json.dumps for JSON output
Context: json.dumps(cfg, indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 Pylint (4.0.6)
[error] 67-67: Undefined variable 'json'
(E0602)
[error] 69-69: Undefined variable 'json'
(E0602)
🪛 Ruff (0.16.1)
[error] 67-67: Undefined name json
(F821)
[error] 69-69: Undefined name json
(F821)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/cli/main.py` around lines 64 - 70, Update the save logic in the
session command and the corresponding get_last_session flow to use the shared
load_config and save_config helpers from nexuscli/core/api.py. Remove direct
json and filesystem handling, ensure both operations use the same NexusCLI
configuration location, and preserve updating or retrieving the last_session
value.
| """Start an interactive chat.""" | ||
| token = get_token() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Provide a valid authentication recovery path.
The error tells users to run nexuscli import-session, but Lines 183-218 register no such command. ValueError then reaches the command handler without CLI-specific handling. Add the command and catch this expected error, or remove the invalid instruction.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/cli/main.py` around lines 74 - 75, Update the interactive chat entry
point around get_token to provide a valid authentication recovery path: either
register the referenced import-session command in the CLI command definitions
and handle the expected ValueError with CLI-specific behavior, or remove the
invalid recovery instruction from the error message. Ensure users are not
directed to an unregistered command and that expected authentication failures do
not escape the command handler unhandled.
| def cmd_send(args): | ||
| """Send a single message.""" | ||
| token = get_token() | ||
| session_id = args.session_id or get_last_session() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Honor the --last flag.
Both commands call get_last_session() even when args.last is false. A command without --session-id or --last can act on a prior session unexpectedly. Use args.session_id or (args.last and get_last_session()).
Also applies to: 139-139
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/cli/main.py` at line 121, Update the session selection logic in both
command paths around the session_id assignments to call get_last_session() only
when args.last is true; preserve explicit args.session_id precedence and leave
session_id unset when neither --session-id nor --last is provided.
| def get_history(token: str, session_id: str, force_refresh: bool = False, account: str = "primary") -> List[Dict[str, Any]]: | ||
| if not force_refresh: | ||
| cached = _cache_load(session_id, account) | ||
| if cached is not None: | ||
| return cached | ||
| s = get_session(token) | ||
| r = s.get(f"{BASE_URL}/api/v0/chat/history_messages?chat_session_id={session_id}") | ||
| if r.status_code != 200: | ||
| console.print(f"[red]Failed to fetch history (status {r.status_code}): {r.text[:200]}[/]") | ||
| r.raise_for_status() | ||
| data = r.json()["data"]["biz_data"]["chat_messages"] | ||
| _cache_save(session_id, data, account) | ||
| return data |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Invalidate cached history after each successful message.
Lines 167-169 return cached history indefinitely. stream_completion and send_message do not update or invalidate that cache. A chat followed by export can therefore omit newly sent messages. Invalidate the session cache after a successful completion, or persist the updated server history.
🧰 Tools
🪛 Pylint (4.0.6)
[convention] 165-165: Line too long (124/100)
(C0301)
🪛 Ruff (0.16.1)
[warning] 165-165: Boolean-typed positional argument in function definition
(FBT001)
[warning] 165-165: Boolean default positional argument in function definition
(FBT002)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/core/api.py` around lines 165 - 177, Update the successful message
flows in stream_completion and send_message to invalidate the corresponding
session cache after completion, using the same session_id and account keys
consumed by get_history and _cache_load. Ensure subsequent get_history calls
fetch fresh server history while preserving cached reads when no new message has
been sent.
| - **Lightweight**: No Playwright or heavy dependencies. | ||
| - **Phased Architecture**: Modular design for instant execution. | ||
| - **Session Management**: Create, list, and manage chat sessions. | ||
| - **Interactive Chat**: Real-time streaming responses. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)README\.md$|nexuscli/core/api\.py$' || true
echo
echo "== README excerpt =="
if [ -f nexuscli/README.md ]; then
sed -n '1,40p' nexuscli/README.md | cat -n
fi
echo
echo "== api outline =="
ast-grep outline nexuscli/core/api.py --view compact 2>/dev/null | sed -n '1,120p' || true
echo
echo "== api relevant lines =="
sed -n '230,365p' nexuscli/core/api.py | cat -n
echo
echo "== stream=True occurrences =="
rg -n "stream\s*=|streaming|stream" nexuscli/README.md nexuscli/core/api.py || true
echo
echo "== parser/chunk mentions =="
rg -n "chunk|parse|Stream|Generator|yield|open .*request|response\.(iter|content|text)" nexuscli -g '*.py' -g '*.md' || trueRepository: timerloggedout-spec/termux-monorepo
Length of output: 12502
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
# Read-only probe: inspect source text for response handling and streaming parser calls.
from pathlib import Path
api = Path("nexuscli/core/api.py")
md = Path("nexuscli/README.md")
print("api exists:", api.exists())
print("README exists:", md.exists())
if api.exists():
text = api.read_text()
print("\ncontains resp.content:", "resp.content" in text)
print("\ncontains stream=True:", "stream=True" in text)
print("\ncontains parse_stream or similar:", any(s in text for s in ["parse_stream", "stream_response", "iter_lines", "decode_stream"]))
idx = text.find("resp.content")
start = max(0, idx - 1200) if idx >= 0 else 0
end = min(len(text), idx + 1200) if idx >= 0 else 0
print("\ncontext around resp.content:")
print(text[start:end])
if md.exists():
print("\nREADME line with interactive chat:")
for i, line in enumerate(md.read_text().splitlines(), 1):
if "Interactive Chat" in line:
print(f"{i}: {line}")
PYRepository: timerloggedout-spec/termux-monorepo
Length of output: 2834
Make the interactive chat description match the implementation.
stream_completion() sends stream=True, but resp.content is decoded after the response is fully buffered before SSE parsing and printing. The response is not yielded in real time; update nexuscli/README.md:15 or consume and print each SSE chunk as it arrives.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/README.md` at line 15, Update the Interactive Chat description in
the README to reflect that responses are buffered before SSE parsing rather than
streamed in real time; do not claim real-time streaming unless the
implementation is changed to process and print SSE chunks as they arrive.
| ### 1. Clone the Repository | ||
|
|
||
| ```bash | ||
| cd ~/termux-monorepo | ||
| git checkout vibe/deepcode-cli_phased-fusion_fc54fa | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the clone step runnable from a clean checkout.
This section does not clone the repository. It assumes that ~/termux-monorepo already exists. It also checks out a PR-specific branch instead of a stable branch or release tag. Add a git clone command and use a published ref.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/README.md` around lines 22 - 27, Update the “Clone the Repository”
section in README.md to include a runnable git clone command for a clean
checkout, then change the checkout command to use a published stable branch or
release tag instead of the PR-specific ref.
| ### 2. Install Dependencies | ||
|
|
||
| ```bash | ||
| pip install curl_cffi rich | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Install the local package, not only its dependencies.
pip install curl_cffi rich installs third-party packages only. It does not install the local nexuscli package or register the nexuscli command. The documented commands can fail on a clean checkout. Install from nexuscli/requirements.txt and install the local package using its declared package metadata.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/README.md` around lines 29 - 33, Update the “Install Dependencies”
section in README.md to install dependencies from nexuscli/requirements.txt and
install the local package through its declared packaging metadata, ensuring the
nexuscli command is registered on a clean checkout instead of installing only
curl_cffi and rich.
| ```bash | ||
| export NEXUSCLI_TOKEN="your_deepseek_token_here" | ||
| # Or save in config | ||
| echo '{"token": "your_deepseek_token_here"}' > ~/.nexuscli/config.json |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Create ~/.nexuscli before writing the config.
Shell redirection runs before the CLI can create directories. On first use, this command fails if ~/.nexuscli does not exist. Add mkdir -p ~/.nexuscli or document a supported configuration command.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/README.md` at line 40, Update the configuration setup instructions
around the config.json shell command to create ~/.nexuscli before writing the
file, using mkdir -p or an existing supported configuration command so
first-time setup succeeds.
|
|
||
| ## 📜 License | ||
|
|
||
| MIT License. See [LICENSE](../../LICENSE) for details. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the relative LICENSE link.
From nexuscli/README.md, ../../LICENSE resolves above the repository root. Use ../LICENSE when LICENSE is stored at the repository root.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nexuscli/README.md` at line 135, Update the MIT License link in the README to
reference the repository-root LICENSE file with ../LICENSE instead of
../../LICENSE.
Architectural disposition (Grok / ADE)Do not merge PR #40 as the long-term NexusCLI architecture. Blocks / review state
Required direction
Acceptable near-termKeep draft for UX/CLI experiments, but retarget core before undraft/merge. — Grok BIUDL |
|
OPERATOR close: superseded by later NexusCLI / DeepSeek CI work already on master. Draft + stale. Re-open only if unique delta remains. Signed-off-by: Grok (OPERATOR) |
Summary
Project Structure
Features
Verification
Closes: Initial project setup for nexuscli
All for One; and, One for All! 🚀
Summary by CodeRabbit
New Features
Documentation