nanocode-cli 0.5.10__tar.gz → 0.5.12__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.5.10/nanocode_cli.egg-info → nanocode_cli-0.5.12}/PKG-INFO +15 -3
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/README.md +13 -1
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/README.zh-CN.md +11 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/nanocode.py +55 -16
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12/nanocode_cli.egg-info}/PKG-INFO +15 -3
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/nanocode_cli.egg-info/requires.txt +1 -1
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/pyproject.toml +2 -2
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/LICENSE +0 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/MANIFEST.in +0 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/nanocode_cli.egg-info/SOURCES.txt +0 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/nanocode_cli.egg-info/dependency_links.txt +0 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/nanocode_cli.egg-info/entry_points.txt +0 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/nanocode_cli.egg-info/top_level.txt +0 -0
- {nanocode_cli-0.5.10 → nanocode_cli-0.5.12}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nanocode-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.12
|
|
4
4
|
Summary: A small terminal coding agent written in Python
|
|
5
5
|
Author-email: hit9 <hit9@icloud.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -22,7 +22,7 @@ Requires-Python: >=3.11
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
24
|
Requires-Dist: anthropic>=0.64.0
|
|
25
|
-
Requires-Dist: code-symbol-index>=0.
|
|
25
|
+
Requires-Dist: code-symbol-index>=0.3.0
|
|
26
26
|
Requires-Dist: json-repair
|
|
27
27
|
Requires-Dist: openai>=2.37.0
|
|
28
28
|
Requires-Dist: prompt-toolkit>=3.0
|
|
@@ -39,6 +39,8 @@ A small terminal coding agent written in Python.
|
|
|
39
39
|
|
|
40
40
|
[简体中文](README.zh-CN.md)
|
|
41
41
|
|
|
42
|
+
[Chinese blog](https://hit9.dev/post/nanocode)
|
|
43
|
+
|
|
42
44
|
nanocode is pre-1.0 software. Commands, configuration, and tool behavior may change before a stable release.
|
|
43
45
|
|
|
44
46
|

|
|
@@ -48,7 +50,7 @@ nanocode is pre-1.0 software. Commands, configuration, and tool behavior may cha
|
|
|
48
50
|
- **Live turn control**: Add follow-up input while the agent is still working, without losing the current tool flow.
|
|
49
51
|
- **File-state brain**: Reads and edits build a current, line-numbered view of the files that matter now.
|
|
50
52
|
- **Stale-edit protection**: `line:hash` anchors reject edits when the target code has drifted.
|
|
51
|
-
- **Project-aware navigation**: Use the symbol index to jump through outlines, references, and changed files quickly.
|
|
53
|
+
- **Project-aware navigation**: Use the symbol index to jump through outlines, references, implementors, call chains, and changed files quickly.
|
|
52
54
|
- **Recoverable context**: Tool output stays bounded in the prompt, while raw `tr.N` results remain recallable.
|
|
53
55
|
- **Cache-aware context**: Stable sections stay early and noisy working state stays late to improve prompt-cache reuse.
|
|
54
56
|
- **Focused working memory**: `Note` separates goal, plan, and known facts from noisy execution logs.
|
|
@@ -138,6 +140,16 @@ Main fields:
|
|
|
138
140
|
|
|
139
141
|
`api = "auto"` chooses between Chat Completions and Anthropic Messages using provider/model profiles. `prompt_cache_key = "auto"` derives a stable key from provider, model, workspace, and tool schema names.
|
|
140
142
|
|
|
143
|
+
|
|
144
|
+
## Tested Providers
|
|
145
|
+
|
|
146
|
+
The following providers have been tested with nanocode:
|
|
147
|
+
|
|
148
|
+
- **deepseek**: DeepSeek API
|
|
149
|
+
- **opencode**: OpenCode API
|
|
150
|
+
- **aliyun**: Alibaba Cloud (Tongyi Qianwen) API via Chat Completions
|
|
151
|
+
- **llama.cpp**: Local inference via llama.cpp server
|
|
152
|
+
|
|
141
153
|
## Context Design
|
|
142
154
|
|
|
143
155
|
Each model request is built manually from explicit messages. Stable context comes first, conversation stays as messages, working memory follows, and the latest file state is appended at the end.
|
|
@@ -4,6 +4,8 @@ A small terminal coding agent written in Python.
|
|
|
4
4
|
|
|
5
5
|
[简体中文](README.zh-CN.md)
|
|
6
6
|
|
|
7
|
+
[Chinese blog](https://hit9.dev/post/nanocode)
|
|
8
|
+
|
|
7
9
|
nanocode is pre-1.0 software. Commands, configuration, and tool behavior may change before a stable release.
|
|
8
10
|
|
|
9
11
|

|
|
@@ -13,7 +15,7 @@ nanocode is pre-1.0 software. Commands, configuration, and tool behavior may cha
|
|
|
13
15
|
- **Live turn control**: Add follow-up input while the agent is still working, without losing the current tool flow.
|
|
14
16
|
- **File-state brain**: Reads and edits build a current, line-numbered view of the files that matter now.
|
|
15
17
|
- **Stale-edit protection**: `line:hash` anchors reject edits when the target code has drifted.
|
|
16
|
-
- **Project-aware navigation**: Use the symbol index to jump through outlines, references, and changed files quickly.
|
|
18
|
+
- **Project-aware navigation**: Use the symbol index to jump through outlines, references, implementors, call chains, and changed files quickly.
|
|
17
19
|
- **Recoverable context**: Tool output stays bounded in the prompt, while raw `tr.N` results remain recallable.
|
|
18
20
|
- **Cache-aware context**: Stable sections stay early and noisy working state stays late to improve prompt-cache reuse.
|
|
19
21
|
- **Focused working memory**: `Note` separates goal, plan, and known facts from noisy execution logs.
|
|
@@ -103,6 +105,16 @@ Main fields:
|
|
|
103
105
|
|
|
104
106
|
`api = "auto"` chooses between Chat Completions and Anthropic Messages using provider/model profiles. `prompt_cache_key = "auto"` derives a stable key from provider, model, workspace, and tool schema names.
|
|
105
107
|
|
|
108
|
+
|
|
109
|
+
## Tested Providers
|
|
110
|
+
|
|
111
|
+
The following providers have been tested with nanocode:
|
|
112
|
+
|
|
113
|
+
- **deepseek**: DeepSeek API
|
|
114
|
+
- **opencode**: OpenCode API
|
|
115
|
+
- **aliyun**: Alibaba Cloud (Tongyi Qianwen) API via Chat Completions
|
|
116
|
+
- **llama.cpp**: Local inference via llama.cpp server
|
|
117
|
+
|
|
106
118
|
## Context Design
|
|
107
119
|
|
|
108
120
|
Each model request is built manually from explicit messages. Stable context comes first, conversation stays as messages, working memory follows, and the latest file state is appended at the end.
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
[English](README.md)
|
|
6
6
|
|
|
7
|
+
[中文博客](https://hit9.dev/post/nanocode)
|
|
8
|
+
|
|
7
9
|
nanocode 仍是 1.0 前的软件。稳定版发布前,命令、配置和工具行为都可能变化。
|
|
8
10
|
|
|
9
11
|

|
|
@@ -103,6 +105,15 @@ nanocode --init-config
|
|
|
103
105
|
|
|
104
106
|
`api = "auto"` 会根据 provider/model profile 在 Chat Completions 和 Anthropic Messages 之间选择。`prompt_cache_key = "auto"` 会根据 provider、model、workspace 和工具 schema 名称生成稳定 key。
|
|
105
107
|
|
|
108
|
+
|
|
109
|
+
## 已测试的 Provider
|
|
110
|
+
|
|
111
|
+
以下 provider 已在 nanocode 中测试通过:
|
|
112
|
+
|
|
113
|
+
- **deepseek**: DeepSeek API
|
|
114
|
+
- **opencode**: OpenCode API
|
|
115
|
+
- **aliyun**: 阿里云通义千问 API(Chat Completions)
|
|
116
|
+
- **llama.cpp**: 通过 llama.cpp 服务端本地推理
|
|
106
117
|
## 上下文设计
|
|
107
118
|
|
|
108
119
|
每次模型请求都由 nanocode 手动构建成明确的 messages。稳定上下文在前,会话作为 messages 保留,工作记忆随后,最新文件状态放在末尾。
|
|
@@ -55,7 +55,7 @@ from prompt_toolkit.widgets import SearchToolbar
|
|
|
55
55
|
from rich.console import Console
|
|
56
56
|
from rich.markdown import Markdown
|
|
57
57
|
|
|
58
|
-
__version__ = "0.5.
|
|
58
|
+
__version__ = "0.5.12"
|
|
59
59
|
|
|
60
60
|
Json = dict[str, Any]
|
|
61
61
|
HTTP_USER_AGENT = "nanocode/" + __version__
|
|
@@ -1447,31 +1447,44 @@ class InspectCodeTool(Tool):
|
|
|
1447
1447
|
NAME = "InspectCode"
|
|
1448
1448
|
MAX_LIMIT: ClassVar[int] = 80
|
|
1449
1449
|
MAX_OUTLINE_LIMIT: ClassVar[int] = 1000
|
|
1450
|
-
|
|
1451
|
-
|
|
1450
|
+
MAX_DEPTH: ClassVar[int] = 5
|
|
1451
|
+
MODES: ClassVar[tuple[str, ...]] = ("find", "inspect", "outline", "refs", "impls", "callers", "callees")
|
|
1452
|
+
SYMBOL_MODES: ClassVar[frozenset[str]] = frozenset({"find", "inspect", "refs", "impls", "callers", "callees"})
|
|
1453
|
+
RESOLVE_MODES: ClassVar[frozenset[str]] = frozenset({"inspect", "refs", "impls", "callers", "callees"})
|
|
1454
|
+
CHAIN_MODES: ClassVar[frozenset[str]] = frozenset({"callers", "callees"})
|
|
1455
|
+
OPTION_KEYS: ClassVar[tuple[str, ...]] = ("limit", "kind", "path", "symbol", "exact_only", "depth", "offset", "all_kinds", "ref_kind", "loose")
|
|
1456
|
+
DESCRIPTION = "Use the code index: find returns symbols; inspect returns anchors/members/references; outline returns a file symbol tree; refs lists classified references; impls lists implementors; callers/callees walk the call chain."
|
|
1457
|
+
SIGNATURE = "InspectCode(mode,target,kind?,path?,symbol?,limit?,exact_only?,depth?,offset?,all_kinds?,ref_kind?,loose?)"
|
|
1452
1458
|
EXAMPLE = (
|
|
1453
1459
|
'Find symbols; kind can be class|function|method|variable|constant|enum|struct|interface|module|type|trait|field|property|impl|namespace|dict_key, comma-ok. Example: {"mode":"find","target":"Tool","kind":"class,function","limit":20}',
|
|
1454
|
-
'Find exact symbol in a path. Example: {"mode":"find","target":"Session","path":"src","exact_only":true,"limit":10}',
|
|
1455
1460
|
'Inspect one symbol; path narrows candidates. Example: {"mode":"inspect","target":"Tool","path":"src/app.py"}',
|
|
1456
1461
|
'Outline one file; symbol narrows subtree. Example: {"mode":"outline","target":"src/app.py","symbol":"App","limit":300}',
|
|
1462
|
+
'List references; default hides import/attribute noise, ref_kind filters to call|read|write|inherit|type|import|attribute|usage (comma-ok), all_kinds shows everything, offset pages. Example: {"mode":"refs","target":"Tool","ref_kind":"call,write","offset":0}',
|
|
1463
|
+
'List implementors of an interface/base. Example: {"mode":"impls","target":"Tool","kind":"class"}',
|
|
1464
|
+
'Walk transitive callers/callees up to depth; callees loose includes ambiguous cross-module matches. Example: {"mode":"callers","target":"handle_job","depth":3}',
|
|
1457
1465
|
)
|
|
1458
1466
|
|
|
1459
1467
|
@classmethod
|
|
1460
1468
|
def params_schema(cls) -> Json:
|
|
1461
1469
|
props = {
|
|
1462
|
-
"mode": {"type": "string", "enum":
|
|
1470
|
+
"mode": {"type": "string", "enum": list(cls.MODES)},
|
|
1463
1471
|
"target": {"type": "string"},
|
|
1464
1472
|
"limit": {"type": "integer", "minimum": 1, "maximum": cls.MAX_OUTLINE_LIMIT},
|
|
1465
1473
|
"kind": {"type": "string"},
|
|
1466
1474
|
"path": {"type": "string"},
|
|
1467
1475
|
"symbol": {"type": "string"},
|
|
1468
1476
|
"exact_only": {"type": "boolean"},
|
|
1477
|
+
"depth": {"type": "integer", "minimum": 1, "maximum": cls.MAX_DEPTH},
|
|
1478
|
+
"offset": {"type": "integer", "minimum": 0},
|
|
1479
|
+
"all_kinds": {"type": "boolean"},
|
|
1480
|
+
"ref_kind": {"type": "string"},
|
|
1481
|
+
"loose": {"type": "boolean"},
|
|
1469
1482
|
}
|
|
1470
1483
|
return {"type": "object", "properties": props, "required": ["mode", "target"], "additionalProperties": False}
|
|
1471
1484
|
|
|
1472
1485
|
@classmethod
|
|
1473
1486
|
def payload_args(cls, payload: Json) -> list[Any]:
|
|
1474
|
-
options = {key: payload[key] for key in
|
|
1487
|
+
options = {key: payload[key] for key in cls.OPTION_KEYS if key in payload}
|
|
1475
1488
|
return [str(payload.get("mode") or ""), str(payload.get("target") or ""), *([options] if options else [])]
|
|
1476
1489
|
|
|
1477
1490
|
def call(self) -> str:
|
|
@@ -1483,22 +1496,37 @@ class InspectCodeTool(Tool):
|
|
|
1483
1496
|
if len(self.args) == 3 and not isinstance(self.args[2], dict):
|
|
1484
1497
|
raise ToolError("InspectCode options must be an object")
|
|
1485
1498
|
options = self.args[2] if len(self.args) == 3 else {}
|
|
1486
|
-
if unexpected := sorted(set(options) -
|
|
1499
|
+
if unexpected := sorted(set(options) - set(self.OPTION_KEYS)):
|
|
1487
1500
|
raise ToolError("InspectCode unexpected option: " + ", ".join(unexpected))
|
|
1488
|
-
if mode not in
|
|
1489
|
-
raise ToolError("InspectCode mode must be
|
|
1501
|
+
if mode not in self.MODES:
|
|
1502
|
+
raise ToolError("InspectCode mode must be one of: " + ", ".join(self.MODES))
|
|
1490
1503
|
if not target:
|
|
1491
1504
|
raise ToolError("InspectCode target is required")
|
|
1492
|
-
if mode in
|
|
1505
|
+
if mode in self.SYMBOL_MODES and re.search(r"\s", target):
|
|
1493
1506
|
raise ToolError("InspectCode symbol target must not contain whitespace")
|
|
1494
|
-
if mode
|
|
1495
|
-
raise ToolError("InspectCode
|
|
1507
|
+
if mode in self.RESOLVE_MODES and (target.endswith(".py") or os.path.exists(self.session.resolve_path(target))):
|
|
1508
|
+
raise ToolError(f"InspectCode {mode} target must be a symbol, not a file")
|
|
1496
1509
|
if mode == "outline" and not os.path.isfile(self.session.resolve_path(target)):
|
|
1497
1510
|
raise ToolError("InspectCode outline target must be an existing file")
|
|
1498
1511
|
limit = options.get("limit")
|
|
1499
1512
|
max_limit = self.MAX_OUTLINE_LIMIT if mode == "outline" else self.MAX_LIMIT
|
|
1500
1513
|
if limit is not None and (isinstance(limit, bool) or not isinstance(limit, int) or limit < 1 or limit > max_limit):
|
|
1501
1514
|
raise ToolError(f"InspectCode {mode} limit must be 1..{max_limit}")
|
|
1515
|
+
depth = options.get("depth")
|
|
1516
|
+
if depth is not None and (isinstance(depth, bool) or not isinstance(depth, int) or depth < 1 or depth > self.MAX_DEPTH):
|
|
1517
|
+
raise ToolError(f"InspectCode depth must be 1..{self.MAX_DEPTH}")
|
|
1518
|
+
offset = options.get("offset")
|
|
1519
|
+
if offset is not None and (isinstance(offset, bool) or not isinstance(offset, int) or offset < 0):
|
|
1520
|
+
raise ToolError("InspectCode offset must be >= 0")
|
|
1521
|
+
ref_kind = options.get("ref_kind")
|
|
1522
|
+
if ref_kind is not None:
|
|
1523
|
+
if not isinstance(ref_kind, str):
|
|
1524
|
+
raise ToolError("InspectCode ref_kind must be a string")
|
|
1525
|
+
if options.get("all_kinds"):
|
|
1526
|
+
raise ToolError("InspectCode ref_kind and all_kinds are mutually exclusive")
|
|
1527
|
+
tokens = [token.strip() for token in ref_kind.split(",") if token.strip()]
|
|
1528
|
+
if unknown := sorted(set(tokens) - csi.REFERENCE_KINDS):
|
|
1529
|
+
raise ToolError("InspectCode unknown ref_kind: " + ", ".join(unknown) + "; valid: " + ", ".join(sorted(csi.REFERENCE_KINDS)))
|
|
1502
1530
|
index = CodeIndex(self.session)
|
|
1503
1531
|
if not index.available():
|
|
1504
1532
|
raise ToolError("code index is not available; run /index")
|
|
@@ -1520,6 +1548,16 @@ class InspectCodeTool(Tool):
|
|
|
1520
1548
|
return csi.search(target, limit=limit or csi.DEFAULT_SEARCH_LIMIT, **common)
|
|
1521
1549
|
if mode == "inspect":
|
|
1522
1550
|
return csi.inspect(target, limit=limit or csi.DEFAULT_PAGE_LIMIT, anchors=True, **common)
|
|
1551
|
+
if mode == "refs":
|
|
1552
|
+
ref_kinds = options.get("ref_kind") or ("all" if options.get("all_kinds") else "behavioral")
|
|
1553
|
+
return csi.refs(target, limit=limit or csi.DEFAULT_MAX_REFERENCES, offset=int(options.get("offset") or 0), ref_kinds=ref_kinds, **common)
|
|
1554
|
+
if mode == "impls":
|
|
1555
|
+
return csi.impls(target, limit=limit or csi.DEFAULT_MAX_IMPLEMENTORS, offset=int(options.get("offset") or 0), **common)
|
|
1556
|
+
if mode in self.CHAIN_MODES:
|
|
1557
|
+
depth = int(options.get("depth") or 3)
|
|
1558
|
+
if mode == "callees":
|
|
1559
|
+
return csi.callees(target, limit=limit or csi.DEFAULT_MAX_CALLEES, depth=depth, loose=bool(options.get("loose")), **common)
|
|
1560
|
+
return csi.callers(target, limit=limit or csi.DEFAULT_MAX_CALLERS, depth=depth, **common)
|
|
1523
1561
|
symbol = options.get("symbol") or None
|
|
1524
1562
|
return csi.outline(
|
|
1525
1563
|
target, root=self.session.cwd, symbol=str(symbol) if symbol else None, max_symbols=limit or csi.DEFAULT_MAX_OUTLINE_SYMBOLS, format="text"
|
|
@@ -4117,8 +4155,7 @@ Tools:
|
|
|
4117
4155
|
except (EOFError, KeyboardInterrupt):
|
|
4118
4156
|
pass
|
|
4119
4157
|
finally:
|
|
4120
|
-
|
|
4121
|
-
self.queue_input_text = buffer.text
|
|
4158
|
+
self.queue_input_text = buffer.text
|
|
4122
4159
|
self.queue_input_active.clear()
|
|
4123
4160
|
if self.queue_input_app is app:
|
|
4124
4161
|
self.queue_input_app = None
|
|
@@ -4137,7 +4174,8 @@ Tools:
|
|
|
4137
4174
|
UpdateChecker(self.session).start()
|
|
4138
4175
|
while True:
|
|
4139
4176
|
try:
|
|
4140
|
-
user_input = self.read_input()
|
|
4177
|
+
user_input = self.read_input(initial_text=self.queue_input_text)
|
|
4178
|
+
self.queue_input_text = ""
|
|
4141
4179
|
except EOFError:
|
|
4142
4180
|
self.emit("")
|
|
4143
4181
|
return 0
|
|
@@ -4174,7 +4212,6 @@ Tools:
|
|
|
4174
4212
|
if watcher:
|
|
4175
4213
|
watcher.join(timeout=1.0)
|
|
4176
4214
|
self.queue_input_paused.clear()
|
|
4177
|
-
self.queue_input_text = ""
|
|
4178
4215
|
self.session.state.manual_model_retry_requested = False
|
|
4179
4216
|
CodeIndex(self.session).update_pending()
|
|
4180
4217
|
self.status_bar.stop()
|
|
@@ -4233,6 +4270,7 @@ Tools:
|
|
|
4233
4270
|
multiline: bool = False,
|
|
4234
4271
|
submit_on_enter: bool = False,
|
|
4235
4272
|
prompt_style: str = "class:prompt",
|
|
4273
|
+
initial_text: str = "",
|
|
4236
4274
|
) -> str:
|
|
4237
4275
|
if self.input_history is None:
|
|
4238
4276
|
return self.input_fn(prompt_text)
|
|
@@ -4248,6 +4286,7 @@ Tools:
|
|
|
4248
4286
|
enable_history_search=True,
|
|
4249
4287
|
multiline=multiline,
|
|
4250
4288
|
accept_handler=accept,
|
|
4289
|
+
document=Document(initial_text, cursor_position=len(initial_text)),
|
|
4251
4290
|
)
|
|
4252
4291
|
search_toolbar = SearchToolbar()
|
|
4253
4292
|
control = BufferControl(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nanocode-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.12
|
|
4
4
|
Summary: A small terminal coding agent written in Python
|
|
5
5
|
Author-email: hit9 <hit9@icloud.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -22,7 +22,7 @@ Requires-Python: >=3.11
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
24
|
Requires-Dist: anthropic>=0.64.0
|
|
25
|
-
Requires-Dist: code-symbol-index>=0.
|
|
25
|
+
Requires-Dist: code-symbol-index>=0.3.0
|
|
26
26
|
Requires-Dist: json-repair
|
|
27
27
|
Requires-Dist: openai>=2.37.0
|
|
28
28
|
Requires-Dist: prompt-toolkit>=3.0
|
|
@@ -39,6 +39,8 @@ A small terminal coding agent written in Python.
|
|
|
39
39
|
|
|
40
40
|
[简体中文](README.zh-CN.md)
|
|
41
41
|
|
|
42
|
+
[Chinese blog](https://hit9.dev/post/nanocode)
|
|
43
|
+
|
|
42
44
|
nanocode is pre-1.0 software. Commands, configuration, and tool behavior may change before a stable release.
|
|
43
45
|
|
|
44
46
|

|
|
@@ -48,7 +50,7 @@ nanocode is pre-1.0 software. Commands, configuration, and tool behavior may cha
|
|
|
48
50
|
- **Live turn control**: Add follow-up input while the agent is still working, without losing the current tool flow.
|
|
49
51
|
- **File-state brain**: Reads and edits build a current, line-numbered view of the files that matter now.
|
|
50
52
|
- **Stale-edit protection**: `line:hash` anchors reject edits when the target code has drifted.
|
|
51
|
-
- **Project-aware navigation**: Use the symbol index to jump through outlines, references, and changed files quickly.
|
|
53
|
+
- **Project-aware navigation**: Use the symbol index to jump through outlines, references, implementors, call chains, and changed files quickly.
|
|
52
54
|
- **Recoverable context**: Tool output stays bounded in the prompt, while raw `tr.N` results remain recallable.
|
|
53
55
|
- **Cache-aware context**: Stable sections stay early and noisy working state stays late to improve prompt-cache reuse.
|
|
54
56
|
- **Focused working memory**: `Note` separates goal, plan, and known facts from noisy execution logs.
|
|
@@ -138,6 +140,16 @@ Main fields:
|
|
|
138
140
|
|
|
139
141
|
`api = "auto"` chooses between Chat Completions and Anthropic Messages using provider/model profiles. `prompt_cache_key = "auto"` derives a stable key from provider, model, workspace, and tool schema names.
|
|
140
142
|
|
|
143
|
+
|
|
144
|
+
## Tested Providers
|
|
145
|
+
|
|
146
|
+
The following providers have been tested with nanocode:
|
|
147
|
+
|
|
148
|
+
- **deepseek**: DeepSeek API
|
|
149
|
+
- **opencode**: OpenCode API
|
|
150
|
+
- **aliyun**: Alibaba Cloud (Tongyi Qianwen) API via Chat Completions
|
|
151
|
+
- **llama.cpp**: Local inference via llama.cpp server
|
|
152
|
+
|
|
141
153
|
## Context Design
|
|
142
154
|
|
|
143
155
|
Each model request is built manually from explicit messages. Stable context comes first, conversation stays as messages, working memory follows, and the latest file state is appended at the end.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nanocode-cli"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.12"
|
|
8
8
|
description = "A small terminal coding agent written in Python"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
|
28
28
|
]
|
|
29
29
|
dependencies = [
|
|
30
30
|
"anthropic>=0.64.0",
|
|
31
|
-
"code-symbol-index>=0.
|
|
31
|
+
"code-symbol-index>=0.3.0",
|
|
32
32
|
"json-repair",
|
|
33
33
|
"openai>=2.37.0",
|
|
34
34
|
"prompt-toolkit>=3.0",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|