nanocode-cli 0.1.0__tar.gz → 0.2.1__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.
- {nanocode_cli-0.1.0/nanocode_cli.egg-info → nanocode_cli-0.2.1}/PKG-INFO +32 -3
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/README.md +31 -2
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/nanocode.py +44 -7
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1/nanocode_cli.egg-info}/PKG-INFO +32 -3
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/pyproject.toml +1 -1
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/LICENSE +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/MANIFEST.in +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/nanocode_cli.egg-info/SOURCES.txt +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/nanocode_cli.egg-info/dependency_links.txt +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/nanocode_cli.egg-info/entry_points.txt +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/nanocode_cli.egg-info/requires.txt +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/nanocode_cli.egg-info/top_level.txt +0 -0
- {nanocode_cli-0.1.0 → nanocode_cli-0.2.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nanocode-cli
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A lightweight terminal-based AI coding assistant
|
|
5
5
|
Author-email: hit9 <hit9@icloud.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -30,12 +30,15 @@ Dynamic: license-file
|
|
|
30
30
|
|
|
31
31
|
# nanocode
|
|
32
32
|
|
|
33
|
+
A lightweight terminal-based AI coding assistant.
|
|
34
|
+
|
|
35
|
+
nanocode is used to help building itself, including features such as `@file` path completion.
|
|
33
36
|
|
|
34
37
|
## Screenshots
|
|
35
38
|
|
|
36
39
|
| | |
|
|
37
40
|
|---|---|
|
|
38
|
-
|  |  |
|
|
39
42
|
|
|
40
43
|
## Install
|
|
41
44
|
|
|
@@ -43,6 +46,12 @@ Dynamic: license-file
|
|
|
43
46
|
uv tool install nanocode-cli
|
|
44
47
|
```
|
|
45
48
|
|
|
49
|
+
Upgrade an existing install:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
uv tool upgrade nanocode-cli
|
|
53
|
+
```
|
|
54
|
+
|
|
46
55
|
For local development:
|
|
47
56
|
|
|
48
57
|
```sh
|
|
@@ -55,7 +64,7 @@ uv run nanocode
|
|
|
55
64
|
Required:
|
|
56
65
|
|
|
57
66
|
```sh
|
|
58
|
-
export NANOCODE_API_URL="https://api.example.com/v1
|
|
67
|
+
export NANOCODE_API_URL="https://api.example.com/v1"
|
|
59
68
|
export NANOCODE_API_KEY="your-api-key"
|
|
60
69
|
export NANOCODE_MODEL="your-model"
|
|
61
70
|
```
|
|
@@ -72,6 +81,26 @@ export NANOCODE_SHELL_TIMEOUT="60"
|
|
|
72
81
|
export NANOCODE_COMPACT_AT="100"
|
|
73
82
|
```
|
|
74
83
|
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
Start nanocode:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
nanocode
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Show available commands:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
/help
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Ask a source-aware question about nanocode itself:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
/help how does compact work?
|
|
102
|
+
```
|
|
103
|
+
|
|
75
104
|
## Safety
|
|
76
105
|
|
|
77
106
|
nanocode does not provide sandbox protection. It can run shell commands and edit files in the environment where you start it.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# nanocode
|
|
2
2
|
|
|
3
|
+
A lightweight terminal-based AI coding assistant.
|
|
4
|
+
|
|
5
|
+
nanocode is used to help building itself, including features such as `@file` path completion.
|
|
3
6
|
|
|
4
7
|
## Screenshots
|
|
5
8
|
|
|
6
9
|
| | |
|
|
7
10
|
|---|---|
|
|
8
|
-
|  |  |
|
|
9
12
|
|
|
10
13
|
## Install
|
|
11
14
|
|
|
@@ -13,6 +16,12 @@
|
|
|
13
16
|
uv tool install nanocode-cli
|
|
14
17
|
```
|
|
15
18
|
|
|
19
|
+
Upgrade an existing install:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
uv tool upgrade nanocode-cli
|
|
23
|
+
```
|
|
24
|
+
|
|
16
25
|
For local development:
|
|
17
26
|
|
|
18
27
|
```sh
|
|
@@ -25,7 +34,7 @@ uv run nanocode
|
|
|
25
34
|
Required:
|
|
26
35
|
|
|
27
36
|
```sh
|
|
28
|
-
export NANOCODE_API_URL="https://api.example.com/v1
|
|
37
|
+
export NANOCODE_API_URL="https://api.example.com/v1"
|
|
29
38
|
export NANOCODE_API_KEY="your-api-key"
|
|
30
39
|
export NANOCODE_MODEL="your-model"
|
|
31
40
|
```
|
|
@@ -42,6 +51,26 @@ export NANOCODE_SHELL_TIMEOUT="60"
|
|
|
42
51
|
export NANOCODE_COMPACT_AT="100"
|
|
43
52
|
```
|
|
44
53
|
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
Start nanocode:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
nanocode
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Show available commands:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
/help
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Ask a source-aware question about nanocode itself:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
/help how does compact work?
|
|
72
|
+
```
|
|
73
|
+
|
|
45
74
|
## Safety
|
|
46
75
|
|
|
47
76
|
nanocode does not provide sandbox protection. It can run shell commands and edit files in the environment where you start it.
|
|
@@ -32,7 +32,7 @@ from enum import StrEnum
|
|
|
32
32
|
from typing import Any, Callable, ClassVar, final, Iterator, Protocol, Self, Type, TypeAlias
|
|
33
33
|
from typing_extensions import override
|
|
34
34
|
from prompt_toolkit import PromptSession, print_formatted_text
|
|
35
|
-
from prompt_toolkit.completion import WordCompleter
|
|
35
|
+
from prompt_toolkit.completion import Completer, Completion, WordCompleter
|
|
36
36
|
from prompt_toolkit.formatted_text import FormattedText
|
|
37
37
|
from prompt_toolkit.history import FileHistory
|
|
38
38
|
from prompt_toolkit.output.defaults import create_output
|
|
@@ -41,7 +41,7 @@ from prompt_toolkit.patch_stdout import patch_stdout
|
|
|
41
41
|
|
|
42
42
|
JsonValue: TypeAlias = Any
|
|
43
43
|
Json: TypeAlias = dict[str, JsonValue]
|
|
44
|
-
__version__ = "0.1
|
|
44
|
+
__version__ = "0.2.1"
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class Error(Exception): ...
|
|
@@ -56,6 +56,34 @@ class LLMError(Exception): ...
|
|
|
56
56
|
class Cancellation(Exception): ...
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
class ReferenceFileCompleter(Completer):
|
|
60
|
+
def __init__(self, cwd: str, command_completer: WordCompleter):
|
|
61
|
+
self.cwd = cwd
|
|
62
|
+
self.command_completer = command_completer
|
|
63
|
+
|
|
64
|
+
def get_completions(self, document, complete_event):
|
|
65
|
+
match = re.search(r"(?:^|\s)@([^\s]*)$", document.text_before_cursor)
|
|
66
|
+
if match is None:
|
|
67
|
+
yield from self.command_completer.get_completions(document, complete_event)
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
partial = match.group(1)
|
|
71
|
+
dirname, prefix = os.path.split(partial)
|
|
72
|
+
base_dir = os.path.abspath(os.path.join(self.cwd, dirname))
|
|
73
|
+
try:
|
|
74
|
+
names = sorted(os.listdir(base_dir))
|
|
75
|
+
except OSError:
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
for name in names:
|
|
79
|
+
if not name.startswith(prefix):
|
|
80
|
+
continue
|
|
81
|
+
full_path = os.path.join(base_dir, name)
|
|
82
|
+
suffix = "/" if os.path.isdir(full_path) else ""
|
|
83
|
+
candidate = os.path.join(dirname, name) + suffix if dirname else name + suffix
|
|
84
|
+
yield Completion(candidate, start_position=-len(partial), display="@" + candidate)
|
|
85
|
+
|
|
86
|
+
|
|
59
87
|
class PromptItem:
|
|
60
88
|
@abstractmethod
|
|
61
89
|
def format(self, indent: str = "") -> str:
|
|
@@ -2665,13 +2693,19 @@ class Agent:
|
|
|
2665
2693
|
for event, execution in zip(self.tool_runner.latest_events, self.tool_runner.latest_executions):
|
|
2666
2694
|
if not event.summary:
|
|
2667
2695
|
continue
|
|
2668
|
-
|
|
2696
|
+
is_reading_result_file = self._has_read_result_file_call(tool_calls, event.result_file)
|
|
2697
|
+
if event.needs_raw_read and not is_reading_result_file:
|
|
2669
2698
|
needs_read.append(event)
|
|
2670
2699
|
if event.outcome in {"failure", "partial"}:
|
|
2671
|
-
if not event.key_details:
|
|
2700
|
+
if not event.key_details and not is_reading_result_file:
|
|
2672
2701
|
missing_evidence.append(event)
|
|
2673
2702
|
continue
|
|
2674
|
-
if
|
|
2703
|
+
if (
|
|
2704
|
+
self._is_large_tool_output(execution.output)
|
|
2705
|
+
and not event.key_details
|
|
2706
|
+
and not event.needs_raw_read
|
|
2707
|
+
and not is_reading_result_file
|
|
2708
|
+
):
|
|
2675
2709
|
missing_evidence.append(event)
|
|
2676
2710
|
if not missing and not missing_evidence and not needs_read:
|
|
2677
2711
|
return ""
|
|
@@ -2700,12 +2734,13 @@ class Agent:
|
|
|
2700
2734
|
def _has_read_result_file_call(self, tool_calls: list[JsonValue], result_file: str) -> bool:
|
|
2701
2735
|
if not result_file:
|
|
2702
2736
|
return False
|
|
2737
|
+
expected = self.session.resolve_path(result_file)
|
|
2703
2738
|
for raw_call in tool_calls:
|
|
2704
2739
|
call = _json_dict(raw_call)
|
|
2705
2740
|
if _json_str(call.get("name")) != ReadTool.name():
|
|
2706
2741
|
continue
|
|
2707
2742
|
args = [_json_str(arg) or "" for arg in _json_list(call.get("args"))]
|
|
2708
|
-
if args and args[0] ==
|
|
2743
|
+
if args and self.session.resolve_path(args[0]) == expected:
|
|
2709
2744
|
return True
|
|
2710
2745
|
return False
|
|
2711
2746
|
|
|
@@ -2806,6 +2841,8 @@ class CommandDispatcher:
|
|
|
2806
2841
|
current_category = spec.category
|
|
2807
2842
|
lines.append(current_category + ":")
|
|
2808
2843
|
lines.append(" " + spec.display_name() + " - " + spec.description)
|
|
2844
|
+
lines.append("")
|
|
2845
|
+
lines.append("Tip: use @path to autocomplete file paths in prompts.")
|
|
2809
2846
|
return "\n".join(lines)
|
|
2810
2847
|
|
|
2811
2848
|
def _format_source_help_question(self, question: str) -> str:
|
|
@@ -3114,7 +3151,7 @@ class AgentLoop:
|
|
|
3114
3151
|
os.makedirs(os.path.dirname(self.history_path), exist_ok=True)
|
|
3115
3152
|
return PromptSession(
|
|
3116
3153
|
history=FileHistory(self.history_path),
|
|
3117
|
-
completer=self._command_completer(),
|
|
3154
|
+
completer=ReferenceFileCompleter(self.agent.session.cwd, self._command_completer()),
|
|
3118
3155
|
complete_while_typing=True,
|
|
3119
3156
|
)
|
|
3120
3157
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nanocode-cli
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A lightweight terminal-based AI coding assistant
|
|
5
5
|
Author-email: hit9 <hit9@icloud.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -30,12 +30,15 @@ Dynamic: license-file
|
|
|
30
30
|
|
|
31
31
|
# nanocode
|
|
32
32
|
|
|
33
|
+
A lightweight terminal-based AI coding assistant.
|
|
34
|
+
|
|
35
|
+
nanocode is used to help building itself, including features such as `@file` path completion.
|
|
33
36
|
|
|
34
37
|
## Screenshots
|
|
35
38
|
|
|
36
39
|
| | |
|
|
37
40
|
|---|---|
|
|
38
|
-
|  |  |
|
|
39
42
|
|
|
40
43
|
## Install
|
|
41
44
|
|
|
@@ -43,6 +46,12 @@ Dynamic: license-file
|
|
|
43
46
|
uv tool install nanocode-cli
|
|
44
47
|
```
|
|
45
48
|
|
|
49
|
+
Upgrade an existing install:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
uv tool upgrade nanocode-cli
|
|
53
|
+
```
|
|
54
|
+
|
|
46
55
|
For local development:
|
|
47
56
|
|
|
48
57
|
```sh
|
|
@@ -55,7 +64,7 @@ uv run nanocode
|
|
|
55
64
|
Required:
|
|
56
65
|
|
|
57
66
|
```sh
|
|
58
|
-
export NANOCODE_API_URL="https://api.example.com/v1
|
|
67
|
+
export NANOCODE_API_URL="https://api.example.com/v1"
|
|
59
68
|
export NANOCODE_API_KEY="your-api-key"
|
|
60
69
|
export NANOCODE_MODEL="your-model"
|
|
61
70
|
```
|
|
@@ -72,6 +81,26 @@ export NANOCODE_SHELL_TIMEOUT="60"
|
|
|
72
81
|
export NANOCODE_COMPACT_AT="100"
|
|
73
82
|
```
|
|
74
83
|
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
Start nanocode:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
nanocode
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Show available commands:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
/help
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Ask a source-aware question about nanocode itself:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
/help how does compact work?
|
|
102
|
+
```
|
|
103
|
+
|
|
75
104
|
## Safety
|
|
76
105
|
|
|
77
106
|
nanocode does not provide sandbox protection. It can run shell commands and edit files in the environment where you start it.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|