weio-cli 0.2.0__tar.gz → 0.4.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.4.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
@@ -35,14 +35,29 @@ Requires Python 3.9+.
35
35
 
36
36
  ## Authenticate
37
37
 
38
- Generate an API key in **Settings → API & CLI** on weio.ai, then:
38
+ ```bash
39
+ weio login # opens your browser, sign in (incl. Google), key is created automatically
40
+ ```
41
+
42
+ `weio login` starts a one-time local handshake, opens weio.ai in your browser to
43
+ sign in, mints an API key for this device, and saves it to `~/.weio/config.json`.
44
+ No copy-paste.
45
+
46
+ Prefer to paste a key yourself? Generate one in **Settings → API & CLI** on
47
+ weio.ai and:
39
48
 
40
49
  ```bash
41
- weio login # paste your weio_sk_… key (saved to ~/.weio/config.json)
42
- # or, per-session:
50
+ weio login --no-browser # paste your weio_sk_… key
51
+ # or, per session:
43
52
  export WEIO_API_KEY="weio_sk_…"
44
53
  ```
45
54
 
55
+ Check what you're using:
56
+
57
+ ```bash
58
+ weio usage # tier, tokens used today, remaining, reset time
59
+ ```
60
+
46
61
  ## Use
47
62
 
48
63
  ### Interactive TUI (default)
@@ -93,6 +108,19 @@ weio ping
93
108
  Edits are shown as a diff and require confirmation before anything is written
94
109
  (use `-y`/`--yes` to apply automatically). New files are created as needed.
95
110
 
111
+ ## Updating
112
+
113
+ weio-cli checks PyPI once a day (fail-silent) and prints a one-line notice when a
114
+ newer version is available. To upgrade:
115
+
116
+ ```bash
117
+ weio update # upgrades in place via pip
118
+ # or
119
+ pip install -U weio-cli
120
+ ```
121
+
122
+ Disable the check with `WEIO_NO_UPDATE_CHECK=1`.
123
+
96
124
  ## Configuration
97
125
 
98
126
  | Setting | Flag | Env | Config file |
@@ -13,14 +13,29 @@ Requires Python 3.9+.
13
13
 
14
14
  ## Authenticate
15
15
 
16
- Generate an API key in **Settings → API & CLI** on weio.ai, then:
16
+ ```bash
17
+ weio login # opens your browser, sign in (incl. Google), key is created automatically
18
+ ```
19
+
20
+ `weio login` starts a one-time local handshake, opens weio.ai in your browser to
21
+ sign in, mints an API key for this device, and saves it to `~/.weio/config.json`.
22
+ No copy-paste.
23
+
24
+ Prefer to paste a key yourself? Generate one in **Settings → API & CLI** on
25
+ weio.ai and:
17
26
 
18
27
  ```bash
19
- weio login # paste your weio_sk_… key (saved to ~/.weio/config.json)
20
- # or, per-session:
28
+ weio login --no-browser # paste your weio_sk_… key
29
+ # or, per session:
21
30
  export WEIO_API_KEY="weio_sk_…"
22
31
  ```
23
32
 
33
+ Check what you're using:
34
+
35
+ ```bash
36
+ weio usage # tier, tokens used today, remaining, reset time
37
+ ```
38
+
24
39
  ## Use
25
40
 
26
41
  ### Interactive TUI (default)
@@ -71,6 +86,19 @@ weio ping
71
86
  Edits are shown as a diff and require confirmation before anything is written
72
87
  (use `-y`/`--yes` to apply automatically). New files are created as needed.
73
88
 
89
+ ## Updating
90
+
91
+ weio-cli checks PyPI once a day (fail-silent) and prints a one-line notice when a
92
+ newer version is available. To upgrade:
93
+
94
+ ```bash
95
+ weio update # upgrades in place via pip
96
+ # or
97
+ pip install -U weio-cli
98
+ ```
99
+
100
+ Disable the check with `WEIO_NO_UPDATE_CHECK=1`.
101
+
74
102
  ## Configuration
