Skip to content

Commit a436d4e

Browse files
metiu1claude
andcommitted
v0.3.59: detect updates from main, GUI upgrade button + open notification
- Update check now compares the installed version against main's version.go (installs come from main, which is ahead of GitHub releases), so "update available" is detected correctly instead of never. - GUI shows a sidebar "Aggiorna Vortelio" button and a one-time toast on open when a newer version is available (plus the existing topbar/settings entries). - Advanced sidebar group: raise max-height so items aren't clipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 9b563cd commit a436d4e

7 files changed

Lines changed: 37 additions & 24 deletions

File tree

vortelio-pip/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "vortelio"
7-
version = "0.3.58"
7+
version = "0.3.59"
88
description = "Local-first AI platform. Run LLMs, generate images & video, transcribe audio, create 3D — on your own machine. OpenAI & Ollama API compatible. Apache 2.0."
99
readme = "README.md"
1010
requires-python = ">=3.8"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.3.58"
1+
__version__ = "0.3.59"

vortelio-pip/src/vortelio_cli/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import urllib.request
1111
from pathlib import Path
1212

13-
VERSION = "0.3.58"
13+
VERSION = "0.3.59"
1414
RELEASE_BASE = os.environ.get(
1515
"VORTELIO_RELEASE_BASE",
1616
f"https://github.com/metiu1/Vortelio/releases/download/v{VERSION}",
512 Bytes
Binary file not shown.

vortelio/internal/server/ui.html

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
.sec-chevron { width: 9px; height: 9px; transition: transform .18s cubic-bezier(.4,0,.2,1); opacity: .7; }
9292
.sidebar-section.collapsible[aria-expanded="true"] .sec-chevron { transform: rotate(-180deg); }
9393
.nav-group { overflow: hidden; max-height: 0; transition: max-height .22s cubic-bezier(.4,0,.2,1); }
94-
.nav-group.open { max-height: 320px; }
94+
.nav-group.open { max-height: 600px; }
9595

9696
.history-list { flex: 1; overflow-y: auto; }
9797
.hist-item {
@@ -1126,6 +1126,10 @@
11261126
</div>
11271127

11281128
<div style="margin-top:auto">
1129+
<!-- Shown when a newer version is available on main -->
1130+
<button class="nav-item" id="sidebar-update-btn" onclick="startVortelioUpdate()" style="display:none;color:var(--accent);font-weight:600">
1131+
<span>⬆️</span> <span id="sidebar-update-lbl">Aggiorna Vortelio</span>
1132+
</button>
11291133
<!-- Account info (when logged in) -->
11301134
<div class="auth-user-bar" id="auth-user-bar" style="display:none">
11311135
<div class="auth-avatar" id="auth-avatar">?</div>
@@ -3342,6 +3346,7 @@ <h3 style="margin:0">☁️ Add cloud model</h3>
33423346

33433347
let _onboardChecked = false;
33443348
let vortelioUpdateInfo = null;
3349+
let _updateNotified = false;
33453350

33463351
function renderVortelioUpdate(info) {
33473352
vortelioUpdateInfo = info || null;
@@ -3352,6 +3357,15 @@ <h3 style="margin:0">☁️ Add cloud model</h3>
33523357
const setLink = document.getElementById('settings-update-link');
33533358
const setTitle = document.getElementById('settings-update-title');
33543359
const setSub = document.getElementById('settings-update-sub');
3360+
const sideBtn = document.getElementById('sidebar-update-btn');
3361+
const sideLbl = document.getElementById('sidebar-update-lbl');
3362+
if (sideBtn) sideBtn.style.display = available ? 'flex' : 'none';
3363+
if (sideLbl && latest) sideLbl.textContent = 'Aggiorna a ' + latest;
3364+
// One-time notification on open when a new version is available.
3365+
if (available && !_updateNotified) {
3366+
_updateNotified = true;
3367+
try { toast('🎉 Nuova versione ' + (latest || '') + ' disponibile — clicca "Aggiorna"', 'ok'); } catch {}
3368+
}
33553369
if (topBtn) topBtn.style.display = available ? 'flex' : 'none';
33563370
if (topLbl && latest) topLbl.textContent = 'Update ' + latest;
33573371
// The settings entry is ALWAYS available so the user can reinstall the latest

vortelio/internal/updater/updater.go

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package updater
22

33
import (
44
"context"
5-
"encoding/json"
65
"errors"
76
"fmt"
7+
"io"
88
"net/http"
99
"regexp"
1010
"strconv"
@@ -17,8 +17,14 @@ import (
1717
const (
1818
RepoInstallSpec = "git+https://github.com/metiu1/Vortelio#subdirectory=vortelio-pip"
1919
LatestAPIURL = "https://api.github.com/repos/metiu1/Vortelio/releases/latest"
20+
// MainVersionURL is the canonical version on the default branch. Installs come
21+
// from main (git), which is usually ahead of the latest GitHub release, so we
22+
// compare against this to detect available updates.
23+
MainVersionURL = "https://raw.githubusercontent.com/metiu1/Vortelio/main/vortelio/internal/version/version.go"
2024
)
2125

26+
var mainVersionRE = regexp.MustCompile(`Version\s*=\s*"([0-9]+(?:\.[0-9]+){1,3})"`)
27+
2228
type Info struct {
2329
Current string `json:"current"`
2430
Latest string `json:"latest"`
@@ -36,16 +42,16 @@ type StartResult struct {
3642
func Check(ctx context.Context) (Info, error) {
3743
info := Info{
3844
Current: version.Version,
39-
InstallCommand: "uv tool install --force \"" + RepoInstallSpec + "\"",
40-
Source: LatestAPIURL,
45+
InstallCommand: "uv tool install --reinstall --refresh \"" + RepoInstallSpec + "\"",
46+
Source: MainVersionURL,
4147
}
4248

43-
req, err := http.NewRequestWithContext(ctx, http.MethodGet, LatestAPIURL, nil)
49+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, MainVersionURL, nil)
4450
if err != nil {
4551
return info, err
4652
}
47-
req.Header.Set("Accept", "application/vnd.github+json")
4853
req.Header.Set("User-Agent", "vortelio-updater/"+version.Version)
54+
req.Header.Set("Cache-Control", "no-cache")
4955

5056
resp, err := http.DefaultClient.Do(req)
5157
if err != nil {
@@ -56,23 +62,16 @@ func Check(ctx context.Context) (Info, error) {
5662
return info, fmt.Errorf("GitHub returned HTTP %d", resp.StatusCode)
5763
}
5864

59-
var payload struct {
60-
TagName string `json:"tag_name"`
61-
Name string `json:"name"`
62-
}
63-
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
65+
body, err := io.ReadAll(io.LimitReader(resp.Body, 4096))
66+
if err != nil {
6467
return info, err
6568
}
66-
latest := cleanVersion(payload.TagName)
67-
if latest == "" {
68-
latest = cleanVersion(payload.Name)
69+
m := mainVersionRE.FindStringSubmatch(string(body))
70+
if len(m) < 2 {
71+
return info, errors.New("could not read version from main")
6972
}
70-
if latest == "" {
71-
return info, errors.New("latest release does not contain a version")
72-
}
73-
74-
info.Latest = latest
75-
info.Available = compareVersions(latest, version.Version) > 0
73+
info.Latest = m[1]
74+
info.Available = compareVersions(info.Latest, version.Version) > 0
7675
return info, nil
7776
}
7877

vortelio/internal/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package version
33
// Version è impostabile a build time via:
44
//
55
// -ldflags "-X github.com/vortelio/vortelio/internal/version.Version=X.Y.Z"
6-
var Version = "0.3.58"
6+
var Version = "0.3.59"

0 commit comments

Comments
 (0)