@pi-unipi/updater 3.0.0-alpha.3 → 3.0.0-alpha.31
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.
- package/README.md +53 -55
- package/package.json +2 -2
- package/src/index.ts +29 -30
- package/src/settings.ts +8 -2
package/README.md
CHANGED
|
@@ -1,77 +1,75 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Updater
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Updater tells you when a new UniPi release is on npm and installs it with one key.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@pi-unipi/updater` · part of [UniPi](../../README.md)
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What it does
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
- Checks the npm registry for `@pi-unipi/unipi` at session start.
|
|
10
|
+
- Shows an update overlay with the changelog entries between your version and the new version.
|
|
11
|
+
- Runs `pi install npm:@pi-unipi/unipi` when you press `Y`.
|
|
12
|
+
- Remembers a version that you skip. It asks again only for a newer version.
|
|
13
|
+
- Opens package READMEs and the changelog in TUI overlays.
|
|
14
|
+
- Adds an Updater group to the info screen: installed version, latest version, status and last check.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
## Quick start
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|-----|--------|
|
|
19
|
-
| `j/k` or Up/Down | Navigate |
|
|
20
|
-
| `Enter` | Select/open |
|
|
21
|
-
| `q/Esc` | Back/close |
|
|
22
|
-
| `g/G` | Jump to top/bottom |
|
|
23
|
-
| `Space` | Cycle options (settings) |
|
|
24
|
-
| `h/l` or Left/Right | Cycle options (settings) |
|
|
18
|
+
Updater ships in `@pi-unipi/unipi`. It checks the version of `@pi-unipi/unipi`, so it is useful only with the full suite.
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
1. Start a pi session. Updater checks npm in the background.
|
|
21
|
+
2. If a newer version is on npm, the update overlay opens.
|
|
22
|
+
3. Press `Y` to install. Press `n` to skip this version.
|
|
23
|
+
4. Restart pi to load the new version.
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
## Commands
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
| Command | What it does |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `/unipi:readme [package]` | Opens the README browser. A package name, for example `utility`, opens that README. |
|
|
30
|
+
| `/unipi:changelog` | Opens the changelog browser with a version list and a detail view. |
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Keys
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
2. Compare latest version with installed version
|
|
36
|
-
3. If newer and not skipped, show update overlay
|
|
37
|
-
4. User views changelog diff, presses `Y` to update or `n` to skip
|
|
38
|
-
5. Update runs `pi install npm:@pi-unipi/unipi`
|
|
39
|
-
6. Skipped version cached — re-prompted only for newer versions
|
|
34
|
+
Update overlay:
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
| Key | What it does |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `Y` or `y` | Installs the new version. |
|
|
39
|
+
| `n`, `q` or `Esc` | Skips this version. |
|
|
40
|
+
| `j` / `k` or arrows | Scrolls the changelog. |
|
|
41
|
+
| `g` / `G` | Goes to the top or the bottom. |
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
README and changelog browsers:
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
| Key | What it does |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `j` / `k` or arrows | Moves in the list, or scrolls the detail view. |
|
|
48
|
+
| `Enter` | Opens the selected item. |
|
|
49
|
+
| `g` / `G` | Goes to the top or the bottom. |
|
|
50
|
+
| `q` or `Esc` | Goes back to the list, or closes the list. |
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|--------|--------|---------|
|
|
54
|
-
| `checkIntervalMs` | 1800000 (30min), 3600000 (1h), 21600000 (6h), 86400000 (1d) | 3600000 (1h) |
|
|
55
|
-
| `autoUpdate` | disabled, notify, auto | notify |
|
|
52
|
+
## Settings
|
|
56
53
|
|
|
57
|
-
|
|
54
|
+
Open `/unipi:settings` → Updater. The namespace is `updater`.
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
| Key | Default | What it does |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `checkIntervalMs` | `3600000` (1 hour) | Minimum time between two npm checks. Options: 30 min, 1 hour, 6 hours, 1 day. |
|
|
59
|
+
| `autoUpdate` | `notify` | `disabled`: no check. `notify`: the overlay asks you. `auto`: the overlay counts down 5 seconds, then installs. Press `n` to cancel and skip this version. |
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
## How it works
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
1. At session start, Updater reads `~/.unipi/cache/updater/last-check.json`.
|
|
64
|
+
2. If the last check is older than `checkIntervalMs`, Updater gets the `latest` dist-tag from npm. The request stops after 10 seconds.
|
|
65
|
+
3. Updater compares the versions. It never offers a lower version.
|
|
66
|
+
4. If the new version is not skipped, the overlay opens. Updater gets the changelog for the new version from GitHub. If that fails, it uses the local `CHANGELOG.md`.
|
|
67
|
+
5. The install command stops after 60 seconds. If it fails, the overlay shows the error. Press any key to close it.
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
"lastCheck": "2026-05-01T12:00:00.000Z",
|
|
70
|
-
"latestVersion": "0.1.16",
|
|
71
|
-
"skippedVersion": "0.1.16"
|
|
72
|
-
}
|
|
73
|
-
```
|
|
69
|
+
A failed npm check is silent. Updater then uses the cached result.
|
|
74
70
|
|
|
75
|
-
##
|
|
71
|
+
## See also
|
|
76
72
|
|
|
77
|
-
|
|
73
|
+
- [Commands reference](../../docs/reference/commands.md)
|
|
74
|
+
- [Settings reference](../../docs/reference/settings.md)
|
|
75
|
+
- [Info Screen](../info-screen/README.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.31",
|
|
4
4
|
"description": "Auto-updater, changelog browser, and readme browser for Unipi — checks npm registry, renders CHANGELOG.md and README.md files in TUI overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.31"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
package/src/index.ts
CHANGED
|
@@ -10,13 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import {
|
|
13
|
+
bus,
|
|
13
14
|
UNIPI_EVENTS,
|
|
14
15
|
MODULES,
|
|
15
16
|
UPDATER_COMMANDS,
|
|
16
17
|
UNIPI_PREFIX,
|
|
17
|
-
emitEvent,
|
|
18
18
|
getPackageVersion,
|
|
19
|
-
type UnipiUpdateCheckEvent,
|
|
20
19
|
} from "@pi-unipi/core";
|
|
21
20
|
import { registerCommands } from "./commands.js";
|
|
22
21
|
import { loadConfig } from "./settings.js";
|
|
@@ -36,7 +35,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
36
35
|
// Session lifecycle — check for updates and announce module
|
|
37
36
|
pi.on("session_start", async (_event, ctx) => {
|
|
38
37
|
// Emit MODULE_READY
|
|
39
|
-
|
|
38
|
+
bus.emit(UNIPI_EVENTS.MODULE_READY, {
|
|
40
39
|
name: MODULES.UPDATER,
|
|
41
40
|
version: VERSION,
|
|
42
41
|
commands: [
|
|
@@ -49,7 +48,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
49
48
|
// Register info-screen group
|
|
50
49
|
const infoRegistry = globalThis.__unipi_info_registry;
|
|
51
50
|
if (infoRegistry) {
|
|
52
|
-
let cachedResult: { currentVersion: string; latestVersion: string; updateAvailable: boolean; lastCheck: string } | null = null;
|
|
51
|
+
let cachedResult: { currentVersion: string; latestVersion: string; updateAvailable: boolean; lastCheck: string; checkedAt: number } | null = null;
|
|
53
52
|
|
|
54
53
|
infoRegistry.registerGroup({
|
|
55
54
|
id: "updater",
|
|
@@ -66,56 +65,56 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
66
65
|
],
|
|
67
66
|
},
|
|
68
67
|
dataProvider: async () => {
|
|
68
|
+
const cfg = loadConfig();
|
|
69
69
|
if (!cachedResult) {
|
|
70
70
|
return {
|
|
71
|
-
current: VERSION,
|
|
72
|
-
latest: "checking
|
|
73
|
-
status: "
|
|
74
|
-
lastCheck: "never",
|
|
71
|
+
current: { value: VERSION },
|
|
72
|
+
latest: { value: "checking…" },
|
|
73
|
+
status: { value: "checking" },
|
|
74
|
+
lastCheck: { value: "never" },
|
|
75
|
+
raw: { value: "", raw: { current: VERSION, latest: null, available: false, checkedAt: 0, mode: cfg.autoUpdate } },
|
|
75
76
|
};
|
|
76
77
|
}
|
|
77
78
|
return {
|
|
78
|
-
current: cachedResult.currentVersion,
|
|
79
|
-
latest: cachedResult.latestVersion,
|
|
80
|
-
status: cachedResult.updateAvailable ? "
|
|
81
|
-
lastCheck: cachedResult.lastCheck || "never",
|
|
79
|
+
current: { value: cachedResult.currentVersion },
|
|
80
|
+
latest: { value: cachedResult.latestVersion },
|
|
81
|
+
status: { value: cachedResult.updateAvailable ? "update available" : "up to date" },
|
|
82
|
+
lastCheck: { value: cachedResult.lastCheck || "never" },
|
|
83
|
+
raw: {
|
|
84
|
+
value: "",
|
|
85
|
+
raw: {
|
|
86
|
+
current: cachedResult.currentVersion,
|
|
87
|
+
latest: cachedResult.latestVersion,
|
|
88
|
+
available: cachedResult.updateAvailable,
|
|
89
|
+
checkedAt: cachedResult.checkedAt,
|
|
90
|
+
mode: cfg.autoUpdate,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
82
93
|
};
|
|
83
94
|
},
|
|
84
95
|
});
|
|
85
96
|
|
|
86
97
|
// Subscribe to events to update cached data
|
|
87
|
-
|
|
88
|
-
const payload = data as UnipiUpdateCheckEvent;
|
|
98
|
+
bus.on(pi, UNIPI_EVENTS.UPDATE_CHECK, (payload) => {
|
|
89
99
|
cachedResult = {
|
|
90
100
|
currentVersion: payload.currentVersion,
|
|
91
101
|
latestVersion: payload.latestVersion,
|
|
92
102
|
updateAvailable: payload.updateAvailable,
|
|
93
103
|
lastCheck: new Date().toLocaleTimeString(),
|
|
104
|
+
checkedAt: Date.now(),
|
|
94
105
|
};
|
|
95
|
-
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
96
|
-
groupId: "updater",
|
|
97
|
-
keys: ["current", "latest", "status", "lastCheck"],
|
|
98
|
-
});
|
|
99
106
|
});
|
|
100
107
|
|
|
101
|
-
|
|
108
|
+
bus.on(pi, UNIPI_EVENTS.UPDATE_AVAILABLE, () => {
|
|
102
109
|
if (cachedResult) {
|
|
103
110
|
cachedResult.updateAvailable = true;
|
|
104
111
|
}
|
|
105
|
-
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
106
|
-
groupId: "updater",
|
|
107
|
-
keys: ["status"],
|
|
108
|
-
});
|
|
109
112
|
});
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
bus.on(pi, UNIPI_EVENTS.UPDATE_APPLIED, () => {
|
|
112
115
|
if (cachedResult) {
|
|
113
116
|
cachedResult.updateAvailable = false;
|
|
114
117
|
}
|
|
115
|
-
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
116
|
-
groupId: "updater",
|
|
117
|
-
keys: ["status"],
|
|
118
|
-
});
|
|
119
118
|
});
|
|
120
119
|
}
|
|
121
120
|
|
|
@@ -127,7 +126,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
127
126
|
const result = await checkForUpdates();
|
|
128
127
|
|
|
129
128
|
// Emit check event
|
|
130
|
-
|
|
129
|
+
bus.emit(UNIPI_EVENTS.UPDATE_CHECK, result);
|
|
131
130
|
|
|
132
131
|
if (!result.updateAvailable || result.error) return;
|
|
133
132
|
|
|
@@ -135,7 +134,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
135
134
|
if (isVersionSkipped(result.latestVersion)) return;
|
|
136
135
|
|
|
137
136
|
// Emit available event
|
|
138
|
-
|
|
137
|
+
bus.emit(UNIPI_EVENTS.UPDATE_AVAILABLE, {
|
|
139
138
|
currentVersion: result.currentVersion,
|
|
140
139
|
latestVersion: result.latestVersion,
|
|
141
140
|
});
|
package/src/settings.ts
CHANGED
|
@@ -46,19 +46,25 @@ registerSettings({
|
|
|
46
46
|
key: "checkIntervalMs",
|
|
47
47
|
type: "enum",
|
|
48
48
|
label: "Check interval",
|
|
49
|
+
plainOptions: true,
|
|
50
|
+
description: "How often to check npm for updates.",
|
|
49
51
|
options: [
|
|
50
52
|
{ value: "1800000", label: "30 min" },
|
|
51
53
|
{ value: "3600000", label: "1 hour" },
|
|
52
54
|
{ value: "21600000", label: "6 hours" },
|
|
53
55
|
{ value: "86400000", label: "daily" },
|
|
54
56
|
],
|
|
55
|
-
description: "How often to check npm for updates",
|
|
56
57
|
},
|
|
57
58
|
{
|
|
58
59
|
key: "autoUpdate",
|
|
59
60
|
type: "enum",
|
|
60
61
|
label: "Auto update",
|
|
61
|
-
|
|
62
|
+
description: "What happens when an update is found.",
|
|
63
|
+
options: [
|
|
64
|
+
{ value: "disabled", label: "disabled", description: "check nothing; update manually" },
|
|
65
|
+
{ value: "notify", label: "notify", description: "tell you; you install" },
|
|
66
|
+
{ value: "auto", label: "auto", description: "install the update itself" },
|
|
67
|
+
],
|
|
62
68
|
},
|
|
63
69
|
],
|
|
64
70
|
},
|