75
103
 
76
104
  | 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.4.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.4.0"
@@ -0,0 +1,88 @@
1
+ """Browser-based login: open Weio in the browser, sign in (incl. Google), and
2
+ receive a freshly-minted API key on a local loopback server. No manual key paste.
3
+
4
+ Standard OAuth-CLI loopback pattern (like gcloud / gh): we start a localhost
5
+ server, open the browser to the Weio authorize page with our port + a random
6
+ state, the page mints a key and redirects back to the loopback with it.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import http.server
11
+ import secrets
12
+ import socketserver
13
+ import sys
14
+ import time
15
+ import urllib.parse
16
+ import webbrowser
17
+ from typing import Optional
18
+
19
+
20
+ def _web_base_from_api(api_base: str) -> str:
21
+ """https://weio.ai/v1 -> https://weio.ai"""
22
+ b = (api_base or "").rstrip("/")
23
+ if b.endswith("/v1"):
24
+ b = b[:-3]
25
+ return b.rstrip("/")
26
+
27
+
28
+ _DONE_HTML = (
29
+ b"<!doctype html><html><head><meta charset='utf-8'><title>Weio CLI</title></head>"
30
+ b"<body style='font-family:-apple-system,Segoe UI,sans-serif;background:#0d1117;"
31
+ b"color:#e6edf3;display:flex;align-items:center;justify-content:center;height:100vh;margin:0'>"
32
+ b"<div style='text-align:center'><h2 style='color:#3fb950'>&#10003; Weio CLI authorized</h2>"
33
+ b"<p>You can close this tab and return to your terminal.</p></div></body></html>"
34
+ )
35
+ _FAIL_HTML = (
36
+ b"<!doctype html><html><body style='font-family:sans-serif'>"
37
+ b"<h2>Authorization failed.</h2><p>Please run <code>weio login</code> again.</p></body></html>"
38
+ )
39
+
40
+
41
+ def browser_login(api_base: str, timeout: float = 180.0) -> Optional[str]:
42
+ """Open the browser and return the minted API key, or None on failure/timeout."""
43
+ state = secrets.token_urlsafe(16)
44
+ result: dict = {}
45
+
46
+ class Handler(http.server.BaseHTTPRequestHandler):
47
+ def do_GET(self): # noqa: N802
48
+ params = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
49
+ key = (params.get("key") or [None])[0]
50
+ st = (params.get("state") or [None])[0]
51
+ ok = bool(key) and st == state
52
+ self.send_response(200)
53
+ self.send_header("Content-Type", "text/html; charset=utf-8")
54
+ self.end_headers()
55
+ self.wfile.write(_DONE_HTML if ok else _FAIL_HTML)
56
+ if ok:
57
+ result["key"] = key
58
+
59
+ def log_message(self, *args): # silence
60
+ pass
61
+
62
+ try:
63
+ httpd = socketserver.TCPServer(("127.0.0.1", 0), Handler)
64
+ except OSError as e:
65
+ print(f"Could not start local auth server: {e}", file=sys.stderr)
66
+ return None
67
+ httpd.timeout = 1
68
+ port = httpd.server_address[1]
69
+ auth_url = (f"{_web_base_from_api(api_base)}/cli/auth"
70
+ f"?port={port}&state={urllib.parse.quote(state)}")
71
+
72
+ print("Opening your browser to sign in to Weio…")
73
+ print(f" {auth_url}")
74
+ print(" (If it doesn't open, copy that URL into your browser.)")
75
+ try:
76
+ webbrowser.open(auth_url)
77
+ except Exception:
78
+ pass
79
+
80
+ deadline = time.time() + timeout
81
+ try:
82
+ while "key" not in result and time.time() < deadline:
83
+ httpd.handle_request()
84
+ except KeyboardInterrupt:
85
+ pass
86
+ finally:
87
+ httpd.server_close()
88
+ return result.get("key")
@@ -43,14 +43,33 @@ def _c(text: str, code: str) -> str:
43
43
  def cmd_login(args) -> int:
