@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 CHANGED
@@ -1,77 +1,75 @@
1
- # @pi-unipi/updater
1
+ # Updater
2
2
 
3
- Checks npm for new versions on session start, shows a changelog diff, and lets you update with one keypress. Also provides TUI browsers for package READMEs and the changelog.
3
+ Updater tells you when a new UniPi release is on npm and installs it with one key.
4
4
 
5
- The update overlay appears automatically when a newer version is found. Press `Y` to update, `n` to skip. Skipped versions are cached — you only get re-prompted when an even newer version appears.
5
+ `@pi-unipi/updater` · part of [UniPi](../../README.md)
6
6
 
7
- ## Commands
7
+ ## What it does
8
8
 
9
- | Command | Description |
10
- |---------|-------------|
11
- | `/unipi:readme [package]` | Browse package README files in TUI overlay |
12
- | `/unipi:changelog` | Browse CHANGELOG.md with version list and detail view |
13
- | `/unipi:settings` | Configure check interval and auto-update mode (Updater group) |
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
- ### TUI Controls
16
+ ## Quick start
16
17
 
17
- | Key | Action |
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
- ## Special Triggers
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
- On session start, updater checks the npm registry for `@pi-unipi/unipi`. If a newer version exists and wasn't previously skipped, it shows the update overlay with changelog diff. This runs once per session, respecting the check interval config.
25
+ ## Commands
29
26
 
30
- Updater registers with the info-screen dashboard, showing installed version, latest version, update status, and last check time.
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
- ## How Updates Work
32
+ ## Keys
33
33
 
34
- 1. Session start triggers npm registry check
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
- ## Configurables
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
- Config stored at `~/.unipi/config/updater/config.json`:
43
+ README and changelog browsers:
44
44
 
45
- ```json
46
- {
47
- "checkIntervalMs": 3600000,
48
- "autoUpdate": "notify"
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
- | Option | Values | Default |
53
- |--------|--------|---------|
54
- | `checkIntervalMs` | 1800000 (30min), 3600000 (1h), 21600000 (6h), 86400000 (1d) | 3600000 (1h) |
55
- | `autoUpdate` | disabled, notify, auto | notify |
52
+ ## Settings
56
53
 
57
- ### Auto-update Modes
54
+ Open `/unipi:settings` → Updater. The namespace is `updater`.
58
55
 
59
- - **disabled** — No update checks on session start
60
- - **notify** — Show overlay with changelog, user chooses Y/n
61
- - **auto** — Show countdown, auto-install after 5 seconds unless cancelled
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
- ### Cache
61
+ ## How it works
64
62
 
65
- Last-check cache at `~/.unipi/cache/updater/last-check.json`:
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
- ```json
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
- ## License
71
+ ## See also
76
72
 
77
- MIT
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",
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.3"
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
- emitEvent(pi, UNIPI_EVENTS.MODULE_READY, {
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: "⏳ Checking",
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 ? "↑ Update available" : "✓ Up to date",
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
- pi.events.on(UNIPI_EVENTS.UPDATE_CHECK, (data) => {
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
- pi.events.on(UNIPI_EVENTS.UPDATE_AVAILABLE, (_data: unknown) => {
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
- pi.events.on(UNIPI_EVENTS.UPDATE_APPLIED, (_data: unknown) => {
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
- emitEvent(pi, UNIPI_EVENTS.UPDATE_CHECK, result);
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
- emitEvent(pi, UNIPI_EVENTS.UPDATE_AVAILABLE, {
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
- options: ["disabled", "notify", "auto"],
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
  },