feat(cli): check for newer version
This commit is contained in:
parent
a6676355d8
commit
9cb6ec1233
|
|
@ -59,6 +59,7 @@ The CLI resolves config in this order: **flag → env var → config file → de
|
|||
| Peer | — | `HONCHO_PEER_ID` | `-p` / `--peer` | No |
|
||||
| Session | — | `HONCHO_SESSION_ID` | `-s` / `--session` | No |
|
||||
| JSON output | — | `HONCHO_JSON` | `--json` | No |
|
||||
| Update nag | — | `HONCHO_NO_UPDATE_CHECK` | — | No |
|
||||
|
||||
### Persisted config
|
||||
|
||||
|
|
@ -110,6 +111,8 @@ Every command adapts its output to the context:
|
|||
- **Piped or redirected** — JSON automatically (detected via `isatty`).
|
||||
- **`--json` flag / `HONCHO_JSON=1`** — force JSON regardless of terminal.
|
||||
|
||||
Interactive sessions may print a one-line upgrade hint on stderr at most once a day when a newer `honcho-cli` is on PyPI (`uv tool upgrade honcho-cli`). JSON/piped output skips it; set `HONCHO_NO_UPDATE_CHECK=1` to disable it.
|
||||
|
||||
Collection commands emit JSON arrays; single-resource commands emit JSON objects. Errors are always structured:
|
||||
|
||||
```json
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
## [0.1.4] - 2026-08-26
|
||||
|
||||
### Changed
|
||||
### Added
|
||||
|
||||
- `--setup` API key prompts echo `*` per character so a paste is visibly received instead of a blank getpass field
|
||||
- A TTY notice when a newer `honcho-cli` is on PyPI (`uv tool upgrade honcho-cli`). Skipped in JSON mode; disable with `HONCHO_NO_UPDATE_CHECK`
|
||||
|
||||
### Fixed
|
||||
|
||||
- `--setup` for openai-compatible writes `EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL` into the profile `.env` alongside `LLM_OPENAI_BASE_URL` (#1068)
|
||||
- `--setup` API key prompts echo `*` per character so a paste is visibly received instead of a blank getpass field
|
||||
|
||||
## [0.1.3] - 2026-08-25
|
||||
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ Precedence (highest first): **flag → env var → config file → default**.
|
|||
| `HONCHO_PEER_ID` | `-p` / `--peer` | Peer scope |
|
||||
| `HONCHO_SESSION_ID` | `-s` / `--session` | Session scope |
|
||||
| `HONCHO_JSON` | `--json` | Force JSON output (`1` / `true`) |
|
||||
| `HONCHO_NO_UPDATE_CHECK` | — | Disable the once-a-day upgrade notice (`1` / `true`) |
|
||||
| `HONCHO_PROFILE` | `--profile` (start/stop/status) | Local stack profile (default: `local`) |
|
||||
| `LLM_OPENAI_API_KEY` | — | Provider key for `honcho start` (also `LLM_ANTHROPIC_API_KEY`, `LLM_GEMINI_API_KEY`) |
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from typer.core import TyperGroup
|
|||
from honcho_cli import __version__
|
||||
from honcho_cli.branding import BANNER, BRAND
|
||||
from honcho_cli.output import use_json
|
||||
from honcho_cli.update_check import maybe_print_update_nag
|
||||
|
||||
|
||||
# Theme Typer's rich help renderer. Module-level side effect limited to
|
||||
|
|
@ -113,6 +114,7 @@ def print_welcome(console: Console) -> None:
|
|||
console.print(_welcome_panel("memory", memory_rows))
|
||||
console.print(_welcome_panel("options", option_rows))
|
||||
console.print()
|
||||
maybe_print_update_nag()
|
||||
|
||||
|
||||
class HonchoTyperGroup(TyperGroup):
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from honcho_cli import __version__
|
|||
from honcho_cli._help import HonchoTyperGroup, print_welcome
|
||||
from honcho_cli.branding import BANNER
|
||||
from honcho_cli.output import set_json_mode
|
||||
from honcho_cli.update_check import maybe_print_update_nag
|
||||
|
||||
|
||||
app = typer.Typer(
|
||||
|
|
@ -60,6 +61,7 @@ def main(
|
|||
if ctx.invoked_subcommand is None:
|
||||
print_welcome(Console())
|
||||
raise typer.Exit()
|
||||
maybe_print_update_nag()
|
||||
|
||||
|
||||
# Register top-level commands
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
"""Once-a-day stderr notice when a newer honcho-cli is on PyPI.
|
||||
|
||||
Fail-open: any error is swallowed. Cache is ``update-check.json`` beside
|
||||
config, not ``config.json``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import httpx
|
||||
|
||||
from honcho_cli import __version__
|
||||
from honcho_cli.branding import ICON_RUN
|
||||
from honcho_cli.config import _config_dir
|
||||
from honcho_cli.output import console, use_json
|
||||
|
||||
_INTERVAL_S = 24 * 60 * 60
|
||||
_PYPI_URL = "https://pypi.org/pypi/honcho-cli/json"
|
||||
|
||||
|
||||
def maybe_print_update_nag() -> None:
|
||||
if use_json() or "--json" in sys.argv:
|
||||
return
|
||||
if os.environ.get("HONCHO_NO_UPDATE_CHECK", "").lower() in ("1", "true"):
|
||||
return
|
||||
try:
|
||||
path = _config_dir() / "update-check.json"
|
||||
now = time.time()
|
||||
try:
|
||||
cache = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError, UnicodeDecodeError):
|
||||
cache = {}
|
||||
if isinstance(cache, dict) and now - float(cache.get("t") or 0) < _INTERVAL_S:
|
||||
return
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps({"t": now}), encoding="utf-8")
|
||||
latest = httpx.get(_PYPI_URL, timeout=1.0).json()["info"]["version"]
|
||||
if not isinstance(latest, str) or not _is_newer(latest, __version__):
|
||||
return
|
||||
console.print(f" {ICON_RUN} honcho-cli {latest} is available (you have {__version__})")
|
||||
console.print(" [dim]uv tool upgrade honcho-cli[/dim]")
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
def _is_newer(latest: str, current: str) -> bool:
|
||||
def parts(version: str) -> tuple[int, ...]:
|
||||
out: list[int] = []
|
||||
for segment in version.lstrip("v").split("."):
|
||||
num = ""
|
||||
for ch in segment:
|
||||
if ch.isdigit():
|
||||
num += ch
|
||||
else:
|
||||
break
|
||||
if not num:
|
||||
break
|
||||
out.append(int(num))
|
||||
return tuple(out) or (0,)
|
||||
|
||||
a, b = parts(latest), parts(current)
|
||||
n = max(len(a), len(b))
|
||||
return a + (0,) * (n - len(a)) > b + (0,) * (n - len(b))
|
||||
Loading…
Reference in New Issue