44
44
  cli_key = getattr(args, "key", None)
45
45
  cli_base = getattr(args, "base", None)
46
- key = cli_key or input("Weio API key (weio_sk_…): ").strip()
46
+ base = config.resolve_base(cli_base)
47
+ no_browser = getattr(args, "no_browser", False)
48
+
49
+ key = cli_key
50
+ # Default: open the browser, sign in (incl. Google), auto-mint a key.
51
+ if not key and not no_browser:
52
+ try:
53
+ from .browser_login import browser_login
54
+ key = browser_login(base)
55
+ except Exception as e:
56
+ print(_c(f"Browser sign-in unavailable ({e}).", "33"), file=sys.stderr)
57
+ if not key:
58
+ print(_c("Browser sign-in didn't complete. Falling back to manual key entry.", "33"))
59
+ # Fallback / explicit: paste a key from Settings → API & CLI.
60
+ if not key:
61
+ try:
62
+ key = input("Weio API key (weio_sk_…): ").strip()
63
+ except (EOFError, KeyboardInterrupt):
64
+ print()
65
+ return 2
47
66
  if not key:
48
67
  print("No key provided.", file=sys.stderr)
49
68
  return 2
69
+
50
70
  path = config.save(key=key, base=cli_base)
51
- # Validate
52
71
  try:
53
- client = WeioClient(key, config.resolve_base(cli_base))
72
+ client = WeioClient(key, base)
54
73
  ok = client.ping()
55
74
  except WeioError:
56
75
  ok = False
@@ -128,6 +147,42 @@ def cmd_chat(args) -> int:
128
147
  return 0
129
148
 
130
149
 
150
+ def cmd_usage(args) -> int:
151
+ try:
152
+ client = _make_client(args)
153
+ except WeioError as e:
154
+ print(_c(str(e), "31"), file=sys.stderr)
155
+ return 2
156
+ try:
157
+ u = client.usage()
158
+ except WeioError as e:
159
+ print(_c(str(e), "31"), file=sys.stderr)
160
+ return 1
161
+ used = u.get("daily_tokens_used", 0)
162
+ limit = u.get("daily_token_limit", 0)
163
+ remaining = u.get("daily_tokens_remaining", 0)
164
+ pct = (used / limit * 100) if limit else 0
165
+ bar_n = int(pct / 5)
166
+ bar = "█" * bar_n + "░" * (20 - bar_n)
167
+ print(_c(f" account ", "2") + f"{u.get('email','?')} ({u.get('tier','?')})")
168
+ print(_c(f" today ", "2") + f"{used:,} / {limit:,} tokens ({pct:.0f}%)")
169
+ print(_c(f" ", "2") + _c(bar, "32" if pct < 80 else "33"))
170
+ print(_c(f" remaining", "2") + f" {remaining:,} tokens")
171
+ if u.get("reset_at"):
172
+ print(_c(f" resets ", "2") + f"{u['reset_at']}")
173
+ return 0
174
+
175
+
176
+ def cmd_update(args) -> int:
177
+ from . import updater
178
+ latest = updater.check_for_update(force=True)
179
+ if not latest:
180
+ print(_c(f"weio-cli {__version__} is up to date.", "32"))
181
+ return 0
182
+ print(_c(f"Updating weio-cli {__version__} → {latest}…", "36"))
183
+ return updater.self_update()
184
+
185
+
131
186
  def cmd_tui(args) -> int:
132
187
  try:
133
188
  client = _make_client(args)
@@ -226,7 +281,7 @@ def build_parser() -> argparse.ArgumentParser:
226
281
  common.add_argument("--key", "-k", default=argparse.SUPPRESS,
227
282
  help="API key (or set WEIO_API_KEY / run `weio login`)")
