weio-cli 0.2.0__tar.gz → 0.3.0__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: weio-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Weio — an agentic coding assistant that routes inference through your Weio account.
5
5
  Author: We I/O Labs
6
6
  License: MIT
@@ -93,6 +93,19 @@ weio ping
93
93
  Edits are shown as a diff and require confirmation before anything is written
94
94
  (use `-y`/`--yes` to apply automatically). New files are created as needed.
95
95
 
96
+ ## Updating
97
+
98
+ weio-cli checks PyPI once a day (fail-silent) and prints a one-line notice when a
99
+ newer version is available. To upgrade:
100
+
101
+ ```bash
102
+ weio update # upgrades in place via pip
103
+ # or
104
+ pip install -U weio-cli
105
+ ```
106
+
107
+ Disable the check with `WEIO_NO_UPDATE_CHECK=1`.
108
+
96
109
  ## Configuration
97
110
 
98
111
  | Setting | Flag | Env | Config file |
@@ -71,6 +71,19 @@ weio ping
71
71
  Edits are shown as a diff and require confirmation before anything is written
72
72
  (use `-y`/`--yes` to apply automatically). New files are created as needed.
73
73
 
74
+ ## Updating
75
+
76
+ weio-cli checks PyPI once a day (fail-silent) and prints a one-line notice when a
77
+ newer version is available. To upgrade:
78
+
79
+ ```bash
80
+ weio update # upgrades in place via pip
81
+ # or
82
+ pip install -U weio-cli
83
+ ```
84
+
85
+ Disable the check with `WEIO_NO_UPDATE_CHECK=1`.
86
+
74
87
  ## Configuration
75
88
 
