nanocode-cli 0.8.0__tar.gz → 0.8.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nanocode-cli
3
- Version: 0.8.0
3
+ Version: 0.8.1
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
@@ -104,6 +104,7 @@ Useful arguments:
104
104
  - `--mcp <selector>`: choose which configured MCP servers to enable.
105
105
  - `--debug`: write model I/O debug traces.
106
106
  - `-v`, `--version`: show the version.
107
+ - `update` / `upgrade`: update nanocode to the latest release, using the right installer (uv tool, pipx, or pip) for how it was installed.
107
108
 
108
109
  During a running turn, type into the `+>` prompt to add follow-up input for the next model request.
109
110
 
@@ -67,6 +67,7 @@ Useful arguments:
67
67
  - `--mcp <selector>`: choose which configured MCP servers to enable.
68
68
  - `--debug`: write model I/O debug traces.
69
69
  - `-v`, `--version`: show the version.
70
+ - `update` / `upgrade`: update nanocode to the latest release, using the right installer (uv tool, pipx, or pip) for how it was installed.
70
71
 
71
72
  During a running turn, type into the `+>` prompt to add follow-up input for the next model request.
72
73
 
@@ -67,6 +67,7 @@ nanocode
67
67
  - `--mcp <selector>`:选择启用哪些已配置的 MCP 服务器。
68
68
  - `--debug`:写入模型 I/O debug trace。
69
69
  - `-v`, `--version`:显示版本。
70
+ - `update` / `upgrade`:将 nanocode 更新到最新版本,并根据安装方式(uv tool、pipx 或 pip)选择正确的升级方式。
70
71
 
71
72
  代理运行中,可以在 `+>` 提示符里输入追加内容,发送到下一次模型请求。
72
73
 
@@ -63,7 +63,7 @@ from rich.console import Console
63
63
  from rich.markdown import Markdown
64
64
  from rich.rule import Rule
65
65
 
66
- __version__ = "0.8.0"
66
+ __version__ = "0.8.1"
67
67
 
68
68
  Json = dict[str, Any]
69
69
  HTTP_USER_AGENT = "nanocode/" + __version__
@@ -8480,6 +8480,68 @@ Tools:
8480
8480
  return "Set " + key
8481
8481
 
8482
8482
 
8483
+ class Updater:
8484
+ """Upgrade nanocode in place, choosing the command that matches how it was installed."""
8485
+
8486
+ PACKAGE = "nanocode-cli"
8487
+
8488
+ def run(self) -> int:
8489
+ try:
8490
+ latest = self.fetch_latest()
8491
+ except Exception as error:
8492
+ print("Error: failed to check latest version: " + Text.clean(str(error)), file=sys.stderr)
8493
+ return 1
8494
+ if not UpdateStatus(latest=latest).newer_than(__version__):
8495
+ print(f"nanocode {__version__} is already up to date (latest: {latest}).")
8496
+ return 0
8497
+ method, command = self.detect()
8498
+ if command is None:
8499
+ print(f"nanocode {__version__} -> {latest} available, but this is an {method} install.", file=sys.stderr)
8500
+ print("Update it the same way you installed it (e.g. git pull, or reinstall).", file=sys.stderr)
8501
+ return 1
8502
+ print(f"Updating nanocode {__version__} -> {latest} ({method}): {' '.join(command)}")
8503
+ try:
8504
+ result = subprocess.run(command)
8505
+ except Exception as error:
8506
+ print("Error: upgrade command failed: " + Text.clean(str(error)), file=sys.stderr)
8507
+ return 1
8508
+ if result.returncode != 0:
8509
+ print("Error: upgrade command exited with status " + str(result.returncode), file=sys.stderr)
8510
+ return result.returncode
8511
+ print(f"Updated nanocode to {latest}.")
8512
+ return 0
8513
+
8514
+ def fetch_latest(self) -> str:
8515
+ request = Request(UpdateChecker.PYPI_URL, headers={"Accept": "application/json", "User-Agent": HTTP_USER_AGENT})
8516
+ with urlopen(request, timeout=UpdateChecker.TIMEOUT) as response:
8517
+ data = json.loads(response.read().decode("utf-8", "replace"))
8518
+ version = data.get("info", {}).get("version") if isinstance(data, dict) else ""
8519
+ if not isinstance(version, str) or not UpdateStatus.version_tuple(version):
8520
+ raise NanocodeError("invalid PyPI version response")
8521
+ return version
8522
+
8523
+ def detect(self) -> tuple[str, list[str] | None]:
8524
+ """Return (method label, upgrade command). command is None when we cannot self-update."""
8525
+ if self.is_editable():
8526
+ return "editable", None
8527
+ location = os.path.realpath(os.path.dirname(__file__))
8528
+ if os.sep + "uv" + os.sep + "tools" + os.sep in location + os.sep and shutil.which("uv"):
8529
+ return "uv tool", ["uv", "tool", "upgrade", self.PACKAGE]
8530
+ if os.sep + "pipx" + os.sep in location + os.sep and shutil.which("pipx"):
8531
+ return "pipx", ["pipx", "upgrade", self.PACKAGE]
8532
+ return "pip", [sys.executable, "-m", "pip", "install", "--upgrade", self.PACKAGE]
8533
+
8534
+ @staticmethod
8535
+ def is_editable() -> bool:
8536
+ try:
8537
+ import importlib.metadata as metadata
8538
+
8539
+ raw = metadata.distribution(Updater.PACKAGE).read_text("direct_url.json")
8540
+ return bool(raw) and json.loads(raw).get("dir_info", {}).get("editable", False)
8541
+ except Exception:
8542
+ return False
8543
+
8544
+
8483
8545
  def main(argv: list[str] | None = None) -> int:
8484
8546
  parser = argparse.ArgumentParser(prog="nanocode")
8485
8547
  parser.add_argument("--config", default=None, help="Path to config TOML")
@@ -8489,10 +8551,13 @@ def main(argv: list[str] | None = None) -> int:
8489
8551
  parser.add_argument("--mcp", default="", help='Filter MCP servers, e.g. "orion*,!orionEval", "all", or "none"')
8490
8552
  parser.add_argument("--resume", default="", nargs="?", const="latest", help='Resume a session by UID, or "latest"/"last" for most recent')
8491
8553
  parser.add_argument("-v", "--version", action="store_true", help="Show version")
8554
+ parser.add_argument("command", nargs="?", choices=["update", "upgrade"], help="Update nanocode to the latest version")
8492
8555
  args = parser.parse_args(argv)
8493
8556
  if args.version:
8494
8557
  print(__version__)
8495
8558
  return 0
8559
+ if args.command in ("update", "upgrade"):
8560
+ return Updater().run()
8496
8561
  try:
8497
8562
  if args.init_config:
8498
8563
  path, created = ConfigFile.init(args.config)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nanocode-cli
3
- Version: 0.8.0
3
+ Version: 0.8.1
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
@@ -104,6 +104,7 @@ Useful arguments:
104
104
  - `--mcp <selector>`: choose which configured MCP servers to enable.
105
105
  - `--debug`: write model I/O debug traces.
106
106
  - `-v`, `--version`: show the version.
107
+ - `update` / `upgrade`: update nanocode to the latest release, using the right installer (uv tool, pipx, or pip) for how it was installed.
107
108
 
108
109
  During a running turn, type into the `+>` prompt to add follow-up input for the next model request.
109
110
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nanocode-cli"
7
- version = "0.8.0"
7
+ version = "0.8.1"
8
8
  description = "A small terminal coding agent written in Python"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes