@pi-unipi/updater 0.1.1 → 2.0.0
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 +41 -35
- package/package.json +1 -1
- package/src/checker.ts +6 -6
- package/src/commands.ts +6 -6
- package/src/index.ts +12 -10
- package/src/installer.ts +9 -9
- package/src/readme.ts +7 -8
- package/src/tui/changelog-overlay.ts +6 -5
- package/src/tui/readme-overlay.ts +4 -4
- package/src/tui/settings-overlay.ts +3 -3
- package/src/tui/update-overlay.ts +3 -3
package/README.md
CHANGED
|
@@ -1,22 +1,44 @@
|
|
|
1
1
|
# @pi-unipi/updater
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **Auto-updater** — Periodically checks npm registry for new versions, shows update prompt with changelog diff
|
|
8
|
-
- **Changelog browser** — TUI overlay listing all versions with dates and status labels (✓ Current, ↑ New)
|
|
9
|
-
- **Readme browser** — TUI overlay listing all packages with versions, opens rendered README content
|
|
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.
|
|
10
6
|
|
|
11
7
|
## Commands
|
|
12
8
|
|
|
13
9
|
| Command | Description |
|
|
14
10
|
|---------|-------------|
|
|
15
|
-
| `/unipi:readme [package]` | Browse package README files
|
|
11
|
+
| `/unipi:readme [package]` | Browse package README files in TUI overlay |
|
|
16
12
|
| `/unipi:changelog` | Browse CHANGELOG.md with version list and detail view |
|
|
17
13
|
| `/unipi:updater-settings` | Configure check interval and auto-update mode |
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
### TUI Controls
|
|
16
|
+
|
|
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) |
|
|
25
|
+
|
|
26
|
+
## Special Triggers
|
|
27
|
+
|
|
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.
|
|
29
|
+
|
|
30
|
+
Updater registers with the info-screen dashboard, showing installed version, latest version, update status, and last check time.
|
|
31
|
+
|
|
32
|
+
## How Updates Work
|
|
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
|
|
40
|
+
|
|
41
|
+
## Configurables
|
|
20
42
|
|
|
21
43
|
Config stored at `~/.unipi/config/updater/config.json`:
|
|
22
44
|
|
|
@@ -27,41 +49,21 @@ Config stored at `~/.unipi/config/updater/config.json`:
|
|
|
27
49
|
}
|
|
28
50
|
```
|
|
29
51
|
|
|
30
|
-
### Options
|
|
31
|
-
|
|
32
52
|
| Option | Values | Default |
|
|
33
53
|
|--------|--------|---------|
|
|
34
|
-
| `checkIntervalMs` |
|
|
35
|
-
| `autoUpdate` |
|
|
54
|
+
| `checkIntervalMs` | 1800000 (30min), 3600000 (1h), 21600000 (6h), 86400000 (1d) | 3600000 (1h) |
|
|
55
|
+
| `autoUpdate` | disabled, notify, auto | notify |
|
|
36
56
|
|
|
37
|
-
### Auto-update
|
|
57
|
+
### Auto-update Modes
|
|
38
58
|
|
|
39
59
|
- **disabled** — No update checks on session start
|
|
40
|
-
- **notify** — Show
|
|
41
|
-
- **auto** — Show countdown
|
|
42
|
-
|
|
43
|
-
## How it works
|
|
44
|
-
|
|
45
|
-
1. On session start, checks npm registry for `@pi-unipi/unipi` latest version
|
|
46
|
-
2. Compares with installed version from `package.json`
|
|
47
|
-
3. If newer version found and not previously skipped, shows update overlay
|
|
48
|
-
4. User can view changelog diff, update with `[Y]`, or skip with `[n]`
|
|
49
|
-
5. Skipped versions are cached — only re-prompted when an even newer version appears
|
|
50
|
-
6. Update installs via `pi install npm:@pi-unipi/unipi`
|
|
60
|
+
- **notify** — Show overlay with changelog, user chooses Y/n
|
|
61
|
+
- **auto** — Show countdown, auto-install after 5 seconds unless cancelled
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
### Cache
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
- `j`/`k` or ↑/↓ — navigate
|
|
56
|
-
- `Enter` — select/open
|
|
57
|
-
- `q`/`Esc` — back/close
|
|
58
|
-
- `g`/`G` — jump to top/bottom
|
|
59
|
-
- `Space` — cycle options (settings overlay)
|
|
60
|
-
- `h`/`l` or ←/→ — cycle options (settings overlay)
|
|
65
|
+
Last-check cache at `~/.unipi/cache/updater/last-check.json`:
|
|
61
66
|
|
|
62
|
-
## Cache
|
|
63
|
-
|
|
64
|
-
Last-check cache stored at `~/.unipi/cache/updater/last-check.json`:
|
|
65
67
|
```json
|
|
66
68
|
{
|
|
67
69
|
"lastCheck": "2026-05-01T12:00:00.000Z",
|
|
@@ -69,3 +71,7 @@ Last-check cache stored at `~/.unipi/cache/updater/last-check.json`:
|
|
|
69
71
|
"skippedVersion": "0.1.16"
|
|
70
72
|
}
|
|
71
73
|
```
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
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
|
"license": "MIT",
|
package/src/checker.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* respects check interval from config/cache.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { getInstalledPackageVersion } from "@pi-unipi/core";
|
|
9
9
|
import { loadConfig } from "./settings.js";
|
|
10
10
|
import { readLastCheck, writeLastCheck, isCheckDue } from "./cache.js";
|
|
11
11
|
import type { UpdateCheckResult } from "../types.js";
|
|
@@ -15,9 +15,9 @@ const NPM_REGISTRY_URL = "https://registry.npmjs.org/@pi-unipi/unipi";
|
|
|
15
15
|
|
|
16
16
|
/** Resolve the installed version of @pi-unipi/unipi */
|
|
17
17
|
function getInstalledVersion(): string {
|
|
18
|
-
// Walk up from this file to find the
|
|
19
|
-
const dir = new URL("
|
|
20
|
-
return
|
|
18
|
+
// Walk up from this file to find the @pi-unipi/unipi package by name
|
|
19
|
+
const dir = new URL("..", import.meta.url).pathname;
|
|
20
|
+
return getInstalledPackageVersion(dir, "@pi-unipi/unipi");
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -71,14 +71,14 @@ export async function checkForUpdates(): Promise<UpdateCheckResult> {
|
|
|
71
71
|
latestVersion,
|
|
72
72
|
currentVersion,
|
|
73
73
|
};
|
|
74
|
-
} catch (err:
|
|
74
|
+
} catch (err: unknown) {
|
|
75
75
|
// Network error — return cached info if available
|
|
76
76
|
const cache = readLastCheck();
|
|
77
77
|
return {
|
|
78
78
|
updateAvailable: false,
|
|
79
79
|
latestVersion: cache?.latestVersion ?? "",
|
|
80
80
|
currentVersion,
|
|
81
|
-
error: err.message
|
|
81
|
+
error: err instanceof Error ? err.message : String(err) || "Unknown error",
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
}
|
package/src/commands.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Registers /unipi:readme [package], /unipi:changelog, /unipi:updater-settings
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
7
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
|
8
8
|
import { UNIPI_PREFIX, UPDATER_COMMANDS } from "@pi-unipi/core";
|
|
9
9
|
import { renderReadmeOverlay } from "./tui/readme-overlay.js";
|
|
10
10
|
import { renderChangelogOverlay } from "./tui/changelog-overlay.js";
|
|
@@ -14,9 +14,9 @@ import { renderSettingsOverlay } from "./tui/settings-overlay.js";
|
|
|
14
14
|
const OVERLAY_OPTIONS = {
|
|
15
15
|
overlay: true,
|
|
16
16
|
overlayOptions: {
|
|
17
|
-
width: "80%",
|
|
17
|
+
width: "80%" as const,
|
|
18
18
|
minWidth: 60,
|
|
19
|
-
anchor: "center",
|
|
19
|
+
anchor: "center" as const,
|
|
20
20
|
margin: 2,
|
|
21
21
|
},
|
|
22
22
|
};
|
|
@@ -28,7 +28,7 @@ export function registerCommands(pi: ExtensionAPI): void {
|
|
|
28
28
|
`${UNIPI_PREFIX}${UPDATER_COMMANDS.README}`,
|
|
29
29
|
{
|
|
30
30
|
description: "Browse package README files",
|
|
31
|
-
handler: async (args: string, ctx:
|
|
31
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
32
32
|
const packageName = args.trim() || undefined;
|
|
33
33
|
try {
|
|
34
34
|
await ctx.ui.custom(
|
|
@@ -47,7 +47,7 @@ export function registerCommands(pi: ExtensionAPI): void {
|
|
|
47
47
|
`${UNIPI_PREFIX}${UPDATER_COMMANDS.CHANGELOG}`,
|
|
48
48
|
{
|
|
49
49
|
description: "Browse changelog (Keep a Changelog format)",
|
|
50
|
-
handler: async (_args: string, ctx:
|
|
50
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
51
51
|
try {
|
|
52
52
|
await ctx.ui.custom(
|
|
53
53
|
renderChangelogOverlay(),
|
|
@@ -65,7 +65,7 @@ export function registerCommands(pi: ExtensionAPI): void {
|
|
|
65
65
|
`${UNIPI_PREFIX}${UPDATER_COMMANDS.UPDATER_SETTINGS}`,
|
|
66
66
|
{
|
|
67
67
|
description: "Configure updater — check interval and auto-update mode",
|
|
68
|
-
handler: async (_args: string, ctx:
|
|
68
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
69
69
|
try {
|
|
70
70
|
const result = await ctx.ui.custom(
|
|
71
71
|
renderSettingsOverlay(),
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
UNIPI_PREFIX,
|
|
17
17
|
emitEvent,
|
|
18
18
|
getPackageVersion,
|
|
19
|
+
type UnipiUpdateCheckEvent,
|
|
19
20
|
} from "@pi-unipi/core";
|
|
20
21
|
import { registerCommands } from "./commands.js";
|
|
21
22
|
import { loadConfig } from "./settings.js";
|
|
@@ -41,7 +42,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
41
42
|
// Session lifecycle — check for updates and announce module
|
|
42
43
|
pi.on("session_start", async (_event, ctx) => {
|
|
43
44
|
// Emit MODULE_READY
|
|
44
|
-
emitEvent(pi
|
|
45
|
+
emitEvent(pi, UNIPI_EVENTS.MODULE_READY, {
|
|
45
46
|
name: MODULES.UPDATER,
|
|
46
47
|
version: VERSION,
|
|
47
48
|
commands: [
|
|
@@ -53,7 +54,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
53
54
|
});
|
|
54
55
|
|
|
55
56
|
// Register info-screen group
|
|
56
|
-
const infoRegistry =
|
|
57
|
+
const infoRegistry = globalThis.__unipi_info_registry;
|
|
57
58
|
if (infoRegistry) {
|
|
58
59
|
let cachedResult: { currentVersion: string; latestVersion: string; updateAvailable: boolean; lastCheck: string } | null = null;
|
|
59
60
|
|
|
@@ -90,34 +91,35 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
90
91
|
});
|
|
91
92
|
|
|
92
93
|
// Subscribe to events to update cached data
|
|
93
|
-
pi.events.on(UNIPI_EVENTS.UPDATE_CHECK, (
|
|
94
|
+
pi.events.on(UNIPI_EVENTS.UPDATE_CHECK, (data) => {
|
|
95
|
+
const payload = data as UnipiUpdateCheckEvent;
|
|
94
96
|
cachedResult = {
|
|
95
97
|
currentVersion: payload.currentVersion,
|
|
96
98
|
latestVersion: payload.latestVersion,
|
|
97
99
|
updateAvailable: payload.updateAvailable,
|
|
98
100
|
lastCheck: new Date().toLocaleTimeString(),
|
|
99
101
|
};
|
|
100
|
-
emitEvent(pi
|
|
102
|
+
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
101
103
|
groupId: "updater",
|
|
102
104
|
keys: ["current", "latest", "status", "lastCheck"],
|
|
103
105
|
});
|
|
104
106
|
});
|
|
105
107
|
|
|
106
|
-
pi.events.on(UNIPI_EVENTS.UPDATE_AVAILABLE, (
|
|
108
|
+
pi.events.on(UNIPI_EVENTS.UPDATE_AVAILABLE, (_data: unknown) => {
|
|
107
109
|
if (cachedResult) {
|
|
108
110
|
cachedResult.updateAvailable = true;
|
|
109
111
|
}
|
|
110
|
-
emitEvent(pi
|
|
112
|
+
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
111
113
|
groupId: "updater",
|
|
112
114
|
keys: ["status"],
|
|
113
115
|
});
|
|
114
116
|
});
|
|
115
117
|
|
|
116
|
-
pi.events.on(UNIPI_EVENTS.UPDATE_APPLIED, (
|
|
118
|
+
pi.events.on(UNIPI_EVENTS.UPDATE_APPLIED, (_data: unknown) => {
|
|
117
119
|
if (cachedResult) {
|
|
118
120
|
cachedResult.updateAvailable = false;
|
|
119
121
|
}
|
|
120
|
-
emitEvent(pi
|
|
122
|
+
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
121
123
|
groupId: "updater",
|
|
122
124
|
keys: ["status"],
|
|
123
125
|
});
|
|
@@ -132,7 +134,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
132
134
|
const result = await checkForUpdates();
|
|
133
135
|
|
|
134
136
|
// Emit check event
|
|
135
|
-
emitEvent(pi
|
|
137
|
+
emitEvent(pi, UNIPI_EVENTS.UPDATE_CHECK, result);
|
|
136
138
|
|
|
137
139
|
if (!result.updateAvailable || result.error) return;
|
|
138
140
|
|
|
@@ -140,7 +142,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
140
142
|
if (isVersionSkipped(result.latestVersion)) return;
|
|
141
143
|
|
|
142
144
|
// Emit available event
|
|
143
|
-
emitEvent(pi
|
|
145
|
+
emitEvent(pi, UNIPI_EVENTS.UPDATE_AVAILABLE, {
|
|
144
146
|
currentVersion: result.currentVersion,
|
|
145
147
|
latestVersion: result.latestVersion,
|
|
146
148
|
});
|
package/src/installer.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { exec } from "child_process";
|
|
9
9
|
import { promisify } from "util";
|
|
10
|
-
import {
|
|
10
|
+
import { getInstalledPackageVersion, emitEvent, UNIPI_EVENTS } from "@pi-unipi/core";
|
|
11
11
|
import type { InstallResult } from "../types.js";
|
|
12
12
|
|
|
13
13
|
const execAsync = promisify(exec);
|
|
@@ -23,9 +23,8 @@ const INSTALL_TIMEOUT_MS = 60000;
|
|
|
23
23
|
export async function installUpdate(
|
|
24
24
|
pi?: { events: { emit: (name: string, payload: unknown) => void } },
|
|
25
25
|
): Promise<InstallResult> {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
);
|
|
26
|
+
const thisDir = new URL("..", import.meta.url).pathname;
|
|
27
|
+
const installedBefore = getInstalledPackageVersion(thisDir, "@pi-unipi/unipi");
|
|
29
28
|
|
|
30
29
|
try {
|
|
31
30
|
const { stdout, stderr } = await execAsync(
|
|
@@ -37,9 +36,7 @@ export async function installUpdate(
|
|
|
37
36
|
);
|
|
38
37
|
|
|
39
38
|
// Get new version after install
|
|
40
|
-
const installedAfter =
|
|
41
|
-
new URL("../../..", import.meta.url).pathname,
|
|
42
|
-
);
|
|
39
|
+
const installedAfter = getInstalledPackageVersion(thisDir, "@pi-unipi/unipi");
|
|
43
40
|
|
|
44
41
|
const result: InstallResult = {
|
|
45
42
|
success: true,
|
|
@@ -55,8 +52,11 @@ export async function installUpdate(
|
|
|
55
52
|
}
|
|
56
53
|
|
|
57
54
|
return result;
|
|
58
|
-
} catch (err:
|
|
59
|
-
const errorMessage = err
|
|
55
|
+
} catch (err: unknown) {
|
|
56
|
+
const errorMessage = (err instanceof Error && 'stderr' in err ? String((err as Error & { stderr?: string }).stderr) : undefined)
|
|
57
|
+
|| (err instanceof Error ? err.message : undefined)
|
|
58
|
+
|| String(err)
|
|
59
|
+
|| "Unknown install error";
|
|
60
60
|
|
|
61
61
|
// Emit error event
|
|
62
62
|
if (pi) {
|
package/src/readme.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { existsSync, readFileSync } from "fs";
|
|
10
|
-
import { join
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
import { findPackageRoot } from "@pi-unipi/core";
|
|
11
12
|
import { MODULES } from "@pi-unipi/core";
|
|
12
13
|
import type { ReadmeEntry } from "../types.js";
|
|
13
14
|
|
|
@@ -35,14 +36,12 @@ const PACKAGE_MAP: Record<string, string> = {
|
|
|
35
36
|
updater: MODULES.UPDATER,
|
|
36
37
|
};
|
|
37
38
|
|
|
38
|
-
/** Resolve the unipi
|
|
39
|
+
/** Resolve the unipi package root directory */
|
|
39
40
|
function resolveUnipiRoot(): string {
|
|
40
|
-
// Walk up from this file to find
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
dir = resolve(dir, "../../..");
|
|
45
|
-
return dir;
|
|
41
|
+
// Walk up from this file to find @pi-unipi/unipi by name
|
|
42
|
+
const dir = new URL(".", import.meta.url).pathname;
|
|
43
|
+
const root = findPackageRoot(dir, "@pi-unipi/unipi");
|
|
44
|
+
return root ?? join(dir, ".."); // fallback to parent
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
/** Get version from a package.json at the given directory */
|
|
@@ -11,7 +11,7 @@ import { Key, matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi
|
|
|
11
11
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
12
12
|
import { parseChangelog } from "../changelog.js";
|
|
13
13
|
import { renderMarkdown } from "../markdown.js";
|
|
14
|
-
import {
|
|
14
|
+
import { getInstalledPackageVersion } from "@pi-unipi/core";
|
|
15
15
|
import type { ChangelogEntry } from "../../types.js";
|
|
16
16
|
|
|
17
17
|
type View = "list" | "detail";
|
|
@@ -39,13 +39,14 @@ function padVisible(content: string, targetWidth: number): string {
|
|
|
39
39
|
*/
|
|
40
40
|
export function renderChangelogOverlay() {
|
|
41
41
|
return (
|
|
42
|
-
tui:
|
|
42
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
43
43
|
theme: Theme,
|
|
44
|
-
_kb:
|
|
44
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
45
45
|
done: (result: { viewed: boolean } | null) => void,
|
|
46
46
|
) => {
|
|
47
|
-
const installedVersion =
|
|
48
|
-
new URL("
|
|
47
|
+
const installedVersion = getInstalledPackageVersion(
|
|
48
|
+
new URL("..", import.meta.url).pathname,
|
|
49
|
+
"@pi-unipi/unipi",
|
|
49
50
|
);
|
|
50
51
|
|
|
51
52
|
const state: ChangelogState = {
|
|
@@ -38,9 +38,9 @@ function padVisible(content: string, targetWidth: number): string {
|
|
|
38
38
|
*/
|
|
39
39
|
export function renderReadmeOverlay(params?: { openDirect?: string }) {
|
|
40
40
|
return (
|
|
41
|
-
tui:
|
|
41
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
42
42
|
theme: Theme,
|
|
43
|
-
_kb:
|
|
43
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
44
44
|
done: (result: { viewed: boolean } | null) => void,
|
|
45
45
|
) => {
|
|
46
46
|
const state: ReadmeState = {
|
|
@@ -61,7 +61,7 @@ export function renderReadmeOverlay(params?: { openDirect?: string }) {
|
|
|
61
61
|
const readmePath = resolveReadmePath(params.openDirect);
|
|
62
62
|
if (readmePath) {
|
|
63
63
|
const content = readFileSync(readmePath, "utf-8");
|
|
64
|
-
state.contentLines = renderMarkdown(content, (tui.
|
|
64
|
+
state.contentLines = renderMarkdown(content, (tui.terminal?.columns ?? 80) - 4, theme);
|
|
65
65
|
state.view = "content";
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -203,7 +203,7 @@ export function renderReadmeOverlay(params?: { openDirect?: string }) {
|
|
|
203
203
|
const entry = state.entries[state.listIndex]!;
|
|
204
204
|
try {
|
|
205
205
|
const content = readFileSync(entry.path, "utf-8");
|
|
206
|
-
state.contentLines = renderMarkdown(content, (tui.
|
|
206
|
+
state.contentLines = renderMarkdown(content, (tui.terminal?.columns ?? 80) - 4, theme);
|
|
207
207
|
state.contentScroll = 0;
|
|
208
208
|
state.view = "content";
|
|
209
209
|
} catch {
|
|
@@ -42,9 +42,9 @@ function trunc(text: string, width: number): string {
|
|
|
42
42
|
*/
|
|
43
43
|
export function renderSettingsOverlay() {
|
|
44
44
|
return (
|
|
45
|
-
tui:
|
|
46
|
-
_theme:
|
|
47
|
-
_kb:
|
|
45
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
46
|
+
_theme: import("@mariozechner/pi-coding-agent").Theme,
|
|
47
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
48
48
|
done: (result: { saved: boolean } | null) => void,
|
|
49
49
|
) => {
|
|
50
50
|
const state = {
|
|
@@ -41,9 +41,9 @@ interface UpdateState {
|
|
|
41
41
|
*/
|
|
42
42
|
export function renderUpdateOverlay(checkResult: UpdateCheckResult) {
|
|
43
43
|
return (
|
|
44
|
-
tui:
|
|
44
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
45
45
|
theme: Theme,
|
|
46
|
-
_kb:
|
|
46
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
47
47
|
done: (result: { updated: boolean } | null) => void,
|
|
48
48
|
) => {
|
|
49
49
|
const config = loadConfig();
|
|
@@ -66,7 +66,7 @@ export function renderUpdateOverlay(checkResult: UpdateCheckResult) {
|
|
|
66
66
|
: `${theme.bold(entry.version)} — ${theme.fg("muted", "Unreleased")}`;
|
|
67
67
|
contentLines.push(` ${title}`);
|
|
68
68
|
// Use markdown renderer for the body content
|
|
69
|
-
const bodyLines = renderMarkdown(entry.body, (tui.
|
|
69
|
+
const bodyLines = renderMarkdown(entry.body, (tui.terminal?.columns ?? 80) - 6, theme);
|
|
70
70
|
for (const line of bodyLines) {
|
|
71
71
|
contentLines.push(` ${line}`);
|
|
72
72
|
}
|