nexcoder 0.1.0__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.
- nex/__init__.py +6 -0
- nex/agent.py +623 -0
- nex/api_client.py +194 -0
- nex/cli.py +506 -0
- nex/config.py +168 -0
- nex/context.py +252 -0
- nex/exceptions.py +39 -0
- nex/indexer/__init__.py +16 -0
- nex/indexer/index.py +332 -0
- nex/indexer/parser.py +352 -0
- nex/indexer/scanner.py +191 -0
- nex/memory/__init__.py +15 -0
- nex/memory/decisions.py +131 -0
- nex/memory/errors.py +257 -0
- nex/memory/project.py +158 -0
- nex/planner.py +122 -0
- nex/py.typed +0 -0
- nex/reviewer.py +111 -0
- nex/safety.py +235 -0
- nex/test_runner.py +201 -0
- nex/tools/__init__.py +114 -0
- nex/tools/file_ops.py +89 -0
- nex/tools/git_ops.py +183 -0
- nex/tools/search.py +156 -0
- nex/tools/shell.py +72 -0
- nexcoder-0.1.0.dist-info/METADATA +170 -0
- nexcoder-0.1.0.dist-info/RECORD +30 -0
- nexcoder-0.1.0.dist-info/WHEEL +4 -0
- nexcoder-0.1.0.dist-info/entry_points.txt +2 -0
- nexcoder-0.1.0.dist-info/licenses/LICENSE +21 -0
nex/tools/search.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""File search tool — ripgrep wrapper with Python fallback."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import re
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from nex.tools import ToolResult
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def search_files(
|
|
13
|
+
pattern: str,
|
|
14
|
+
path: str,
|
|
15
|
+
project_dir: Path,
|
|
16
|
+
max_results: int = 50,
|
|
17
|
+
) -> ToolResult:
|
|
18
|
+
"""Search files using ripgrep or fallback to Python grep.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
pattern: Regex pattern to search for.
|
|
22
|
+
path: Directory to search (relative to project root).
|
|
23
|
+
project_dir: Project root directory.
|
|
24
|
+
max_results: Maximum number of matches to return.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
ToolResult with matches in file:line:content format.
|
|
28
|
+
"""
|
|
29
|
+
search_dir = (project_dir / path).resolve()
|
|
30
|
+
project_root = project_dir.resolve()
|
|
31
|
+
if not str(search_dir).startswith(str(project_root)):
|
|
32
|
+
return ToolResult(success=False, output="", error="Path traversal blocked")
|
|
33
|
+
|
|
34
|
+
if not search_dir.is_dir():
|
|
35
|
+
return ToolResult(success=False, output="", error=f"Directory not found: {path}")
|
|
36
|
+
|
|
37
|
+
# Try ripgrep first
|
|
38
|
+
result = await _search_ripgrep(pattern, search_dir, max_results)
|
|
39
|
+
if result is not None:
|
|
40
|
+
return result
|
|
41
|
+
|
|
42
|
+
# Fallback to Python search
|
|
43
|
+
return _search_python(pattern, search_dir, project_root, max_results)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def _search_ripgrep(pattern: str, search_dir: Path, max_results: int) -> ToolResult | None:
|
|
47
|
+
"""Attempt search using ripgrep (rg).
|
|
48
|
+
|
|
49
|
+
Returns None if rg is not available.
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
process = await asyncio.create_subprocess_exec(
|
|
53
|
+
"rg",
|
|
54
|
+
"--no-heading",
|
|
55
|
+
"--line-number",
|
|
56
|
+
"--context",
|
|
57
|
+
"2",
|
|
58
|
+
"--max-count",
|
|
59
|
+
str(max_results),
|
|
60
|
+
"--color",
|
|
61
|
+
"never",
|
|
62
|
+
pattern,
|
|
63
|
+
str(search_dir),
|
|
64
|
+
stdout=asyncio.subprocess.PIPE,
|
|
65
|
+
stderr=asyncio.subprocess.PIPE,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=15)
|
|
69
|
+
|
|
70
|
+
if process.returncode == 2:
|
|
71
|
+
# rg error (bad pattern, etc.)
|
|
72
|
+
return ToolResult(
|
|
73
|
+
success=False,
|
|
74
|
+
output="",
|
|
75
|
+
error=f"Search error: {stderr.decode('utf-8', errors='replace')}",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
output = stdout.decode("utf-8", errors="replace")
|
|
79
|
+
if not output.strip():
|
|
80
|
+
return ToolResult(success=True, output="No matches found.")
|
|
81
|
+
|
|
82
|
+
return ToolResult(success=True, output=output)
|
|
83
|
+
|
|
84
|
+
except FileNotFoundError:
|
|
85
|
+
return None # rg not installed, fall back
|
|
86
|
+
except TimeoutError:
|
|
87
|
+
return ToolResult(success=False, output="", error="Search timed out")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _search_python(
|
|
91
|
+
pattern: str, search_dir: Path, project_root: Path, max_results: int
|
|
92
|
+
) -> ToolResult:
|
|
93
|
+
"""Fallback search using Python regex."""
|
|
94
|
+
try:
|
|
95
|
+
compiled = re.compile(pattern)
|
|
96
|
+
except re.error as exc:
|
|
97
|
+
return ToolResult(success=False, output="", error=f"Invalid regex: {exc}")
|
|
98
|
+
|
|
99
|
+
matches: list[str] = []
|
|
100
|
+
source_extensions = {
|
|
101
|
+
".py",
|
|
102
|
+
".js",
|
|
103
|
+
".ts",
|
|
104
|
+
".tsx",
|
|
105
|
+
".jsx",
|
|
106
|
+
".go",
|
|
107
|
+
".rs",
|
|
108
|
+
".java",
|
|
109
|
+
".rb",
|
|
110
|
+
".php",
|
|
111
|
+
".c",
|
|
112
|
+
".cpp",
|
|
113
|
+
".h",
|
|
114
|
+
".swift",
|
|
115
|
+
".kt",
|
|
116
|
+
".md",
|
|
117
|
+
".txt",
|
|
118
|
+
".toml",
|
|
119
|
+
".yaml",
|
|
120
|
+
".yml",
|
|
121
|
+
".json",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
for file_path in search_dir.rglob("*"):
|
|
125
|
+
if len(matches) >= max_results:
|
|
126
|
+
break
|
|
127
|
+
if not file_path.is_file():
|
|
128
|
+
continue
|
|
129
|
+
if file_path.suffix not in source_extensions:
|
|
130
|
+
continue
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
content = file_path.read_text(encoding="utf-8", errors="replace")
|
|
134
|
+
lines = content.splitlines()
|
|
135
|
+
rel_path = file_path.relative_to(project_root)
|
|
136
|
+
|
|
137
|
+
for i, line in enumerate(lines, start=1):
|
|
138
|
+
if compiled.search(line):
|
|
139
|
+
# Include 2 lines of context
|
|
140
|
+
start = max(0, i - 3)
|
|
141
|
+
end = min(len(lines), i + 2)
|
|
142
|
+
context_lines = []
|
|
143
|
+
for j in range(start, end):
|
|
144
|
+
prefix = ">" if j == i - 1 else " "
|
|
145
|
+
context_lines.append(f"{prefix} {j + 1:4d} | {lines[j]}")
|
|
146
|
+
matches.append(f"{rel_path}:{i}\n" + "\n".join(context_lines))
|
|
147
|
+
|
|
148
|
+
if len(matches) >= max_results:
|
|
149
|
+
break
|
|
150
|
+
except (OSError, UnicodeDecodeError):
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
if not matches:
|
|
154
|
+
return ToolResult(success=True, output="No matches found.")
|
|
155
|
+
|
|
156
|
+
return ToolResult(success=True, output="\n\n".join(matches))
|
nex/tools/shell.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Shell command execution tool."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from nex.tools import ToolResult
|
|
9
|
+
|
|
10
|
+
_MAX_OUTPUT_LEN = 10_000
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
async def run_command(
|
|
14
|
+
command: str,
|
|
15
|
+
project_dir: Path,
|
|
16
|
+
timeout: int = 30,
|
|
17
|
+
) -> ToolResult:
|
|
18
|
+
"""Execute a shell command with timeout.
|
|
19
|
+
|
|
20
|
+
Safety checks are NOT performed here — they happen in the safety layer
|
|
21
|
+
before this function is called.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
command: The shell command to execute.
|
|
25
|
+
project_dir: Working directory for the command.
|
|
26
|
+
timeout: Maximum seconds to wait (default 30).
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
ToolResult with stdout+stderr or error message.
|
|
30
|
+
"""
|
|
31
|
+
try:
|
|
32
|
+
process = await asyncio.create_subprocess_shell(
|
|
33
|
+
command,
|
|
34
|
+
stdout=asyncio.subprocess.PIPE,
|
|
35
|
+
stderr=asyncio.subprocess.PIPE,
|
|
36
|
+
cwd=str(project_dir),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=timeout)
|
|
41
|
+
except TimeoutError:
|
|
42
|
+
process.kill()
|
|
43
|
+
await process.communicate()
|
|
44
|
+
return ToolResult(
|
|
45
|
+
success=False,
|
|
46
|
+
output="",
|
|
47
|
+
error=f"Command timed out after {timeout}s: {command}",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
stdout_str = stdout.decode("utf-8", errors="replace")
|
|
51
|
+
stderr_str = stderr.decode("utf-8", errors="replace")
|
|
52
|
+
|
|
53
|
+
combined = ""
|
|
54
|
+
if stdout_str:
|
|
55
|
+
combined += stdout_str
|
|
56
|
+
if stderr_str:
|
|
57
|
+
if combined:
|
|
58
|
+
combined += "\n--- stderr ---\n"
|
|
59
|
+
combined += stderr_str
|
|
60
|
+
|
|
61
|
+
if len(combined) > _MAX_OUTPUT_LEN:
|
|
62
|
+
total = len(combined)
|
|
63
|
+
combined = combined[:_MAX_OUTPUT_LEN] + f"\n... (truncated, total {total} chars)"
|
|
64
|
+
|
|
65
|
+
return ToolResult(
|
|
66
|
+
success=process.returncode == 0,
|
|
67
|
+
output=combined,
|
|
68
|
+
error=f"Exit code {process.returncode}" if process.returncode != 0 else None,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
except OSError as exc:
|
|
72
|
+
return ToolResult(success=False, output="", error=f"Failed to run command: {exc}")
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nexcoder
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The coding agent that remembers — AI coding assistant with persistent memory and error learning.
|
|
5
|
+
Project-URL: Homepage, https://github.com/nex-ai/nex-ai
|
|
6
|
+
Project-URL: Repository, https://github.com/nex-ai/nex-ai
|
|
7
|
+
Author: Nex AI Contributors
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ai,anthropic,claude,cli,coding-agent
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Requires-Dist: anthropic>=0.40.0
|
|
19
|
+
Requires-Dist: gitpython>=3.1.0
|
|
20
|
+
Requires-Dist: httpx>=0.28.0
|
|
21
|
+
Requires-Dist: rich>=13.9.0
|
|
22
|
+
Requires-Dist: tree-sitter-javascript>=0.23.0
|
|
23
|
+
Requires-Dist: tree-sitter-python>=0.23.0
|
|
24
|
+
Requires-Dist: tree-sitter-typescript>=0.23.0
|
|
25
|
+
Requires-Dist: tree-sitter>=0.24.0
|
|
26
|
+
Requires-Dist: typer[all]>=0.15.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# Nex AI — The Coding Agent That Remembers
|
|
36
|
+
|
|
37
|
+
A CLI-based AI coding agent that wraps the Anthropic Claude API with persistent project memory, error pattern learning, and codebase indexing.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **Persistent Memory** — Remembers your project context, conventions, and architecture across sessions
|
|
42
|
+
- **Error Learning** — Logs past mistakes and queries them before generating code to avoid repeating errors
|
|
43
|
+
- **Codebase Indexing** — Uses tree-sitter to parse your codebase and select relevant context for each task
|
|
44
|
+
- **Interactive Chat** — Multi-turn conversation mode with full tool access and persistent history
|
|
45
|
+
- **Smart Context Selection** — Two-phase token budgeting with file-level TF-IDF ranking and signature-only fallback
|
|
46
|
+
- **Safety Layer** — Detects destructive operations (rm -rf, DROP TABLE, force push) and requires confirmation
|
|
47
|
+
- **Git Integration** — Creates isolated branches per task, shows diffs, and offers to commit
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install nexcoder
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Initialize Nex in your project
|
|
59
|
+
nex init
|
|
60
|
+
|
|
61
|
+
# Set up your API key
|
|
62
|
+
nex auth
|
|
63
|
+
|
|
64
|
+
# Build the codebase index
|
|
65
|
+
nex index
|
|
66
|
+
|
|
67
|
+
# Run a one-shot task
|
|
68
|
+
nex "add a health check endpoint"
|
|
69
|
+
|
|
70
|
+
# Or start an interactive session
|
|
71
|
+
nex chat
|
|
72
|
+
|
|
73
|
+
# Check project status
|
|
74
|
+
nex status
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Commands
|
|
78
|
+
|
|
79
|
+
| Command | Description |
|
|
80
|
+
|---------|-------------|
|
|
81
|
+
| `nex "task"` | Run a coding task |
|
|
82
|
+
| `nex init` | Initialize .nex/ directory |
|
|
83
|
+
| `nex index` | Build codebase index (.nex/index.json) |
|
|
84
|
+
| `nex chat` | Start interactive chat session |
|
|
85
|
+
| `nex status` | Show project stats |
|
|
86
|
+
| `nex auth` | Configure API key |
|
|
87
|
+
| `nex memory show` | View project memory |
|
|
88
|
+
| `nex memory edit` | Edit project memory |
|
|
89
|
+
| `nex rollback` | Undo last agent change |
|
|
90
|
+
| `nex --dry-run "task"` | Preview without executing |
|
|
91
|
+
|
|
92
|
+
## How It Works
|
|
93
|
+
|
|
94
|
+
1. **Context Assembly** — Loads project memory, error patterns, and relevant code into the prompt. Files are ranked by TF-IDF relevance, with top files included in full and remaining files as signature summaries.
|
|
95
|
+
2. **Agent Loop** — Iterates: call Claude API → execute tools → feed results back, up to 25 iterations.
|
|
96
|
+
3. **Interactive Chat** — `nex chat` maintains a persistent conversation with the agent, accumulating context across turns. Useful for exploratory work, debugging, or multi-step tasks.
|
|
97
|
+
4. **Codebase Index** — `nex index` parses your source files with tree-sitter, extracting function/class signatures for fast relevance search.
|
|
98
|
+
5. **Git Commit** — Shows diff and offers to commit on an isolated branch.
|
|
99
|
+
|
|
100
|
+
## Tools
|
|
101
|
+
|
|
102
|
+
The agent has access to 5 tools:
|
|
103
|
+
|
|
104
|
+
| Tool | Description |
|
|
105
|
+
|------|-------------|
|
|
106
|
+
| `read_file` | Read file contents with line numbers |
|
|
107
|
+
| `write_file` | Write content, creating directories if needed |
|
|
108
|
+
| `run_command` | Execute shell commands (safety-checked) |
|
|
109
|
+
| `search_files` | Regex search across the codebase |
|
|
110
|
+
| `list_directory` | Recursive directory listing |
|
|
111
|
+
|
|
112
|
+
## Development
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Clone and install in editable mode
|
|
116
|
+
git clone https://github.com/nex-ai/nex-ai.git
|
|
117
|
+
cd nex-ai
|
|
118
|
+
pip install -e ".[dev]"
|
|
119
|
+
|
|
120
|
+
# Run tests
|
|
121
|
+
pytest
|
|
122
|
+
|
|
123
|
+
# Lint and format
|
|
124
|
+
ruff check src/ tests/
|
|
125
|
+
ruff format src/ tests/
|
|
126
|
+
|
|
127
|
+
# Type check
|
|
128
|
+
mypy src/nex/
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Architecture
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
src/nex/
|
|
135
|
+
├── cli.py # Typer CLI entry point
|
|
136
|
+
├── agent.py # Core agent loop + ChatSession
|
|
137
|
+
├── api_client.py # Anthropic API wrapper
|
|
138
|
+
├── planner.py # Task decomposition (Haiku)
|
|
139
|
+
├── reviewer.py # Independent code review
|
|
140
|
+
├── context.py # Context assembly + token budgeting
|
|
141
|
+
├── safety.py # Destructive operation detection
|
|
142
|
+
├── config.py # Configuration management
|
|
143
|
+
├── memory/ # Persistent memory system
|
|
144
|
+
│ ├── project.py # .nex/memory.md
|
|
145
|
+
│ ├── errors.py # .nex/errors.db (SQLite)
|
|
146
|
+
│ └── decisions.py # .nex/decisions.md
|
|
147
|
+
├── indexer/ # Codebase indexing
|
|
148
|
+
│ ├── scanner.py # File discovery
|
|
149
|
+
│ ├── parser.py # tree-sitter AST parsing
|
|
150
|
+
│ └── index.py # Index builder + TF-IDF search
|
|
151
|
+
└── tools/ # Agent tools (5 total)
|
|
152
|
+
├── file_ops.py # read_file, write_file
|
|
153
|
+
├── shell.py # run_command
|
|
154
|
+
├── search.py # search_files
|
|
155
|
+
└── git_ops.py # Git operations
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Environment Variables
|
|
159
|
+
|
|
160
|
+
| Variable | Description | Default |
|
|
161
|
+
|----------|-------------|---------|
|
|
162
|
+
| `ANTHROPIC_API_KEY` | Anthropic API key (required) | — |
|
|
163
|
+
| `NEX_MODEL` | Override default model | `claude-sonnet-4-20250514` |
|
|
164
|
+
| `NEX_MAX_ITERATIONS` | Max tool calls per task | `25` |
|
|
165
|
+
| `NEX_DRY_RUN` | Default dry-run mode | `false` |
|
|
166
|
+
| `NEX_LOG_LEVEL` | Logging verbosity | `INFO` |
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
nex/__init__.py,sha256=L_sbkyem5kYqGkPuCZcd-O2wBI3_SUfhf6YOUZZKKys,130
|
|
2
|
+
nex/agent.py,sha256=1GOUOYYNW5pHgG2C11yxmTRUaDkgFKsIg1YD8BCHK4Y,21757
|
|
3
|
+
nex/api_client.py,sha256=L3uZLq2CcBLzphccl_6Hls8bWbjnqMs30OhQP-LWxC8,6193
|
|
4
|
+
nex/cli.py,sha256=hrOSsE89e15kveFk7CakVqLDhey16t2rwi6rIqGq7UI,15562
|
|
5
|
+
nex/config.py,sha256=U-HH513SnP-Qjwm9r7J-X-cc5mXIvwUcxw8mhpPii6I,5636
|
|
6
|
+
nex/context.py,sha256=3n8tNWlLTkUIR8GuQKmNCNEBnMCdrBRq8eD6rVAoOs4,8273
|
|
7
|
+
nex/exceptions.py,sha256=i8qczPp-mkH94RtNHwfyzjWUXFYuF_EmOwCydfBZXG0,1043
|
|
8
|
+
nex/planner.py,sha256=xFmHvP00BQxfwwPtAoMwE8BiJXzluHFNJuL36736roM,3594
|
|
9
|
+
nex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
nex/reviewer.py,sha256=kz9xuuNsMMD_05FNLQSyiM0cODxWLTSIsKJKo9Sl37Q,3348
|
|
11
|
+
nex/safety.py,sha256=keaGodCsHOfVkqHsKKMGYm1XNPsWtfQ8L-h5CZwWVjU,7588
|
|
12
|
+
nex/test_runner.py,sha256=ZLcCGlL0LvboNLY8nClZPkgkw7oK8LiZ4nUaZaJV3WI,6140
|
|
13
|
+
nex/indexer/__init__.py,sha256=AG2KmuT7MWvguV_vkfXM_wuRGCe5B0w-5x4SybQaogs,388
|
|
14
|
+
nex/indexer/index.py,sha256=R92Cq7DGfgXkms_vm-34pJ0j34alwFOOWZHGwef3iok,10570
|
|
15
|
+
nex/indexer/parser.py,sha256=Wo3mEnhztfJKt-tb8-FiI4T8AUqG5JvECP2IwmYMjYs,13877
|
|
16
|
+
nex/indexer/scanner.py,sha256=lIYT_MG3VD0GhxqRCFEYSSG2-hh_MXcXGPsHCSU42Oc,5499
|
|
17
|
+
nex/memory/__init__.py,sha256=p4dQWSY614MC0DhVgtqediIkCO9Lf5adv5F0YF4IzNI,396
|
|
18
|
+
nex/memory/decisions.py,sha256=XvnEb8qwG6lnF-1IFDJ7D6oLc5tN8FvShGx6VO6KE2Y,3905
|
|
19
|
+
nex/memory/errors.py,sha256=DCpE71giIPFD3_90dJILtwNORUj3cMrPFBySKQOiOC8,8174
|
|
20
|
+
nex/memory/project.py,sha256=2OZ2el2T3g-TXcfwqCzWKfasdEWCkLT7aQjx5H5VFhQ,4746
|
|
21
|
+
nex/tools/__init__.py,sha256=WK4gsBGgaWbGz2j8PuBvQtQNTpeWGp5FG_wZLPoqHKU,3443
|
|
22
|
+
nex/tools/file_ops.py,sha256=_QMbWsljexkKkzUqz9llOU1uS2rC4GeMg6nq7C4GD6s,2970
|
|
23
|
+
nex/tools/git_ops.py,sha256=K8yH37Y6vIJUjK-DOZ6afrno_KPOK8xK1VJxfcAlW9w,5406
|
|
24
|
+
nex/tools/search.py,sha256=jSy6uiPzU2VNEv6YJ0e8ZvoYUy8m0YQYqpip9LzVlO0,4648
|
|
25
|
+
nex/tools/shell.py,sha256=3QrzK5C5mq0HX9HS8EssH94d7EEAheJrNEtEc-d6dq0,2113
|
|
26
|
+
nexcoder-0.1.0.dist-info/METADATA,sha256=5D8MaS5V9uwqMNLt92-618yoNgTKdIN6x88mRldPjbg,6021
|
|
27
|
+
nexcoder-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
28
|
+
nexcoder-0.1.0.dist-info/entry_points.txt,sha256=xR6UmNT0yEmlXt7E-Xcv8zZPywI7TmZw-c8WIOl6iVQ,36
|
|
29
|
+
nexcoder-0.1.0.dist-info/licenses/LICENSE,sha256=aOwfjAeGkp6oZxVcTmr_0ae5RoJ2FiJ9HVWAsg-o7tU,1076
|
|
30
|
+
nexcoder-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nex AI Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|