228
283
  common.add_argument("--base", default=argparse.SUPPRESS,
229
- help="API base URL (default https://api.weio.ai/v1)")
284
+ help="API base URL (default https://weio.ai/v1)")
230
285
  common.add_argument("--model", "-m", default=argparse.SUPPRESS, help="Model id (default: auto)")
231
286
  common.add_argument("--max-tokens", type=int, default=argparse.SUPPRESS, help="Max output tokens")
232
287
 
@@ -239,7 +294,10 @@ def build_parser() -> argparse.ArgumentParser:
239
294
 
240
295
  sub = p.add_subparsers(dest="command")
241
296
 
242
- sp = sub.add_parser("login", parents=[common], help="Save your API key")
297
+ sp = sub.add_parser("login", parents=[common],
298
+ help="Sign in via browser (or --no-browser to paste a key)")
299
+ sp.add_argument("--no-browser", action="store_true",
300
+ help="Skip the browser flow and paste an API key manually")
243
301
  sp.set_defaults(func=cmd_login)
244
302
 
245
303
  sp = sub.add_parser("ping", parents=[common], help="Check connectivity and key")
@@ -257,6 +315,12 @@ def build_parser() -> argparse.ArgumentParser:
257
315
  sp.add_argument("--dir", "-C", default=".", help="Project directory (default: cwd)")
258
316
  sp.set_defaults(func=cmd_tui)
259
317
 
318
+ sp = sub.add_parser("usage", parents=[common], help="Show your token usage and limits")
319
+ sp.set_defaults(func=cmd_usage)
320
+
321
+ sp = sub.add_parser("update", parents=[common], help="Update weio-cli to the latest version")
322
+ sp.set_defaults(func=cmd_update)
323
+
260
324
  sp = sub.add_parser("code", parents=[common], help="Run a coding task in a directory")
261
325
  sp.add_argument("message")
262
326
  sp.add_argument("--file", "-f", action="append", help="Add a file to the context (repeatable)")
@@ -271,7 +335,7 @@ def main(argv=None) -> int:
271
335
  argv = list(sys.argv[1:] if argv is None else argv)
272
336
  parser = build_parser()
273
337
 
274
- known = {"login", "ping", "ask", "chat", "code", "tui"}
338
+ known = {"login", "ping", "ask", "chat", "code", "tui", "update", "usage"}
275
339
  # Bare `weio` (no args) → interactive coding TUI, like Claude Code.
276
340
  if not argv:
277
341
  argv = ["tui"]
@@ -284,10 +348,21 @@ def main(argv=None) -> int:
284
348
  parser.print_help()
285
349
  return 1
286
350
  try:
287
- return args.func(args)
351
+ rc = args.func(args)
288
352
  except KeyboardInterrupt:
289
353
  print()
290
354
  return 130
355
+ # Throttled, fail-silent update notice (skipped for tui — it shows its own
356
+ # in the header — and for the update command itself).
357
+ if args.command not in ("update", "tui"):
358
+ try:
359
+ from . import updater
360
+ notice = updater.update_notice()
361
+ if notice:
362
+ print(_c("\n" + notice, "33"), file=sys.stderr)
363
+ except Exception:
364
+ pass
365
+ return rc
291
366
 
292
367
 
293
368
  if __name__ == "__main__":
@@ -108,6 +108,21 @@ class WeioClient:
108
108
  except httpx.HTTPError as e:
109
109
  raise WeioError(f"Network error talking to {self.base}: {e}") from e
110
110
 
