@pi-unipi/unipi 2.20.3 → 2.20.4
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 +10 -0
- package/package.json +24 -24
- package/packages/ask-user/package.json +2 -2
- package/packages/autocomplete/package.json +1 -1
- package/packages/background-tasks/package.json +2 -2
- package/packages/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/package.json +1 -1
- package/packages/footer/package.json +3 -3
- package/packages/fusion/README.md +14 -5
- package/packages/fusion/package.json +3 -3
- package/packages/fusion/src/picker.ts +80 -11
- package/packages/image/package.json +2 -2
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/milestone/package.json +2 -2
- package/packages/notify/package.json +2 -2
- package/packages/ralph/package.json +3 -3
- package/packages/subagents/package.json +2 -2
- package/packages/trajectory/package.json +1 -1
- package/packages/unipi/bundled.js +57 -10
- package/packages/updater/package.json +2 -2
- package/packages/utility/package.json +2 -2
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.20.4] — 2026-09-19
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- `fusion`: **the `/unipi:model` picker name column now grows with the terminal.** `NAME_COL` was a fixed 24 columns, so every name past 23 characters was ellipsized even on a wide terminal and the thinking-effort control sat close to the name. `packages/fusion/src/picker.ts` now computes the column per render from the widest row label (`NAME_COL_MIN = 24`, capped to the available width) and keeps the effort bar right-anchored, so full names fit before the effort control.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `fusion`: **model rows that look like a `provider/id` key are no longer ambiguous.** Rows label with `model.name || model.id` and never showed the provider, so an OpenRouter model named `deepseek/deepseek-v4.1-flash` was indistinguishable from a model actually served by provider `deepseek`. A dim `provider · ` prefix is now added only when the display name contains `/` or the same name is offered by more than one provider; the prefix is never truncated (the friendly name truncates instead). The highlighted row's price panel now spells out the exact registry key (`Model key openrouter/deepseek/deepseek-v4.1-flash`, both lead and sidekick keys on the Fusion row).
|
|
18
|
+
|
|
9
19
|
## [2.20.3] — 2026-09-17
|
|
10
20
|
|
|
11
21
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/unipi",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "All-in-one extension suite for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -84,29 +84,29 @@
|
|
|
84
84
|
"typebox": "^1.1.38"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@pi-unipi/ask-user": "2.20.
|
|
88
|
-
"@pi-unipi/background-tasks": "2.20.
|
|
89
|
-
"@pi-unipi/btw": "2.20.
|
|
90
|
-
"@pi-unipi/command-enchantment": "2.20.
|
|
91
|
-
"@pi-unipi/compactor": "2.20.
|
|
92
|
-
"@pi-unipi/core": "2.20.
|
|
93
|
-
"@pi-unipi/footer": "2.20.
|
|
94
|
-
"@pi-unipi/image": "2.20.
|
|
95
|
-
"@pi-unipi/fusion": "2.20.
|
|
96
|
-
"@pi-unipi/info-screen": "2.20.
|
|
97
|
-
"@pi-unipi/input-shortcuts": "2.20.
|
|
98
|
-
"@pi-unipi/kanboard": "2.20.
|
|
99
|
-
"@pi-unipi/mcp": "2.20.
|
|
100
|
-
"@pi-unipi/memory": "2.20.
|
|
101
|
-
"@pi-unipi/milestone": "2.20.
|
|
102
|
-
"@pi-unipi/notify": "2.20.
|
|
103
|
-
"@pi-unipi/ralph": "2.20.
|
|
104
|
-
"@pi-unipi/subagents": "2.20.
|
|
105
|
-
"@pi-unipi/trajectory": "2.20.
|
|
106
|
-
"@pi-unipi/updater": "2.20.
|
|
107
|
-
"@pi-unipi/utility": "2.20.
|
|
108
|
-
"@pi-unipi/web-api": "2.20.
|
|
109
|
-
"@pi-unipi/workflow": "2.20.
|
|
87
|
+
"@pi-unipi/ask-user": "2.20.4",
|
|
88
|
+
"@pi-unipi/background-tasks": "2.20.4",
|
|
89
|
+
"@pi-unipi/btw": "2.20.4",
|
|
90
|
+
"@pi-unipi/command-enchantment": "2.20.4",
|
|
91
|
+
"@pi-unipi/compactor": "2.20.4",
|
|
92
|
+
"@pi-unipi/core": "2.20.4",
|
|
93
|
+
"@pi-unipi/footer": "2.20.4",
|
|
94
|
+
"@pi-unipi/image": "2.20.4",
|
|
95
|
+
"@pi-unipi/fusion": "2.20.4",
|
|
96
|
+
"@pi-unipi/info-screen": "2.20.4",
|
|
97
|
+
"@pi-unipi/input-shortcuts": "2.20.4",
|
|
98
|
+
"@pi-unipi/kanboard": "2.20.4",
|
|
99
|
+
"@pi-unipi/mcp": "2.20.4",
|
|
100
|
+
"@pi-unipi/memory": "2.20.4",
|
|
101
|
+
"@pi-unipi/milestone": "2.20.4",
|
|
102
|
+
"@pi-unipi/notify": "2.20.4",
|
|
103
|
+
"@pi-unipi/ralph": "2.20.4",
|
|
104
|
+
"@pi-unipi/subagents": "2.20.4",
|
|
105
|
+
"@pi-unipi/trajectory": "2.20.4",
|
|
106
|
+
"@pi-unipi/updater": "2.20.4",
|
|
107
|
+
"@pi-unipi/utility": "2.20.4",
|
|
108
|
+
"@pi-unipi/web-api": "2.20.4",
|
|
109
|
+
"@pi-unipi/workflow": "2.20.4"
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
112
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ask-user",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Structured user input tool for Pi coding agent — single-select, multi-select, freeform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@pi-unipi/core": "2.20.
|
|
43
|
+
"@pi-unipi/core": "2.20.4"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/background-tasks",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Background tasks for UniPi — durable shell jobs and delegated background agents with a footer dock",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
13
|
-
"@pi-unipi/core": "2.20.
|
|
13
|
+
"@pi-unipi/core": "2.20.4",
|
|
14
14
|
"turndown": "^7.2.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/btw",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "A pi extension for parallel side conversations with /unipi:btw — part of the Unipi suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "extensions/btw.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@earendil-works/pi-tui": "^0.84.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "2.20.
|
|
40
|
+
"@pi-unipi/core": "2.20.4"
|
|
41
41
|
},
|
|
42
42
|
"pi": {
|
|
43
43
|
"extensions": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/compactor",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Context engine for Pi — zero-LLM compaction, session continuity, sandbox execution, and tool display optimization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "2.20.
|
|
38
|
-
"@pi-unipi/info-screen": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.4",
|
|
38
|
+
"@pi-unipi/info-screen": "2.20.4",
|
|
39
39
|
"@earendil-works/pi-agent-core": "^0.84.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/footer",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Persistent status bar for Unipi — subscribes to UNIPI_EVENTS and renders key stats from all unipi packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "2.20.
|
|
36
|
-
"@pi-unipi/background-tasks": "2.20.
|
|
35
|
+
"@pi-unipi/core": "2.20.4",
|
|
36
|
+
"@pi-unipi/background-tasks": "2.20.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -10,10 +10,9 @@ pi's extension and RPC APIs natively.
|
|
|
10
10
|
╭ Model ───────────────────────────────────────────────────────────────╮
|
|
11
11
|
│/ Type to search │
|
|
12
12
|
│───────────────────────────────────────────────────────────────────────│
|
|
13
|
-
│❭ Fusion
|
|
14
|
-
│· GLM-5.3 Flash ✱
|
|
15
|
-
│·
|
|
16
|
-
│· DeepSeek V4.1 Flash ✱ ▰▱▱▱▱ High │
|
|
13
|
+
│❭ Fusion ← ▰▰▰▱▱ → Medium Lead Fable… ▾ │
|
|
14
|
+
│· GLM-5.3 Flash ✱ ▰▰▰▰▰ Max │
|
|
15
|
+
│· openrouter · deepseek/deepseek-v4.1-flash ▰▰▱▱▱ High │
|
|
17
16
|
│ ↓ more below │
|
|
18
17
|
│ │
|
|
19
18
|
│ ━━━━━●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
|
|
@@ -21,6 +20,7 @@ pi's extension and RPC APIs natively.
|
|
|
21
20
|
│ $10 / 1M $0.25 / 1M $50 / 1M $0.2 / 1M │
|
|
22
21
|
│ Sidekick cached input Sidekick output │
|
|
23
22
|
│ $0.02 / 1M $1.2 / 1M │
|
|
23
|
+
│ Model key openrouter/deepseek/deepseek-v4.1-flash │
|
|
24
24
|
│ │
|
|
25
25
|
│ ✱ New ✱ Promotion ✱ Beta · Pairs frontier intelligence with cost-efficient execution │
|
|
26
26
|
│↑↓ select · tab lead · ←→ effort · ↵ confirm · esc cancel │
|
|
@@ -44,7 +44,16 @@ pi's extension and RPC APIs natively.
|
|
|
44
44
|
- **Price panel**: the highlighted model's blended price is marked on a
|
|
45
45
|
logarithmic red→orange→yellow→green→cyan→blue→violet slider. Fusion shows
|
|
46
46
|
`Input`, `Cached input`, `Output`, `Sidekick input`, `Sidekick cached input`,
|
|
47
|
-
and `Sidekick output
|
|
47
|
+
and `Sidekick output`, and the exact registry key of the highlighted row is
|
|
48
|
+
spelled out (`Model key openrouter/deepseek/deepseek-v4.1-flash`; both the
|
|
49
|
+
lead and sidekick keys on the Fusion row).
|
|
50
|
+
- **Name column & provider**: the name column sizes itself to the widest row
|
|
51
|
+
label (minimum 24 columns) up to the terminal width, and the effort control
|
|
52
|
+
stays right-anchored — so wide terminals show full names. A row only gets a
|
|
53
|
+
dim `provider · ` prefix when its display name is ambiguous: it contains a
|
|
54
|
+
`/` (`deepseek/deepseek-v4.1-flash` reads like a key) or the same friendly
|
|
55
|
+
name is offered by more than one provider. Unique names stay clean, and the
|
|
56
|
+
prefix is never truncated.
|
|
48
57
|
- **Confirm** applies: `pi.setModel`, `pi.setThinkingLevel(effort)`, updates
|
|
49
58
|
MRU + persisted active selection, and shows `Fusion · Lead ◆ Sidekick` in
|
|
50
59
|
the footer. Switching the model through pi's own `/model`/Ctrl+P drops
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/fusion",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Devin-style model picker, fusion presets (lead + sidekick), and Local Fusion runtime for UniPi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "2.20.
|
|
36
|
-
"@pi-unipi/subagents": "2.20.
|
|
35
|
+
"@pi-unipi/core": "2.20.4",
|
|
36
|
+
"@pi-unipi/subagents": "2.20.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
@@ -109,9 +109,39 @@ type Row = { kind: "fusion" } | { kind: "model"; key: ModelKey };
|
|
|
109
109
|
type FusionFocus = "effort" | "lead" | "sidekick";
|
|
110
110
|
|
|
111
111
|
const DEFAULT_VISIBLE_ROWS = 10;
|
|
112
|
-
|
|
112
|
+
/** Minimum width of the name column (the pre-autosize default). */
|
|
113
|
+
const NAME_COL_MIN = 24;
|
|
113
114
|
const MARKER_COL = 2;
|
|
114
115
|
const BAR_SEGMENTS = 5;
|
|
116
|
+
/** Visible columns outside the name: pointer + marker prefix (4) + effort block (19). */
|
|
117
|
+
const FIXED_COLS = 23;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A model needs a provider prefix when its display name alone is ambiguous:
|
|
121
|
+
* it contains a "/" (so it reads like a `provider/id` key), or the same name
|
|
122
|
+
* is offered by more than one provider.
|
|
123
|
+
*/
|
|
124
|
+
function ambiguousNamesOf(models: readonly PickerModel[]): Set<string> {
|
|
125
|
+
const providersByName = new Map<string, Set<string>>();
|
|
126
|
+
for (const m of models) {
|
|
127
|
+
const set = providersByName.get(m.name) ?? new Set<string>();
|
|
128
|
+
set.add(m.provider);
|
|
129
|
+
providersByName.set(m.name, set);
|
|
130
|
+
}
|
|
131
|
+
const out = new Set<string>();
|
|
132
|
+
for (const [name, set] of providersByName) {
|
|
133
|
+
if (set.size > 1) out.add(name);
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function needsProvider(m: PickerModel, ambiguous: ReadonlySet<string>): boolean {
|
|
139
|
+
return m.name.includes("/") || ambiguous.has(m.name);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function labelOf(m: PickerModel, ambiguous: ReadonlySet<string>): string {
|
|
143
|
+
return needsProvider(m, ambiguous) ? `${m.provider} \u00b7 ${m.name}` : m.name;
|
|
144
|
+
}
|
|
115
145
|
|
|
116
146
|
function printable(data: string): string | undefined {
|
|
117
147
|
if (data.length !== 1) return undefined;
|
|
@@ -146,6 +176,9 @@ export class ModelPicker {
|
|
|
146
176
|
private readonly modelsByKey: Map<ModelKey, PickerModel>;
|
|
147
177
|
private readonly state: PickerState;
|
|
148
178
|
private readonly priceRange: { min: number; max: number };
|
|
179
|
+
private readonly ambiguousNames: Set<string>;
|
|
180
|
+
/** Name column sized to the widest row label; capped to the available width at render time. */
|
|
181
|
+
private readonly naturalNameCol: number;
|
|
149
182
|
|
|
150
183
|
private effort: Record<ModelKey, EffortLevel>;
|
|
151
184
|
/** Fusion-row efforts — deliberately NOT stored in the per-model map. */
|
|
@@ -166,6 +199,12 @@ export class ModelPicker {
|
|
|
166
199
|
this.onRenderRequest = options.onRenderRequest;
|
|
167
200
|
this.visibleRows = options.visibleRows ?? DEFAULT_VISIBLE_ROWS;
|
|
168
201
|
this.modelsByKey = new Map(options.state.models.map((m) => [m.key, m]));
|
|
202
|
+
this.ambiguousNames = ambiguousNamesOf(options.state.models);
|
|
203
|
+
const widestLabel = options.state.models.reduce(
|
|
204
|
+
(max, m) => Math.max(max, visibleWidth(labelOf(m, this.ambiguousNames))),
|
|
205
|
+
0,
|
|
206
|
+
);
|
|
207
|
+
this.naturalNameCol = Math.max(NAME_COL_MIN, widestLabel + 2);
|
|
169
208
|
const prices = options.state.models.map((m) => (hasPricing(m.cost) ? blendedPrice(m.cost) : undefined)).filter((p): p is number => p !== undefined && p > 0);
|
|
170
209
|
this.priceRange = { min: prices.length > 0 ? Math.min(...prices) : 0, max: prices.length > 0 ? Math.max(...prices) : 0 };
|
|
171
210
|
this.effort = { ...options.state.effort };
|
|
@@ -416,7 +455,11 @@ export class ModelPicker {
|
|
|
416
455
|
return shortName(m?.name ?? key, max);
|
|
417
456
|
}
|
|
418
457
|
|
|
419
|
-
private
|
|
458
|
+
private isAmbiguous(model: PickerModel): boolean {
|
|
459
|
+
return needsProvider(model, this.ambiguousNames);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
private renderRow(row: Row, highlighted: boolean, width: number, nameCol: number): string {
|
|
420
463
|
const t = this.theme;
|
|
421
464
|
const pointer = highlighted ? t.fg("accent", "❭") : t.fg("dim", "·");
|
|
422
465
|
const disabledFusion = row.kind === "fusion" && !this.fusionAvailable();
|
|
@@ -429,8 +472,14 @@ export class ModelPicker {
|
|
|
429
472
|
: " "
|
|
430
473
|
: this.markerFor(row.key);
|
|
431
474
|
const working = row.kind === "model" && row.key === this.state.currentModelKey;
|
|
432
|
-
const
|
|
433
|
-
|
|
475
|
+
const model = row.kind === "model" ? this.modelsByKey.get(row.key) : undefined;
|
|
476
|
+
// Only ambiguous rows (slash-y names, or names shared across providers) pay
|
|
477
|
+
// the width cost of a dim provider prefix. The name is truncated, never the
|
|
478
|
+
// prefix, so `openrouter · …` always survives.
|
|
479
|
+
const providerPrefix = model !== undefined && this.isAmbiguous(model) ? t.fg("dim", `${model.provider} · `) : "";
|
|
480
|
+
const nameBudget = Math.max(1, nameCol - visibleWidth(providerPrefix) - 1);
|
|
481
|
+
const nameRaw = row.kind === "fusion" ? "Fusion" : this.nameOf(row.key, nameBudget);
|
|
482
|
+
const styled =
|
|
434
483
|
row.kind === "fusion"
|
|
435
484
|
? disabledFusion
|
|
436
485
|
? highlighted
|
|
@@ -444,7 +493,7 @@ export class ModelPicker {
|
|
|
444
493
|
: highlighted
|
|
445
494
|
? t.fg("accent", nameRaw)
|
|
446
495
|
: t.fg("text", nameRaw);
|
|
447
|
-
const
|
|
496
|
+
const name = `${providerPrefix}${styled}`;
|
|
448
497
|
const badge = model?.badge;
|
|
449
498
|
const badgeGlyph = badge === undefined ? "" : ` ${t.fg(badge === "new" ? "success" : badge === "promotion" ? "accent" : "warning", "✱")}`;
|
|
450
499
|
|
|
@@ -458,7 +507,7 @@ export class ModelPicker {
|
|
|
458
507
|
? t.fg("accent", effortLabel(level))
|
|
459
508
|
: t.fg("muted", effortLabel(level));
|
|
460
509
|
|
|
461
|
-
let line = `${pointer} ${marker} ${pad(`${name}${badgeGlyph}`,
|
|
510
|
+
let line = `${pointer} ${marker} ${pad(`${name}${badgeGlyph}`, nameCol)} ${left} ${this.bar(level, !disabledFusion && highlighted)} ${right} ${pad(label, 8)}`;
|
|
462
511
|
|
|
463
512
|
if (row.kind === "fusion") {
|
|
464
513
|
if (disabledFusion) {
|
|
@@ -480,10 +529,10 @@ export class ModelPicker {
|
|
|
480
529
|
return truncateToWidth(line, Math.max(1, width - 1));
|
|
481
530
|
}
|
|
482
531
|
|
|
483
|
-
private renderDropdown(width: number): string[] {
|
|
532
|
+
private renderDropdown(width: number, nameCol: number): string[] {
|
|
484
533
|
const t = this.theme;
|
|
485
534
|
const items = this.dropdownItems();
|
|
486
|
-
const indent = " ".repeat(MARKER_COL +
|
|
535
|
+
const indent = " ".repeat(MARKER_COL + nameCol + 5);
|
|
487
536
|
if (items.length === 0) {
|
|
488
537
|
return [`${indent}${t.fg("warning", `no ${this.focus} models in preset — run /unipi:fusion-preset`)}`];
|
|
489
538
|
}
|
|
@@ -547,7 +596,23 @@ export class ModelPicker {
|
|
|
547
596
|
: !hasPricing(primaryCost);
|
|
548
597
|
const pricing = !disabledFusion && noPricing ? t.fg("dim", " · no pricing data from provider") : "";
|
|
549
598
|
const description = `${badges}${badges.length > 0 ? " " : ""}${desc}${pricing}`;
|
|
550
|
-
|
|
599
|
+
// The row label may be a friendly name; spell out the exact registry key so
|
|
600
|
+
// the highlighted model is unambiguous (`openrouter/deepseek/...`).
|
|
601
|
+
const keys = row.kind === "fusion"
|
|
602
|
+
? [this.lead, this.sidekick].filter((k): k is ModelKey => k !== undefined)
|
|
603
|
+
: primaryKey === undefined
|
|
604
|
+
? []
|
|
605
|
+
: [primaryKey];
|
|
606
|
+
const out = [
|
|
607
|
+
truncateToWidth(` ${head}`, width - 1),
|
|
608
|
+
truncateToWidth(` ${vals}`, width - 1),
|
|
609
|
+
];
|
|
610
|
+
if (keys.length > 0) {
|
|
611
|
+
const keyText = keys.map((k) => t.fg("text", k)).join(t.fg("dim", " · "));
|
|
612
|
+
out.push(truncateToWidth(` ${t.fg("dim", "Model key")} ${keyText}`, width - 1));
|
|
613
|
+
}
|
|
614
|
+
out.push(truncateToWidth(` ${description}`, width - 1));
|
|
615
|
+
return out;
|
|
551
616
|
}
|
|
552
617
|
|
|
553
618
|
private hintLine(row: Row | undefined): string {
|
|
@@ -572,6 +637,10 @@ export class ModelPicker {
|
|
|
572
637
|
private renderBody(width: number): string[] {
|
|
573
638
|
const t = this.theme;
|
|
574
639
|
const rows = this.rows();
|
|
640
|
+
// Give the name column every spare column (the effort control stays
|
|
641
|
+
// right-anchored) but never less than the historical 24.
|
|
642
|
+
const maxNameCol = Math.max(NAME_COL_MIN, width - FIXED_COLS - 1);
|
|
643
|
+
const nameCol = Math.min(this.naturalNameCol, maxNameCol);
|
|
575
644
|
if (this.selected >= rows.length) this.selected = Math.max(0, rows.length - 1);
|
|
576
645
|
const row = rows[this.selected];
|
|
577
646
|
const lines: string[] = [];
|
|
@@ -591,9 +660,9 @@ export class ModelPicker {
|
|
|
591
660
|
const r = rows[i];
|
|
592
661
|
if (r === undefined) continue;
|
|
593
662
|
const highlighted = i === this.selected;
|
|
594
|
-
lines.push(this.renderRow(r, highlighted, width));
|
|
663
|
+
lines.push(this.renderRow(r, highlighted, width, nameCol));
|
|
595
664
|
if (highlighted && r.kind === "fusion" && this.focus !== "effort") {
|
|
596
|
-
lines.push(...this.renderDropdown(width));
|
|
665
|
+
lines.push(...this.renderDropdown(width, nameCol));
|
|
597
666
|
}
|
|
598
667
|
}
|
|
599
668
|
if (end < rows.length) lines.push(t.fg("dim", ` ↓ more below (${String(rows.length - end)})`));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/image",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
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.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.4"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
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.20.
|
|
36
|
+
"@pi-unipi/core": "2.20.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/input-shortcuts",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Keyboard shortcuts for stash/restore, undo/redo, clipboard, and thinking toggle — chord-based overlay system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "2.20.
|
|
36
|
+
"@pi-unipi/core": "2.20.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/kanboard",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Visualization layer for unipi workflow — HTTP server with htmx/Alpine.js UI, modular parsers, TUI overlay, and kanban board",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pi-unipi/core": "2.20.
|
|
42
|
+
"@pi-unipi/core": "2.20.4"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/mcp",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "MCP server management extension for Pi coding agent — browse, add, configure, and use MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test": "npx tsx --test tests/**/*.test.ts"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@pi-unipi/core": "2.20.
|
|
33
|
+
"@pi-unipi/core": "2.20.4"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/memory",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Persistent cross-session memory with MemPalace backend (auto-installed) and SQLite fallback for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"README.md"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pi-unipi/core": "2.20.
|
|
43
|
-
"@pi-unipi/info-screen": "2.20.
|
|
42
|
+
"@pi-unipi/core": "2.20.4",
|
|
43
|
+
"@pi-unipi/info-screen": "2.20.4",
|
|
44
44
|
"js-yaml": "^4.1.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/milestone",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Lifecycle layer for project-level goals — MILESTONES.md tracking, session hooks, auto-sync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "2.20.
|
|
35
|
+
"@pi-unipi/core": "2.20.4"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/notify",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Cross-platform notification extension for Pi — native OS, Gotify, and Telegram notifications for agent lifecycle events",
|
|
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": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.4",
|
|
38
38
|
"node-notifier": "^10.0.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ralph",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Long-running iterative development loops for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"test": "npx tsx --test reminder.test.ts"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "2.20.
|
|
35
|
-
"@pi-unipi/info-screen": "2.20.
|
|
34
|
+
"@pi-unipi/core": "2.20.4",
|
|
35
|
+
"@pi-unipi/info-screen": "2.20.4"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/subagents",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Subagents for UniPi — parallel execution, file locking, workflow integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"test": "npx tsx --test src/__tests__/*.test.ts"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@pi-unipi/core": "2.20.
|
|
12
|
+
"@pi-unipi/core": "2.20.4",
|
|
13
13
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
14
14
|
"acorn": "8.18.0"
|
|
15
15
|
},
|
|
@@ -50836,9 +50836,29 @@ function renderSlider(cells, markerIndex) {
|
|
|
50836
50836
|
|
|
50837
50837
|
// packages/fusion/src/picker.ts
|
|
50838
50838
|
var DEFAULT_VISIBLE_ROWS = 10;
|
|
50839
|
-
var
|
|
50839
|
+
var NAME_COL_MIN = 24;
|
|
50840
50840
|
var MARKER_COL = 2;
|
|
50841
50841
|
var BAR_SEGMENTS = 5;
|
|
50842
|
+
var FIXED_COLS = 23;
|
|
50843
|
+
function ambiguousNamesOf(models) {
|
|
50844
|
+
const providersByName = /* @__PURE__ */ new Map();
|
|
50845
|
+
for (const m of models) {
|
|
50846
|
+
const set = providersByName.get(m.name) ?? /* @__PURE__ */ new Set();
|
|
50847
|
+
set.add(m.provider);
|
|
50848
|
+
providersByName.set(m.name, set);
|
|
50849
|
+
}
|
|
50850
|
+
const out = /* @__PURE__ */ new Set();
|
|
50851
|
+
for (const [name, set] of providersByName) {
|
|
50852
|
+
if (set.size > 1) out.add(name);
|
|
50853
|
+
}
|
|
50854
|
+
return out;
|
|
50855
|
+
}
|
|
50856
|
+
function needsProvider(m, ambiguous) {
|
|
50857
|
+
return m.name.includes("/") || ambiguous.has(m.name);
|
|
50858
|
+
}
|
|
50859
|
+
function labelOf(m, ambiguous) {
|
|
50860
|
+
return needsProvider(m, ambiguous) ? `${m.provider} \xB7 ${m.name}` : m.name;
|
|
50861
|
+
}
|
|
50842
50862
|
function printable(data) {
|
|
50843
50863
|
if (data.length !== 1) return void 0;
|
|
50844
50864
|
const code = data.charCodeAt(0);
|
|
@@ -50867,6 +50887,9 @@ var ModelPicker = class {
|
|
|
50867
50887
|
modelsByKey;
|
|
50868
50888
|
state;
|
|
50869
50889
|
priceRange;
|
|
50890
|
+
ambiguousNames;
|
|
50891
|
+
/** Name column sized to the widest row label; capped to the available width at render time. */
|
|
50892
|
+
naturalNameCol;
|
|
50870
50893
|
effort;
|
|
50871
50894
|
/** Fusion-row efforts — deliberately NOT stored in the per-model map. */
|
|
50872
50895
|
fusionLeadEffort;
|
|
@@ -50885,6 +50908,12 @@ var ModelPicker = class {
|
|
|
50885
50908
|
this.onRenderRequest = options.onRenderRequest;
|
|
50886
50909
|
this.visibleRows = options.visibleRows ?? DEFAULT_VISIBLE_ROWS;
|
|
50887
50910
|
this.modelsByKey = new Map(options.state.models.map((m) => [m.key, m]));
|
|
50911
|
+
this.ambiguousNames = ambiguousNamesOf(options.state.models);
|
|
50912
|
+
const widestLabel = options.state.models.reduce(
|
|
50913
|
+
(max, m) => Math.max(max, visibleWidth23(labelOf(m, this.ambiguousNames))),
|
|
50914
|
+
0
|
|
50915
|
+
);
|
|
50916
|
+
this.naturalNameCol = Math.max(NAME_COL_MIN, widestLabel + 2);
|
|
50888
50917
|
const prices = options.state.models.map((m) => hasPricing(m.cost) ? blendedPrice(m.cost) : void 0).filter((p) => p !== void 0 && p > 0);
|
|
50889
50918
|
this.priceRange = { min: prices.length > 0 ? Math.min(...prices) : 0, max: prices.length > 0 ? Math.max(...prices) : 0 };
|
|
50890
50919
|
this.effort = { ...options.state.effort };
|
|
@@ -51086,15 +51115,21 @@ var ModelPicker = class {
|
|
|
51086
51115
|
const m = this.modelsByKey.get(key);
|
|
51087
51116
|
return shortName(m?.name ?? key, max);
|
|
51088
51117
|
}
|
|
51089
|
-
|
|
51118
|
+
isAmbiguous(model) {
|
|
51119
|
+
return needsProvider(model, this.ambiguousNames);
|
|
51120
|
+
}
|
|
51121
|
+
renderRow(row, highlighted, width, nameCol) {
|
|
51090
51122
|
const t = this.theme;
|
|
51091
51123
|
const pointer = highlighted ? t.fg("accent", "\u276D") : t.fg("dim", "\xB7");
|
|
51092
51124
|
const disabledFusion = row.kind === "fusion" && !this.fusionAvailable();
|
|
51093
51125
|
const marker = row.kind === "fusion" ? !disabledFusion && this.state.active?.kind === "fusion" ? t.fg("success", "\u2713") : " " : this.markerFor(row.key);
|
|
51094
51126
|
const working = row.kind === "model" && row.key === this.state.currentModelKey;
|
|
51095
|
-
const nameRaw = row.kind === "fusion" ? "Fusion" : this.nameOf(row.key, NAME_COL - 1);
|
|
51096
|
-
const name = row.kind === "fusion" ? disabledFusion ? highlighted ? t.fg("muted", t.bold(nameRaw)) : t.fg("dim", nameRaw) : highlighted ? t.fg("accent", t.bold(nameRaw)) : t.fg("text", nameRaw) : working ? t.fg("accent", t.bold(nameRaw)) : highlighted ? t.fg("accent", nameRaw) : t.fg("text", nameRaw);
|
|
51097
51127
|
const model = row.kind === "model" ? this.modelsByKey.get(row.key) : void 0;
|
|
51128
|
+
const providerPrefix = model !== void 0 && this.isAmbiguous(model) ? t.fg("dim", `${model.provider} \xB7 `) : "";
|
|
51129
|
+
const nameBudget = Math.max(1, nameCol - visibleWidth23(providerPrefix) - 1);
|
|
51130
|
+
const nameRaw = row.kind === "fusion" ? "Fusion" : this.nameOf(row.key, nameBudget);
|
|
51131
|
+
const styled = row.kind === "fusion" ? disabledFusion ? highlighted ? t.fg("muted", t.bold(nameRaw)) : t.fg("dim", nameRaw) : highlighted ? t.fg("accent", t.bold(nameRaw)) : t.fg("text", nameRaw) : working ? t.fg("accent", t.bold(nameRaw)) : highlighted ? t.fg("accent", nameRaw) : t.fg("text", nameRaw);
|
|
51132
|
+
const name = `${providerPrefix}${styled}`;
|
|
51098
51133
|
const badge = model?.badge;
|
|
51099
51134
|
const badgeGlyph = badge === void 0 ? "" : ` ${t.fg(badge === "new" ? "success" : badge === "promotion" ? "accent" : "warning", "\u2731")}`;
|
|
51100
51135
|
const level = row.kind === "fusion" ? this.fusionLeadEffort : this.effortFor(row.key);
|
|
@@ -51102,7 +51137,7 @@ var ModelPicker = class {
|
|
|
51102
51137
|
const left = arrowsOn ? t.fg("accent", "\u2190") : " ";
|
|
51103
51138
|
const right = arrowsOn ? t.fg("accent", "\u2192") : " ";
|
|
51104
51139
|
const label = disabledFusion ? t.fg("dim", effortLabel(level)) : highlighted ? t.fg("accent", effortLabel(level)) : t.fg("muted", effortLabel(level));
|
|
51105
|
-
let line = `${pointer} ${marker} ${pad(`${name}${badgeGlyph}`,
|
|
51140
|
+
let line = `${pointer} ${marker} ${pad(`${name}${badgeGlyph}`, nameCol)} ${left} ${this.bar(level, !disabledFusion && highlighted)} ${right} ${pad(label, 8)}`;
|
|
51106
51141
|
if (row.kind === "fusion") {
|
|
51107
51142
|
if (disabledFusion) {
|
|
51108
51143
|
line += ` ${t.fg("dim", "not configured \u2014 run /unipi:fusion-preset")}`;
|
|
@@ -51118,10 +51153,10 @@ var ModelPicker = class {
|
|
|
51118
51153
|
}
|
|
51119
51154
|
return truncateToWidth26(line, Math.max(1, width - 1));
|
|
51120
51155
|
}
|
|
51121
|
-
renderDropdown(width) {
|
|
51156
|
+
renderDropdown(width, nameCol) {
|
|
51122
51157
|
const t = this.theme;
|
|
51123
51158
|
const items = this.dropdownItems();
|
|
51124
|
-
const indent = " ".repeat(MARKER_COL +
|
|
51159
|
+
const indent = " ".repeat(MARKER_COL + nameCol + 5);
|
|
51125
51160
|
if (items.length === 0) {
|
|
51126
51161
|
return [`${indent}${t.fg("warning", `no ${this.focus} models in preset \u2014 run /unipi:fusion-preset`)}`];
|
|
51127
51162
|
}
|
|
@@ -51173,7 +51208,17 @@ var ModelPicker = class {
|
|
|
51173
51208
|
const noPricing = row.kind === "fusion" ? !hasPricing(primaryCost) || !hasPricing(sideCost) : !hasPricing(primaryCost);
|
|
51174
51209
|
const pricing = !disabledFusion && noPricing ? t.fg("dim", " \xB7 no pricing data from provider") : "";
|
|
51175
51210
|
const description = `${badges}${badges.length > 0 ? " " : ""}${desc}${pricing}`;
|
|
51176
|
-
|
|
51211
|
+
const keys = row.kind === "fusion" ? [this.lead, this.sidekick].filter((k) => k !== void 0) : primaryKey === void 0 ? [] : [primaryKey];
|
|
51212
|
+
const out = [
|
|
51213
|
+
truncateToWidth26(` ${head}`, width - 1),
|
|
51214
|
+
truncateToWidth26(` ${vals}`, width - 1)
|
|
51215
|
+
];
|
|
51216
|
+
if (keys.length > 0) {
|
|
51217
|
+
const keyText = keys.map((k) => t.fg("text", k)).join(t.fg("dim", " \xB7 "));
|
|
51218
|
+
out.push(truncateToWidth26(` ${t.fg("dim", "Model key")} ${keyText}`, width - 1));
|
|
51219
|
+
}
|
|
51220
|
+
out.push(truncateToWidth26(` ${description}`, width - 1));
|
|
51221
|
+
return out;
|
|
51177
51222
|
}
|
|
51178
51223
|
hintLine(row) {
|
|
51179
51224
|
const t = this.theme;
|
|
@@ -51195,6 +51240,8 @@ var ModelPicker = class {
|
|
|
51195
51240
|
renderBody(width) {
|
|
51196
51241
|
const t = this.theme;
|
|
51197
51242
|
const rows = this.rows();
|
|
51243
|
+
const maxNameCol = Math.max(NAME_COL_MIN, width - FIXED_COLS - 1);
|
|
51244
|
+
const nameCol = Math.min(this.naturalNameCol, maxNameCol);
|
|
51198
51245
|
if (this.selected >= rows.length) this.selected = Math.max(0, rows.length - 1);
|
|
51199
51246
|
const row = rows[this.selected];
|
|
51200
51247
|
const lines = [];
|
|
@@ -51212,9 +51259,9 @@ var ModelPicker = class {
|
|
|
51212
51259
|
const r = rows[i];
|
|
51213
51260
|
if (r === void 0) continue;
|
|
51214
51261
|
const highlighted = i === this.selected;
|
|
51215
|
-
lines.push(this.renderRow(r, highlighted, width));
|
|
51262
|
+
lines.push(this.renderRow(r, highlighted, width, nameCol));
|
|
51216
51263
|
if (highlighted && r.kind === "fusion" && this.focus !== "effort") {
|
|
51217
|
-
lines.push(...this.renderDropdown(width));
|
|
51264
|
+
lines.push(...this.renderDropdown(width, nameCol));
|
|
51218
51265
|
}
|
|
51219
51266
|
}
|
|
51220
51267
|
if (end < rows.length) lines.push(t.fg("dim", ` \u2193 more below (${String(rows.length - end)})`));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
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": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.4"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/utility",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Utility commands and tools for Pi coding agent — lifecycle, diagnostics, cache, analytics, display, batch execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@pi-unipi/core": "2.20.
|
|
39
|
+
"@pi-unipi/core": "2.20.4"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {},
|
|
42
42
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/web-api",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Web search, read, and summarize tools with provider-based backend selection for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "2.20.
|
|
34
|
+
"@pi-unipi/core": "2.20.4",
|
|
35
35
|
"defuddle": "^0.18.1",
|
|
36
36
|
"linkedom": "^0.18.12",
|
|
37
37
|
"wreq-js": "^2.3.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/workflow",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.4",
|
|
4
4
|
"description": "Structured development workflow commands for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@pi-unipi/core": "2.20.
|
|
33
|
+
"@pi-unipi/core": "2.20.4"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-ai": "^0.84.0",
|