@pi-unipi/unipi 2.6.0 → 2.6.2
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/CHANGELOG.md +19 -0
- package/package.json +21 -22
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/settings-tui.ts +18 -34
- package/packages/autocomplete/package.json +1 -1
- package/packages/autocomplete/src/constants.ts +2 -15
- package/packages/autocomplete/src/provider.ts +3 -17
- package/packages/btw/extensions/btw.ts +18 -45
- package/packages/btw/package.json +2 -2
- package/packages/compactor/README.md +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/compactor/skills/compactor/SKILL.md +1 -1
- package/packages/compactor/skills/compactor-detail/SKILL.md +3 -5
- package/packages/compactor/skills/compactor-doctor/SKILL.md +1 -1
- package/packages/compactor/skills/compactor-stats/SKILL.md +1 -1
- package/packages/compactor/src/commands/index.ts +47 -78
- package/packages/compactor/src/compaction/brief.ts +161 -90
- package/packages/compactor/src/compaction/build-sections.ts +3 -4
- package/packages/compactor/src/compaction/compact-args.ts +86 -0
- package/packages/compactor/src/compaction/cut.ts +270 -28
- package/packages/compactor/src/compaction/drill-down.ts +261 -0
- package/packages/compactor/src/compaction/format-recall.ts +96 -0
- package/packages/compactor/src/compaction/format.ts +8 -3
- package/packages/compactor/src/compaction/hooks.ts +248 -72
- package/packages/compactor/src/compaction/merge.ts +34 -4
- package/packages/compactor/src/compaction/rank.ts +270 -0
- package/packages/compactor/src/compaction/recall-scope.ts +28 -0
- package/packages/compactor/src/compaction/search-entries.ts +333 -96
- package/packages/compactor/src/compaction/skill-collapse.ts +35 -0
- package/packages/compactor/src/compaction/summarize.ts +37 -6
- package/packages/compactor/src/compaction/token-estimate.ts +104 -0
- package/packages/compactor/src/compaction/touched-files.ts +35 -0
- package/packages/compactor/src/config/manager.ts +2 -27
- package/packages/compactor/src/config/presets.ts +0 -2
- package/packages/compactor/src/config/schema.ts +2 -16
- package/packages/compactor/src/executor/executor.ts +6 -15
- package/packages/compactor/src/executor/runtime.ts +2 -12
- package/packages/compactor/src/index.ts +4 -121
- package/packages/compactor/src/info-screen.ts +3 -10
- package/packages/compactor/src/security/evaluator.ts +0 -53
- package/packages/compactor/src/security/policy.ts +7 -8
- package/packages/compactor/src/session/db.ts +0 -6
- package/packages/compactor/src/tools/ctx-execute-file.ts +0 -5
- package/packages/compactor/src/tools/register.ts +27 -50
- package/packages/compactor/src/tools/vcc-recall.ts +86 -48
- package/packages/compactor/src/tui/settings-overlay.ts +20 -40
- package/packages/compactor/src/types.ts +43 -100
- package/packages/core/constants.ts +1 -28
- package/packages/core/events.ts +1 -83
- package/packages/core/index.ts +1 -0
- package/packages/core/model-cache.ts +18 -12
- package/packages/core/package.json +3 -1
- package/packages/core/tui-overlay.ts +89 -0
- package/packages/core/tui-width.ts +18 -0
- package/packages/core/utils.ts +43 -0
- package/packages/footer/package.json +2 -2
- package/packages/footer/src/help.ts +2 -2
- package/packages/footer/src/index.ts +9 -10
- package/packages/footer/src/presets.ts +1 -27
- package/packages/footer/src/registry/index.ts +0 -23
- package/packages/footer/src/rendering/icons.ts +0 -13
- package/packages/footer/src/rendering/renderer.ts +5 -40
- package/packages/footer/src/rendering/separators.ts +0 -10
- package/packages/footer/src/rendering/theme.ts +1 -15
- package/packages/footer/src/segments/compactor.ts +7 -14
- package/packages/footer/src/segments/core.ts +15 -54
- package/packages/footer/src/segments/kanboard.ts +5 -5
- package/packages/footer/src/segments/mcp.ts +5 -5
- package/packages/footer/src/segments/memory.ts +4 -4
- package/packages/footer/src/segments/notify.ts +2 -2
- package/packages/footer/src/segments/ralph.ts +3 -3
- package/packages/footer/src/segments/status-ext.ts +1 -1
- package/packages/footer/src/segments/workflow.ts +3 -3
- package/packages/footer/src/tps-tracker.ts +0 -8
- package/packages/footer/src/tui/settings-tui.ts +14 -31
- package/packages/footer/src/types.ts +0 -15
- package/packages/image/package.json +2 -2
- package/packages/image/src/register-providers.ts +0 -11
- package/packages/image/src/tools.ts +0 -3
- package/packages/image/src/tui/model-selector.ts +36 -71
- package/packages/info-screen/config.ts +0 -16
- package/packages/info-screen/core-groups.ts +0 -10
- package/packages/info-screen/index.ts +22 -13
- package/packages/info-screen/package.json +2 -2
- package/packages/info-screen/registry.ts +1 -72
- package/packages/info-screen/tui/info-overlay.ts +85 -100
- package/packages/info-screen/usage-parser.ts +12 -47
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/input-shortcuts/src/index.ts +3 -3
- package/packages/input-shortcuts/src/registers.ts +0 -8
- package/packages/input-shortcuts/src/settings-overlay.ts +4 -13
- package/packages/input-shortcuts/src/undo-redo.ts +0 -12
- package/packages/kanboard/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/mcp/src/bridge/client.ts +0 -15
- package/packages/mcp/src/config/manager.ts +0 -38
- package/packages/mcp/src/config/schema.ts +0 -27
- package/packages/mcp/src/config/sync.ts +0 -29
- package/packages/mcp/src/index.ts +1 -1
- package/packages/mcp/src/tui/add-overlay.ts +6 -6
- package/packages/mcp/src/types.ts +0 -6
- package/packages/memory/embedding.ts +0 -31
- package/packages/memory/mempalace.ts +0 -16
- package/packages/memory/package.json +4 -8
- package/packages/memory/storage.ts +56 -753
- package/packages/milestone/hooks.ts +1 -6
- package/packages/milestone/milestone.ts +2 -41
- package/packages/milestone/package.json +2 -2
- package/packages/notify/README.md +1 -0
- package/packages/notify/commands.ts +61 -3
- package/packages/notify/events.ts +0 -10
- package/packages/notify/package.json +2 -2
- package/packages/notify/settings.ts +0 -19
- package/packages/notify/tui/gotify-setup.ts +108 -143
- package/packages/notify/tui/ntfy-setup.ts +137 -172
- package/packages/notify/tui/recap-model-selector.ts +107 -101
- package/packages/notify/tui/settings-overlay.ts +94 -117
- package/packages/notify/tui/telegram-setup.ts +48 -79
- package/packages/notify/types.ts +0 -2
- package/packages/ralph/index.ts +11 -35
- package/packages/ralph/package.json +3 -3
- package/packages/ralph/ralph-loop.ts +3 -44
- package/packages/subagents/package.json +2 -1
- package/packages/subagents/src/agent-manager.ts +0 -51
- package/packages/subagents/src/agent-runner.ts +6 -80
- package/packages/subagents/src/conversation-viewer.ts +1 -19
- package/packages/subagents/src/core-compat.ts +8 -25
- package/packages/subagents/src/custom-agents.ts +0 -1
- package/packages/subagents/src/index.ts +3 -48
- package/packages/subagents/src/types.ts +0 -11
- package/packages/subagents/src/widget.ts +5 -5
- package/packages/unipi/bundled.js +4468 -7769
- package/packages/unipi/index.ts +6 -3
- package/packages/updater/package.json +2 -2
- package/packages/updater/src/changelog.ts +1 -16
- package/packages/updater/src/index.ts +0 -5
- package/packages/updater/src/installer.ts +4 -26
- package/packages/updater/src/markdown.ts +6 -152
- package/packages/updater/src/settings.ts +0 -15
- package/packages/updater/src/tui/changelog-overlay.ts +42 -234
- package/packages/updater/src/tui/list-detail-overlay.ts +260 -0
- package/packages/updater/src/tui/readme-overlay.ts +53 -210
- package/packages/updater/src/tui/settings-overlay.ts +13 -26
- package/packages/updater/src/version.ts +2 -31
- package/packages/utility/package.json +2 -4
- package/packages/utility/src/commands.ts +4 -5
- package/packages/utility/src/herdr-sync.ts +136 -0
- package/packages/utility/src/index.ts +11 -68
- package/packages/utility/src/lifecycle/cleanup.ts +2 -16
- package/packages/utility/src/{diff/settings.ts → settings.ts} +42 -80
- package/packages/utility/src/tools/env.ts +0 -0
- package/packages/utility/src/tui/name-badge-state.ts +18 -2
- package/packages/utility/src/tui/name-badge.ts +5 -4
- package/packages/utility/src/tui/util-settings-tui.ts +41 -224
- package/packages/web-api/package.json +2 -6
- package/packages/web-api/src/engine/dependencies.ts +13 -134
- package/packages/web-api/src/engine/extract.ts +9 -99
- package/packages/web-api/src/engine/format.ts +0 -75
- package/packages/web-api/src/engine/types.ts +0 -39
- package/packages/web-api/src/index.ts +1 -2
- package/packages/web-api/src/providers/base.ts +0 -10
- package/packages/web-api/src/providers/duckduckgo.ts +0 -1
- package/packages/web-api/src/providers/firecrawl.ts +0 -9
- package/packages/web-api/src/providers/jina-reader.ts +0 -9
- package/packages/web-api/src/providers/jina-search.ts +0 -9
- package/packages/web-api/src/providers/perplexity.ts +0 -9
- package/packages/web-api/src/providers/registry.ts +0 -80
- package/packages/web-api/src/providers/serpapi.ts +0 -9
- package/packages/web-api/src/providers/tavily.ts +0 -9
- package/packages/web-api/src/providers/wigolo-client.ts +0 -30
- package/packages/web-api/src/providers/wigolo.ts +0 -1
- package/packages/web-api/src/settings.ts +17 -77
- package/packages/web-api/src/tools.ts +21 -24
- package/packages/web-api/src/tui/settings-dialog.ts +0 -1
- package/packages/workflow/commands.ts +38 -122
- package/packages/workflow/index.ts +1 -5
- package/packages/workflow/package.json +2 -2
- package/packages/cocoindex/README.md +0 -94
- package/packages/cocoindex/bridge.ts +0 -842
- package/packages/cocoindex/commands.ts +0 -175
- package/packages/cocoindex/index.ts +0 -48
- package/packages/cocoindex/installer.ts +0 -397
- package/packages/cocoindex/package.json +0 -49
- package/packages/cocoindex/skills/cocoindex/SKILL.md +0 -88
- package/packages/cocoindex/tools.ts +0 -157
- package/packages/compactor/src/display/diff-renderer.ts +0 -281
- package/packages/compactor/src/display/line-width-safety.ts +0 -28
- package/packages/compactor/src/display/render-utils.ts +0 -52
- package/packages/compactor/src/display/thinking-label.ts +0 -18
- package/packages/compactor/src/display/tool-overrides.ts +0 -136
- package/packages/compactor/src/tools/compact.ts +0 -20
- package/packages/subagents/src/file-lock.ts +0 -102
- package/packages/utility/src/cache/ttl-cache.ts +0 -311
- package/packages/utility/src/diff/highlighter.ts +0 -352
- package/packages/utility/src/diff/parser.ts +0 -191
- package/packages/utility/src/diff/renderer.ts +0 -395
- package/packages/utility/src/diff/theme.ts +0 -316
- package/packages/utility/src/diff/wrapper.ts +0 -339
- package/packages/utility/src/display/capabilities.ts +0 -214
- package/packages/utility/src/display/width.ts +0 -226
- package/packages/utility/src/tools/batch.ts +0 -229
- package/packages/utility/src/tui/badge-settings-tui.ts +0 -388
- package/packages/utility/src/tui/badge-settings.ts +0 -67
- package/packages/utility/src/tui/settings-inspector.ts +0 -303
- package/packages/web-api/src/providers/llm-summarize.ts +0 -71
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
13
|
-
import { matchesKey, SettingsList, type SettingItem, type SettingsListTheme } from "@earendil-works/pi-tui";
|
|
13
|
+
import { Key, matchesKey, SettingsList, type SettingItem, type SettingsListTheme } from "@earendil-works/pi-tui";
|
|
14
14
|
import { loadFooterSettings, saveFooterSettings } from "../config.js";
|
|
15
15
|
import { PRESET_NAMES } from "../presets.js";
|
|
16
16
|
import { setIconStyle } from "../rendering/icons.js";
|
|
17
17
|
import type { FooterGroup, FooterSettings, SeparatorStyle, IconStyle } from "../types.js";
|
|
18
|
-
import { boxInnerWidth } from "@pi-unipi/core";
|
|
18
|
+
import { boxInnerWidth, OverlayTheme } from "@pi-unipi/core";
|
|
19
19
|
|
|
20
20
|
// ─── Section types ─────────────────────────────────────────────────────
|
|
21
21
|
|
|
@@ -43,27 +43,10 @@ const THEME: SettingsListTheme = {
|
|
|
43
43
|
hint: (text) => `\x1b[2m${text}\x1b[0m`,
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
// ───
|
|
46
|
+
// ─── Shared box-drawing helper ────────────────────────────────────────
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
const visLen = visibleWidth(content);
|
|
50
|
-
const pad = Math.max(0, innerWidth - visLen);
|
|
51
|
-
return `\x1b[90m│\x1b[0m${content}${" ".repeat(pad)}\x1b[90m│\x1b[0m`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function ruleLine(innerWidth: number): string {
|
|
55
|
-
return `\x1b[90m├${"─".repeat(innerWidth)}┤\x1b[0m`;
|
|
56
|
-
}
|
|
48
|
+
const overlay = new OverlayTheme();
|
|
57
49
|
|
|
58
|
-
function borderLine(innerWidth: number, edge: "top" | "bottom"): string {
|
|
59
|
-
const left = edge === "top" ? "┌" : "└";
|
|
60
|
-
const right = edge === "top" ? "┐" : "┘";
|
|
61
|
-
return `\x1b[90m${left}${"─".repeat(innerWidth)}${right}\x1b[0m`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function visibleWidth(text: string): number {
|
|
65
|
-
return text.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
66
|
-
}
|
|
67
50
|
|
|
68
51
|
// ─── Show the footer settings overlay ──────────────────────────────────
|
|
69
52
|
|
|
@@ -129,7 +112,7 @@ class FooterSettingsOverlay {
|
|
|
129
112
|
|
|
130
113
|
handleInput(data: string): void {
|
|
131
114
|
// Tab cycles sections
|
|
132
|
-
if (data === "\t" || data
|
|
115
|
+
if (data === "\t" || matchesKey(data, Key.shift("tab"))) {
|
|
133
116
|
const idx = SECTIONS.indexOf(this.section);
|
|
134
117
|
if (data === "\t") {
|
|
135
118
|
this.section = SECTIONS[(idx + 1) % SECTIONS.length];
|
|
@@ -209,7 +192,7 @@ class FooterSettingsOverlay {
|
|
|
209
192
|
}
|
|
210
193
|
|
|
211
194
|
// Left arrow / backspace in segment drill-down — back to groups
|
|
212
|
-
if (this.section === "segments" && this.selectedGroupId && (data
|
|
195
|
+
if (this.section === "segments" && this.selectedGroupId && (matchesKey(data, Key.left) || data === "\x7f")) {
|
|
213
196
|
this.backToGroups();
|
|
214
197
|
return;
|
|
215
198
|
}
|
|
@@ -462,8 +445,8 @@ class FooterSettingsOverlay {
|
|
|
462
445
|
const lines: string[] = [];
|
|
463
446
|
|
|
464
447
|
// Header
|
|
465
|
-
lines.push(borderLine(innerWidth, "top"));
|
|
466
|
-
lines.push(frameLine(`\x1b[1m\x1b[36m⚙ Footer Settings\x1b[0m`, innerWidth));
|
|
448
|
+
lines.push(overlay.borderLine(innerWidth, "top"));
|
|
449
|
+
lines.push(overlay.frameLine(`\x1b[1m\x1b[36m⚙ Footer Settings\x1b[0m`, innerWidth));
|
|
467
450
|
|
|
468
451
|
// Section tabs
|
|
469
452
|
const tabParts = SECTIONS.map((s) => {
|
|
@@ -473,20 +456,20 @@ class FooterSettingsOverlay {
|
|
|
473
456
|
}
|
|
474
457
|
return `\x1b[2m${label}\x1b[0m`;
|
|
475
458
|
});
|
|
476
|
-
lines.push(frameLine(` ${tabParts.join(" ")}`, innerWidth));
|
|
477
|
-
lines.push(ruleLine(innerWidth));
|
|
459
|
+
lines.push(overlay.frameLine(` ${tabParts.join(" ")}`, innerWidth));
|
|
460
|
+
lines.push(overlay.ruleLine(innerWidth));
|
|
478
461
|
|
|
479
462
|
// Section content
|
|
480
463
|
const activeList = this.currentList;
|
|
481
464
|
if (activeList) {
|
|
482
465
|
const contentLines = activeList.render(innerWidth - 2);
|
|
483
466
|
for (const line of contentLines) {
|
|
484
|
-
lines.push(frameLine(` ${line}`, innerWidth));
|
|
467
|
+
lines.push(overlay.frameLine(` ${line}`, innerWidth));
|
|
485
468
|
}
|
|
486
469
|
}
|
|
487
470
|
|
|
488
471
|
// Footer hints
|
|
489
|
-
lines.push(ruleLine(innerWidth));
|
|
472
|
+
lines.push(overlay.ruleLine(innerWidth));
|
|
490
473
|
|
|
491
474
|
let hints: string;
|
|
492
475
|
if (this.section === "segments" && this.selectedGroupId) {
|
|
@@ -496,8 +479,8 @@ class FooterSettingsOverlay {
|
|
|
496
479
|
} else {
|
|
497
480
|
hints = "j/k navigate · Space/Enter change · Tab section · q close";
|
|
498
481
|
}
|
|
499
|
-
lines.push(frameLine(`\x1b[2m${hints}\x1b[0m`, innerWidth));
|
|
500
|
-
lines.push(borderLine(innerWidth, "bottom"));
|
|
482
|
+
lines.push(overlay.frameLine(`\x1b[2m${hints}\x1b[0m`, innerWidth));
|
|
483
|
+
lines.push(overlay.borderLine(innerWidth, "bottom"));
|
|
501
484
|
|
|
502
485
|
return lines;
|
|
503
486
|
}
|
|
@@ -145,8 +145,6 @@ export interface FooterSegment {
|
|
|
145
145
|
description: string;
|
|
146
146
|
/** Layout zone assignment */
|
|
147
147
|
zone: SegmentZone;
|
|
148
|
-
/** Icon glyph (Nerd Font or ASCII) */
|
|
149
|
-
icon: string;
|
|
150
148
|
/** Render function */
|
|
151
149
|
render: SegmentRenderFn;
|
|
152
150
|
/** Whether this segment is shown by default */
|
|
@@ -161,8 +159,6 @@ export interface FooterGroup {
|
|
|
161
159
|
id: string;
|
|
162
160
|
/** Display name */
|
|
163
161
|
name: string;
|
|
164
|
-
/** Group icon */
|
|
165
|
-
icon: string;
|
|
166
162
|
/** Segments within this group */
|
|
167
163
|
segments: FooterSegment[];
|
|
168
164
|
/** Whether this group is shown by default */
|
|
@@ -199,13 +195,6 @@ export interface FooterSettings {
|
|
|
199
195
|
groups: Record<string, FooterGroupSettings>;
|
|
200
196
|
}
|
|
201
197
|
|
|
202
|
-
/** Full footer config (settings + runtime state) */
|
|
203
|
-
export interface FooterConfig {
|
|
204
|
-
settings: FooterSettings;
|
|
205
|
-
/** Runtime: whether footer is currently active */
|
|
206
|
-
active: boolean;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
198
|
// ─── Presets ────────────────────────────────────────────────────────────────
|
|
210
199
|
|
|
211
200
|
/** Preset definition */
|
|
@@ -218,10 +207,6 @@ export interface PresetDef {
|
|
|
218
207
|
secondarySegments: string[];
|
|
219
208
|
/** Color scheme for this preset */
|
|
220
209
|
colors?: ColorScheme;
|
|
221
|
-
/** Per-segment options */
|
|
222
|
-
segmentOptions?: Record<string, Record<string, unknown>>;
|
|
223
|
-
/** Zone order (default: left, center, right) */
|
|
224
|
-
zoneOrder?: ("left" | "center" | "right")[];
|
|
225
210
|
/** Zone separator string (between zones) */
|
|
226
211
|
zoneSeparator?: string;
|
|
227
212
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/image",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Image generation and image recognition tools for the Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "2.6.
|
|
37
|
+
"@pi-unipi/core": "2.6.1"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-ai": "^0.80.0",
|
|
@@ -207,14 +207,3 @@ async function resolveProviderKey(
|
|
|
207
207
|
const envName = `${provider.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_API_KEY`;
|
|
208
208
|
return process.env[envName] || undefined;
|
|
209
209
|
}
|
|
210
|
-
|
|
211
|
-
/** Provider ids pi-ai can currently generate with, after registration. */
|
|
212
|
-
export function registeredProviderIds(images: {
|
|
213
|
-
getProviders?: () => ReadonlyArray<{ id: string }>;
|
|
214
|
-
}): string[] {
|
|
215
|
-
try {
|
|
216
|
-
return (images.getProviders?.() ?? []).map((p) => p.id);
|
|
217
|
-
} catch {
|
|
218
|
-
return [];
|
|
219
|
-
}
|
|
220
|
-
}
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
listAllImageGenModels,
|
|
20
20
|
resolveImageGenModel,
|
|
21
21
|
resolveVisionModel,
|
|
22
|
-
splitModelRef,
|
|
23
22
|
type ChatModelRegistry,
|
|
24
23
|
type VisionModel,
|
|
25
24
|
} from "./models.js";
|
|
@@ -325,5 +324,3 @@ function currentSessionModel(ctx: ExtensionContext): string {
|
|
|
325
324
|
}
|
|
326
325
|
return "";
|
|
327
326
|
}
|
|
328
|
-
|
|
329
|
-
export { splitModelRef };
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { Component } from "@earendil-works/pi-tui";
|
|
9
|
-
import { matchesKey
|
|
9
|
+
import { matchesKey } from "@earendil-works/pi-tui";
|
|
10
10
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
11
|
-
import { boxInnerWidth,
|
|
11
|
+
import { boxInnerWidth, OverlayTheme } from "@pi-unipi/core";
|
|
12
12
|
|
|
13
13
|
export interface SelectableModel {
|
|
14
14
|
provider: string;
|
|
@@ -29,7 +29,7 @@ export class ImageModelSelectorOverlay implements Component {
|
|
|
29
29
|
private filterMode = false;
|
|
30
30
|
private saved = false;
|
|
31
31
|
private error: string | null = null;
|
|
32
|
-
private
|
|
32
|
+
private overlay = new OverlayTheme();
|
|
33
33
|
/** Free-text entry, for models the catalog does not know about. */
|
|
34
34
|
private customMode = false;
|
|
35
35
|
private custom = "";
|
|
@@ -55,7 +55,7 @@ export class ImageModelSelectorOverlay implements Component {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
setTheme(theme: Theme): void {
|
|
58
|
-
this.theme
|
|
58
|
+
this.overlay.setTheme(theme);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
invalidate(): void {}
|
|
@@ -229,41 +229,6 @@ export class ImageModelSelectorOverlay implements Component {
|
|
|
229
229
|
this.onClose?.();
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
// ─── Theme helpers ───────────────────────────────────────────────────
|
|
233
|
-
|
|
234
|
-
private fg(color: string, text: string): string {
|
|
235
|
-
if (this.theme) return this.theme.fg(color as never, text);
|
|
236
|
-
const codes: Record<string, string> = {
|
|
237
|
-
accent: "\x1b[36m",
|
|
238
|
-
success: "\x1b[32m",
|
|
239
|
-
warning: "\x1b[33m",
|
|
240
|
-
error: "\x1b[31m",
|
|
241
|
-
dim: "\x1b[2m",
|
|
242
|
-
borderMuted: "\x1b[90m",
|
|
243
|
-
};
|
|
244
|
-
return `${codes[color] ?? ""}${text}\x1b[0m`;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private bold(text: string): string {
|
|
248
|
-
return this.theme ? this.theme.bold(text) : `\x1b[1m${text}\x1b[0m`;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
private frameLine(content: string, innerWidth: number): string {
|
|
252
|
-
const truncated = truncateToWidth(content, innerWidth, "");
|
|
253
|
-
const padding = safeRepeat(" ", innerWidth - visibleWidth(truncated));
|
|
254
|
-
return `${this.fg("borderMuted", "│")}${truncated}${padding}${this.fg("borderMuted", "│")}`;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private ruleLine(innerWidth: number): string {
|
|
258
|
-
return this.fg("borderMuted", `├${safeRepeat("─", innerWidth)}┤`);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
private borderLine(innerWidth: number, edge: "top" | "bottom"): string {
|
|
262
|
-
const left = edge === "top" ? "┌" : "└";
|
|
263
|
-
const right = edge === "top" ? "┐" : "┘";
|
|
264
|
-
return this.fg("borderMuted", `${left}${safeRepeat("─", innerWidth)}${right}`);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
232
|
render(width: number): string[] {
|
|
268
233
|
const innerWidth = boxInnerWidth(width);
|
|
269
234
|
const lines: string[] = [];
|
|
@@ -277,48 +242,48 @@ export class ImageModelSelectorOverlay implements Component {
|
|
|
277
242
|
? "Model used by image_generate"
|
|
278
243
|
: "Vision model used by image_recognize";
|
|
279
244
|
|
|
280
|
-
lines.push(this.borderLine(innerWidth, "top"));
|
|
281
|
-
lines.push(this.frameLine(this.fg("accent", this.bold(title)), innerWidth));
|
|
282
|
-
lines.push(this.frameLine(this.fg("dim", subtitle), innerWidth));
|
|
283
|
-
lines.push(this.ruleLine(innerWidth));
|
|
245
|
+
lines.push(this.overlay.borderLine(innerWidth, "top"));
|
|
246
|
+
lines.push(this.overlay.frameLine(this.overlay.fg("accent", this.overlay.bold(title)), innerWidth));
|
|
247
|
+
lines.push(this.overlay.frameLine(this.overlay.fg("dim", subtitle), innerWidth));
|
|
248
|
+
lines.push(this.overlay.ruleLine(innerWidth));
|
|
284
249
|
|
|
285
250
|
// Filter bar
|
|
286
251
|
if (this.customMode) {
|
|
287
252
|
lines.push(
|
|
288
|
-
this.frameLine(
|
|
289
|
-
` ${this.fg("accent", "Model:")} ${this.custom}${this.fg("accent", "█")}`,
|
|
253
|
+
this.overlay.frameLine(
|
|
254
|
+
` ${this.overlay.fg("accent", "Model:")} ${this.custom}${this.overlay.fg("accent", "█")}`,
|
|
290
255
|
innerWidth,
|
|
291
256
|
),
|
|
292
257
|
);
|
|
293
258
|
lines.push(
|
|
294
|
-
this.frameLine(
|
|
295
|
-
` ${this.fg("dim", "e.g. omniroute/fal/fal-ai/flux-2-pro")}`,
|
|
259
|
+
this.overlay.frameLine(
|
|
260
|
+
` ${this.overlay.fg("dim", "e.g. omniroute/fal/fal-ai/flux-2-pro")}`,
|
|
296
261
|
innerWidth,
|
|
297
262
|
),
|
|
298
263
|
);
|
|
299
264
|
} else if (this.filterMode) {
|
|
300
265
|
lines.push(
|
|
301
|
-
this.frameLine(
|
|
302
|
-
` ${this.fg("accent", "Filter:")} ${this.filter}${this.fg("accent", "█")}`,
|
|
266
|
+
this.overlay.frameLine(
|
|
267
|
+
` ${this.overlay.fg("accent", "Filter:")} ${this.filter}${this.overlay.fg("accent", "█")}`,
|
|
303
268
|
innerWidth,
|
|
304
269
|
),
|
|
305
270
|
);
|
|
306
271
|
} else if (this.filter) {
|
|
307
272
|
lines.push(
|
|
308
|
-
this.frameLine(
|
|
309
|
-
` ${this.fg("dim", "Filter:")} ${this.filter} ${this.fg("dim", "(press / to edit)")}`,
|
|
273
|
+
this.overlay.frameLine(
|
|
274
|
+
` ${this.overlay.fg("dim", "Filter:")} ${this.filter} ${this.overlay.fg("dim", "(press / to edit)")}`,
|
|
310
275
|
innerWidth,
|
|
311
276
|
),
|
|
312
277
|
);
|
|
313
278
|
} else {
|
|
314
279
|
lines.push(
|
|
315
|
-
this.frameLine(
|
|
316
|
-
` ${this.fg("dim", `${this.models.length} models · / filter · c custom`)}`,
|
|
280
|
+
this.overlay.frameLine(
|
|
281
|
+
` ${this.overlay.fg("dim", `${this.models.length} models · / filter · c custom`)}`,
|
|
317
282
|
innerWidth,
|
|
318
283
|
),
|
|
319
284
|
);
|
|
320
285
|
}
|
|
321
|
-
lines.push(this.ruleLine(innerWidth));
|
|
286
|
+
lines.push(this.overlay.ruleLine(innerWidth));
|
|
322
287
|
|
|
323
288
|
// Model list
|
|
324
289
|
const terminalRows = process.stdout.rows ?? 30;
|
|
@@ -335,47 +300,47 @@ export class ImageModelSelectorOverlay implements Component {
|
|
|
335
300
|
? "No image models available (needs OpenRouter)"
|
|
336
301
|
: "No vision-capable models configured"
|
|
337
302
|
: "No models match the filter";
|
|
338
|
-
lines.push(this.frameLine(` ${this.fg("dim", empty)}`, innerWidth));
|
|
303
|
+
lines.push(this.overlay.frameLine(` ${this.overlay.fg("dim", empty)}`, innerWidth));
|
|
339
304
|
} else {
|
|
340
305
|
for (let i = start; i < end; i++) {
|
|
341
306
|
const model = this.filtered[i];
|
|
342
307
|
const isSelected = i === this.selectedIndex;
|
|
343
|
-
const marker = isSelected ? this.fg("accent", "▸") : " ";
|
|
308
|
+
const marker = isSelected ? this.overlay.fg("accent", "▸") : " ";
|
|
344
309
|
const label = model.name || model.id;
|
|
345
|
-
const providerTag = this.fg("dim", `[${model.provider}]`);
|
|
310
|
+
const providerTag = this.overlay.fg("dim", `[${model.provider}]`);
|
|
346
311
|
const base = isSelected
|
|
347
|
-
? `${providerTag} ${this.bold(label)}`
|
|
348
|
-
: `${providerTag} ${this.fg("dim", label)}`;
|
|
312
|
+
? `${providerTag} ${this.overlay.bold(label)}`
|
|
313
|
+
: `${providerTag} ${this.overlay.fg("dim", label)}`;
|
|
349
314
|
const display = model.unavailable
|
|
350
|
-
? `${base} ${this.fg("warning", `(${model.unavailable})`)}`
|
|
315
|
+
? `${base} ${this.overlay.fg("warning", `(${model.unavailable})`)}`
|
|
351
316
|
: base;
|
|
352
|
-
lines.push(this.frameLine(` ${marker} ${display}`, innerWidth));
|
|
317
|
+
lines.push(this.overlay.frameLine(` ${marker} ${display}`, innerWidth));
|
|
353
318
|
}
|
|
354
319
|
}
|
|
355
320
|
|
|
356
321
|
if (!this.customMode && this.filtered.length > maxVisible) {
|
|
357
322
|
const pct = Math.round(((this.selectedIndex + 1) / this.filtered.length) * 100);
|
|
358
323
|
lines.push(
|
|
359
|
-
this.frameLine(
|
|
360
|
-
this.fg("dim", ` ${pct}% (${this.selectedIndex + 1}/${this.filtered.length})`),
|
|
324
|
+
this.overlay.frameLine(
|
|
325
|
+
this.overlay.fg("dim", ` ${pct}% (${this.selectedIndex + 1}/${this.filtered.length})`),
|
|
361
326
|
innerWidth,
|
|
362
327
|
),
|
|
363
328
|
);
|
|
364
329
|
}
|
|
365
330
|
|
|
366
331
|
if (this.error) {
|
|
367
|
-
lines.push(this.ruleLine(innerWidth));
|
|
368
|
-
lines.push(this.frameLine(` ${this.fg("error", `⚠ ${this.error}`)}`, innerWidth));
|
|
332
|
+
lines.push(this.overlay.ruleLine(innerWidth));
|
|
333
|
+
lines.push(this.overlay.frameLine(` ${this.overlay.fg("error", `⚠ ${this.error}`)}`, innerWidth));
|
|
369
334
|
}
|
|
370
335
|
if (this.saved) {
|
|
371
|
-
lines.push(this.ruleLine(innerWidth));
|
|
372
|
-
lines.push(this.frameLine(` ${this.fg("success", "✓ Model saved")}`, innerWidth));
|
|
336
|
+
lines.push(this.overlay.ruleLine(innerWidth));
|
|
337
|
+
lines.push(this.overlay.frameLine(` ${this.overlay.fg("success", "✓ Model saved")}`, innerWidth));
|
|
373
338
|
}
|
|
374
339
|
|
|
375
|
-
lines.push(this.ruleLine(innerWidth));
|
|
340
|
+
lines.push(this.overlay.ruleLine(innerWidth));
|
|
376
341
|
lines.push(
|
|
377
|
-
this.frameLine(
|
|
378
|
-
this.fg(
|
|
342
|
+
this.overlay.frameLine(
|
|
343
|
+
this.overlay.fg(
|
|
379
344
|
"dim",
|
|
380
345
|
this.customMode
|
|
381
346
|
? "Enter save · Esc back to list"
|
|
@@ -384,7 +349,7 @@ export class ImageModelSelectorOverlay implements Component {
|
|
|
384
349
|
innerWidth,
|
|
385
350
|
),
|
|
386
351
|
);
|
|
387
|
-
lines.push(this.borderLine(innerWidth, "bottom"));
|
|
352
|
+
lines.push(this.overlay.borderLine(innerWidth, "bottom"));
|
|
388
353
|
|
|
389
354
|
return lines;
|
|
390
355
|
}
|
|
@@ -164,15 +164,6 @@ export function setGroupSettings(groupId: string, groupSettings: GroupSettings):
|
|
|
164
164
|
saveInfoSettings(settings);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
/**
|
|
168
|
-
* Check if a group is enabled.
|
|
169
|
-
*/
|
|
170
|
-
export function isGroupEnabled(groupId: string): boolean {
|
|
171
|
-
const settings = getInfoSettings();
|
|
172
|
-
if (!(groupId in settings.groups)) return true; // Default to enabled
|
|
173
|
-
return settings.groups[groupId].show;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
167
|
/**
|
|
177
168
|
* Check if a stat within a group is enabled.
|
|
178
169
|
*/
|
|
@@ -182,10 +173,3 @@ export function isStatEnabled(groupId: string, statId: string): boolean {
|
|
|
182
173
|
if (!(statId in groupSettings.stats)) return true;
|
|
183
174
|
return groupSettings.stats[statId];
|
|
184
175
|
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Clear cached settings (for testing or reload).
|
|
188
|
-
*/
|
|
189
|
-
export function clearSettingsCache(): void {
|
|
190
|
-
cachedSettings = null;
|
|
191
|
-
}
|
|
@@ -141,11 +141,6 @@ export function startLoadTracking(): void {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
/** Record when a module starts loading */
|
|
145
|
-
export function recordModuleStart(name: string): void {
|
|
146
|
-
moduleStartTimes.set(name, Date.now());
|
|
147
|
-
}
|
|
148
|
-
|
|
149
144
|
/** Record a load time */
|
|
150
145
|
export function recordLoadTime(name: string, type: string, ms?: number): void {
|
|
151
146
|
// If no ms provided, calculate from start time
|
|
@@ -172,11 +167,6 @@ export function finishLoadTracking(): void {
|
|
|
172
167
|
}
|
|
173
168
|
}
|
|
174
169
|
|
|
175
|
-
/** Get load times */
|
|
176
|
-
export function getLoadTimes(): Array<{ name: string; type: string; ms: number }> {
|
|
177
|
-
return [...loadTimes];
|
|
178
|
-
}
|
|
179
|
-
|
|
180
170
|
/** Get total load time */
|
|
181
171
|
export function getTotalLoadTime(): number {
|
|
182
172
|
return totalLoadTimeMs > 0 ? totalLoadTimeMs : (loadTrackingStarted ? Date.now() - loadTrackingStartMs : 0);
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
import { dirname } from "node:path";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
14
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
15
|
-
import { UNIPI_EVENTS, MODULES, UNIPI_PREFIX, emitEvent, getPackageVersion, type UnipiModuleEvent
|
|
15
|
+
import { UNIPI_EVENTS, MODULES, UNIPI_PREFIX, emitEvent, getPackageVersion, type UnipiModuleEvent } from "@pi-unipi/core";
|
|
16
16
|
import { infoRegistry } from "./registry.js";
|
|
17
|
-
import { registerCoreGroups, trackModule, trackTool, setPiApi, registerSkillDir, startLoadTracking, recordLoadTime, finishLoadTracking
|
|
17
|
+
import { registerCoreGroups, trackModule, trackTool, setPiApi, registerSkillDir, startLoadTracking, recordLoadTime, finishLoadTracking } from "./core-groups.js";
|
|
18
18
|
|
|
19
19
|
/** Re-export for external use */
|
|
20
|
-
export { infoRegistry, registerSkillDir, startLoadTracking, recordLoadTime, finishLoadTracking
|
|
20
|
+
export { infoRegistry, registerSkillDir, startLoadTracking, recordLoadTime, finishLoadTracking };
|
|
21
21
|
import { getInfoSettings } from "./config.js";
|
|
22
22
|
import { InfoOverlay } from "./tui/info-overlay.js";
|
|
23
23
|
import { SettingsOverlay } from "./settings/settings-tui.js";
|
|
@@ -95,10 +95,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
pi.events.on(UNIPI_EVENTS.INFO_GROUP_REGISTERED, (_data) => {
|
|
99
|
-
// Group already registered via globalThis in registerGroup()
|
|
100
|
-
});
|
|
101
|
-
|
|
102
98
|
// Track built-in tools
|
|
103
99
|
const trackedBuiltinTools = new Set<string>();
|
|
104
100
|
pi.on("tool_call", async (event, _ctx) => {
|
|
@@ -116,9 +112,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
116
112
|
* Background: each group fetches independently, overlay re-renders reactively.
|
|
117
113
|
*/
|
|
118
114
|
function showOverlay(ctx: ExtensionContext, autoCloseMs?: number): void {
|
|
115
|
+
let overlay: InfoOverlay;
|
|
119
116
|
ctx.ui.custom<void>(
|
|
120
117
|
(tui, theme, _keybindings, done) => {
|
|
121
|
-
|
|
118
|
+
overlay = new InfoOverlay();
|
|
122
119
|
overlay.setTheme(theme);
|
|
123
120
|
overlayVisible = true;
|
|
124
121
|
overlay.onClose = () => {
|
|
@@ -127,11 +124,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
127
124
|
done();
|
|
128
125
|
};
|
|
129
126
|
overlay.requestRender = () => tui.requestRender();
|
|
130
|
-
|
|
131
|
-
if (autoCloseMs && autoCloseMs > 0) {
|
|
132
|
-
overlay.startBootTimer(autoCloseMs);
|
|
133
|
-
}
|
|
134
|
-
return {
|
|
127
|
+
const component = {
|
|
135
128
|
render: (w: number) => overlay.render(w),
|
|
136
129
|
invalidate: () => overlay.invalidate(),
|
|
137
130
|
handleInput: (data: string) => {
|
|
@@ -139,6 +132,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
139
132
|
tui.requestRender();
|
|
140
133
|
},
|
|
141
134
|
};
|
|
135
|
+
// Boot dashboard dismisses itself; any keypress cancels the timer.
|
|
136
|
+
if (autoCloseMs && autoCloseMs > 0) {
|
|
137
|
+
overlay.startBootTimer(autoCloseMs);
|
|
138
|
+
}
|
|
139
|
+
return component;
|
|
142
140
|
},
|
|
143
141
|
{
|
|
144
142
|
overlay: true,
|
|
@@ -148,6 +146,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
148
146
|
anchor: "center" as const,
|
|
149
147
|
margin: 2,
|
|
150
148
|
},
|
|
149
|
+
// `done()` (the extension UI's close callback) pops the *topmost* overlay
|
|
150
|
+
// in the TUI stack, not this one specifically. When another overlay (e.g.
|
|
151
|
+
// the updater's "Update Available" prompt) is stacked on top, the boot
|
|
152
|
+
// auto-close timer must not fire `done()` — that would pop the covering
|
|
153
|
+
// overlay and strand this dashboard with a spent one-shot close the user
|
|
154
|
+
// can no longer dismiss. `isTopmostOverlay` lets the boot timer defer
|
|
155
|
+
// until we are the focused (topmost) entry; the user can still press
|
|
156
|
+
// q/Esc to close once the covering overlay is gone.
|
|
157
|
+
onHandle: (handle) => {
|
|
158
|
+
overlay.isTopmostOverlay = () => handle.isFocused();
|
|
159
|
+
},
|
|
151
160
|
}
|
|
152
161
|
);
|
|
153
162
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "2.6.
|
|
36
|
+
"@pi-unipi/core": "2.6.1"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.80.0",
|