111
+ def usage(self) -> dict:
112
+ """Fetch account usage + limits."""
113
+ try:
114
+ r = httpx.get(f"{self.base}/usage", headers=self._headers(), timeout=15.0)
115
+ except httpx.HTTPError as e:
116
+ raise WeioError(f"Network error talking to {self.base}: {e}") from e
117
+ if r.status_code == 401:
118
+ raise WeioError("Authentication failed (401). Check your API key.")
119
+ if r.status_code >= 400:
120
+ raise WeioError(f"Gateway error {r.status_code}: {r.text[:200]}")
121
+ try:
122
+ return r.json()
123
+ except json.JSONDecodeError as e:
124
+ raise WeioError(f"Unexpected response: {r.text[:200]}") from e
125
+
111
126
  def ping(self) -> bool:
112
127
  """Check the gateway is reachable and the key is valid (GET /models)."""
113
128
  try:
@@ -13,7 +13,7 @@ import os
13
13
  from pathlib import Path
14
14
  from typing import Optional
15
15
 
16
- DEFAULT_BASE = "https://api.weio.ai/v1"
16
+ DEFAULT_BASE = "https://weio.ai/v1"
17
17
 
18
18
  CONFIG_DIR = Path(os.environ.get("WEIO_CONFIG_DIR", str(Path.home() / ".weio")))
19
19
  CONFIG_FILE = CONFIG_DIR / "config.json"
@@ -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.4.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
@@ -35,14 +35,29 @@ Requires Python 3.9+.
35
35
 
36
36
  ## Authenticate
37
37
 
38
- Generate an API key in **Settings → API & CLI** on weio.ai, then:
38
+ ```bash
39
+ weio login # opens your browser, sign in (incl. Google), key is created automatically
40
+ ```
41
+
42
+ `weio login` starts a one-time local handshake, opens weio.ai in your browser to
43
+ sign in, mints an API key for this device, and saves it to `~/.weio/config.json`.
44
+ No copy-paste.
45
+
46
+ Prefer to paste a key yourself? Generate one in **Settings → API & CLI** on
47
+ weio.ai and:
39
48
 
40
49
  ```bash
41
- weio login # paste your weio_sk_… key (saved to ~/.weio/config.json)
42
- # or, per-session:
50
+ weio login --no-browser # paste your weio_sk_… key
51
+ # or, per session:
43
52
  export WEIO_API_KEY="weio_sk_…"
44
53
  ```
45
54
 
55
+ Check what you're using:
56
+
57
+ ```bash
58
+ weio usage # tier, tokens used today, remaining, reset time
59
+ ```
60
+
46
61
  ## Use
47
62
 
48
63
  ### Interactive TUI (default)
@@ -93,6 +108,19 @@ weio ping
93
108
  Edits are shown as a diff and require confirmation before anything is written
94
109
  (use `-y`/`--yes` to apply automatically). New files are created as needed.
95
110
 
111
+ ## Updating
112
+
113
+ weio-cli checks PyPI once a day (fail-silent) and prints a one-line notice when a
114
+ newer version is available. To upgrade:
115
+
116
+ ```bash
117
+ weio update # upgrades in place via pip
118
+ # or
119
+ pip install -U weio-cli
120
+ ```
121
+
122
+ Disable the check with `WEIO_NO_UPDATE_CHECK=1`.
123
+
96
124
  ## Configuration
97
125
 
98
126
  | Setting | Flag | Env | Config file |
@@ -3,11 +3,13 @@ README.md
3
3
  pyproject.toml
4
4
  src/weio_cli/__init__.py
5
5
  src/weio_cli/__main__.py
6
+ src/weio_cli/browser_login.py
6
7
  src/weio_cli/cli.py
7
8
  src/weio_cli/client.py
8
9
  src/weio_cli/coder.py
9
10
  src/weio_cli/config.py
10
11
  src/weio_cli/tui.py
12
+ src/weio_cli/updater.py
11
13
  src/weio_cli.egg-info/PKG-INFO
12
14
  src/weio_cli.egg-info/SOURCES.txt
13
15
  src/weio_cli.egg-info/dependency_links.txt
File without changes
File without changes
File without changes
File without changes