76
89
  | Setting | Flag | Env | Config file |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "weio-cli"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "Weio — an agentic coding assistant that routes inference through your Weio account."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """Weio CLI — an agentic coding assistant that routes inference through your Weio account."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"
@@ -128,6 +128,16 @@ def cmd_chat(args) -> int:
128
128
  return 0
129
129
 
130
130
 
131
+ def cmd_update(args) -> int:
132
+ from . import updater
133
+ latest = updater.check_for_update(force=True)
134
+ if not latest:
135
+ print(_c(f"weio-cli {__version__} is up to date.", "32"))
136
+ return 0
137
+ print(_c(f"Updating weio-cli {__version__} → {latest}…", "36"))
138
+ return updater.self_update()
139
+
140
+
131
141
  def cmd_tui(args) -> int:
132
142
  try:
133
143
  client = _make_client(args)
@@ -257,6 +267,9 @@ def build_parser() -> argparse.ArgumentParser:
257
267
  sp.add_argument("--dir", "-C", default=".", help="Project directory (default: cwd)")
258
268
  sp.set_defaults(func=cmd_tui)
259
269
 
270
+ sp = sub.add_parser("update", parents=[common], help="Update weio-cli to the latest version")
271
+ sp.set_defaults(func=cmd_update)
272
+
260
273
  sp = sub.add_parser("code", parents=[common], help="Run a coding task in a directory")
261
274
  sp.add_argument("message")
262
275
  sp.add_argument("--file", "-f", action="append", help="Add a file to the context (repeatable)")
@@ -271,7 +284,7 @@ def main(argv=None) -> int:
271
284
  argv = list(sys.argv[1:] if argv is None else argv)
272
285
  parser = build_parser()
273
286
 
274
- known = {"login", "ping", "ask", "chat", "code", "tui"}
287
+ known = {"login", "ping", "ask", "chat", "code", "tui", "update"}
275
288
  # Bare `weio` (no args) → interactive coding TUI, like Claude Code.
276
289
  if not argv:
277
290
  argv = ["tui"]
@@ -284,10 +297,21 @@ def main(argv=None) -> int:
284
297
  parser.print_help()
285
298
  return 1
286
299
  try:
287
- return args.func(args)
300
+ rc = args.func(args)
288
301
  except KeyboardInterrupt:
289
302
  print()
290
303
  return 130
304
+ # Throttled, fail-silent update notice (skipped for tui — it shows its own
305
+ # in the header — and for the update command itself).
306
+ if args.command not in ("update", "tui"):
307
+ try:
308
+ from . import updater
309
+ notice = updater.update_notice()
310
+ if notice:
311
+ print(_c("\n" + notice, "33"), file=sys.stderr)
312
+ except Exception:
313
+ pass
314
+ return rc
291
315
 
292
316
 
293
317
  if __name__ == "__main__":
@@ -283,6 +283,13 @@ class Repl:
283
283
  print(_c(f" {self.client.base} · " +
284
284
  ("connected" if ok else "⚠ cannot reach gateway / bad key"),
285
285
  GREEN if ok else RED))
286
+ try:
287
+ from .updater import update_notice
288
+ notice = update_notice()
289
+ if notice:
290
+ print(_c(" ⬆ " + notice, YELLOW))
291
+ except Exception:
292
+ pass
286
293
  print(_c(" Type a request, or /help. Ctrl-D to exit.\n", DIM))
287
294
  while True:
288
295
  text = self._read()
@@ -0,0 +1,114 @@
1
+ """Update checking + self-update.
2
+
3
+ A throttled, fail-silent check against PyPI (once per day) tells the user when a
4
+ newer weio-cli is published. `weio update` upgrades in place. Disable the check
5
+ with WEIO_NO_UPDATE_CHECK=1.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import os
11
+ import subprocess
12
+ import sys
13
+ import time
14
+ from pathlib import Path
15
+ from typing import Optional
16
+
17
+ from . import __version__
18
+
19
+ INDEX_JSON = os.environ.get("WEIO_UPDATE_INDEX", "https://pypi.org/pypi/weio-cli/json")
20
+ _CACHE_NAME = "update_check.json"
21
+ _TTL_HOURS = 24
22
+
23
+
24
+ def _cache_dir() -> Path:
25
+ return Path(os.environ.get("WEIO_CONFIG_DIR", str(Path.home() / ".weio")))
26
+
27
+
28
+ def _parse_version(v: str) -> tuple:
29
+ """Lenient numeric version tuple, e.g. '0.10.2' -> (0, 10, 2)."""
30
+ out = []
31
+ for part in (v or "").split("."):
32
+ num = ""
33
+ for ch in part:
34
+ if ch.isdigit():
35
+ num += ch
36
+ else:
37
+ break
38
+ out.append(int(num) if num else 0)
39
+ return tuple(out) or (0,)
40
+
41
+
42
+ def is_newer(latest: str, current: str) -> bool:
43
+ return _parse_version(latest) > _parse_version(current)
44
+
45
+
46
+ def fetch_latest(timeout: float = 2.5) -> Optional[str]:
47
+ try:
48
+ import httpx
49
+ r = httpx.get(INDEX_JSON, timeout=timeout,
50
+ headers={"User-Agent": f"weio-cli/{__version__}"})
51
+ if r.status_code != 200:
52
+ return None
53
+ return r.json()["info"]["version"]
54
+ except Exception:
55
+ return None
56
+
57
+
58
+ def check_for_update(current: str = __version__, *, ttl_hours: int = _TTL_HOURS,
59
+ force: bool = False) -> Optional[str]:
60
+ """Return the latest version string if newer than `current`, else None.
61
+
62
+ Throttled to once per ttl_hours via a cache file; never raises.
63
+ """
64
+ if os.environ.get("WEIO_NO_UPDATE_CHECK") == "1":
65
+ return None
66
+ try:
67
+ cache = _cache_dir() / _CACHE_NAME
68
+ data = {}
69
+ if cache.exists():
70
+ try:
71
+ data = json.loads(cache.read_text())
72
+ except Exception:
73
+ data = {}
74
+ now = time.time()
75
+ latest = data.get("latest")
76
+ last = float(data.get("last_check", 0) or 0)
77
+
78
+ if force or not latest or (now - last) > ttl_hours * 3600:
79
+ fetched = fetch_latest()
80
+ if fetched:
81
+ latest = fetched
82
+ try:
83
+ cache.parent.mkdir(parents=True, exist_ok=True)
84
+ cache.write_text(json.dumps({"last_check": now, "latest": latest}))
85
+ except Exception:
86
+ pass
87
+
88
+ if latest and is_newer(latest, current):
89
+ return latest
90
+ except Exception:
91
+ pass
92
+ return None
93
+
94
+
95
+ def update_notice(current: str = __version__) -> Optional[str]:
96
+ """One-line, color-free notice if an update is available (for printing)."""
97
+ latest = check_for_update(current)
98
+ if not latest:
99
+ return None
100
+ return (f"weio-cli {latest} is available (you have {current}). "
101
+ f"Update with: weio update")
102
+
103
+
104
+ def self_update(pre: bool = False) -> int:
105
+ """Upgrade weio-cli in place using the running interpreter's pip."""
106
+ cmd = [sys.executable, "-m", "pip", "install", "--upgrade", "weio-cli"]
107
+ if pre:
108
+ cmd.append("--pre")
109
+ print(f"Running: {' '.join(cmd)}")
110
+ try:
111
+ return subprocess.call(cmd)
112
+ except Exception as e:
113
+ print(f"Update failed: {e}", file=sys.stderr)
114
+ return 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weio-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Weio — an agentic coding assistant that routes inference through your Weio account.
5
5
  Author: We I/O Labs
6
6
  License: MIT
@@ -93,6 +93,19 @@ weio ping
93
93
  Edits are shown as a diff and require confirmation before anything is written
94
94
  (use `-y`/`--yes` to apply automatically). New files are created as needed.
95
95
 
96
+ ## Updating
97
+
98
+ weio-cli checks PyPI once a day (fail-silent) and prints a one-line notice when a
99
+ newer version is available. To upgrade:
100
+
101
+ ```bash
102
+ weio update # upgrades in place via pip
103
+ # or
104
+ pip install -U weio-cli
105
+ ```
106
+
107
+ Disable the check with `WEIO_NO_UPDATE_CHECK=1`.
108
+
96
109
  ## Configuration
97
110
 
98
111
  | Setting | Flag | Env | Config file |
@@ -8,6 +8,7 @@ src/weio_cli/client.py
8
8
  src/weio_cli/coder.py
9
9
  src/weio_cli/config.py
10
10
  src/weio_cli/tui.py
11
+ src/weio_cli/updater.py
11
12
  src/weio_cli.egg-info/PKG-INFO
12
13
  src/weio_cli.egg-info/SOURCES.txt
13
14
  src/weio_cli.egg-info/dependency_links.txt
File without changes
File without changes
File without changes
File without changes