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.
- {weio_cli-0.2.0/src/weio_cli.egg-info → weio_cli-0.3.0}/PKG-INFO +14 -1
- {weio_cli-0.2.0 → weio_cli-0.3.0}/README.md +13 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/pyproject.toml +1 -1
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/__init__.py +1 -1
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/cli.py +26 -2
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/tui.py +7 -0
- weio_cli-0.3.0/src/weio_cli/updater.py +114 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0/src/weio_cli.egg-info}/PKG-INFO +14 -1
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli.egg-info/SOURCES.txt +1 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/LICENSE +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/setup.cfg +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/__main__.py +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/client.py +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/coder.py +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli/config.py +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli.egg-info/dependency_links.txt +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli.egg-info/entry_points.txt +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli.egg-info/requires.txt +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/src/weio_cli.egg-info/top_level.txt +0 -0
- {weio_cli-0.2.0 → weio_cli-0.3.0}/tests/test_coder.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: weio-cli
|
|
3
|
-
Version: 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.
|
|
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"
|
|
@@ -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
|
-
|
|
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.
|
|
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 |
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|