pi-hide-providers 0.1.4 → 0.1.6
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 +1 -1
- package/hide-providers.ts +0 -7
- package/package.json +11 -12
- package/src/provider-selector.ts +70 -31
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Pi has `enabledModels` in `settings.json` as an allowlist, but maintaining it ma
|
|
|
30
30
|
- The `/model` selector, `Ctrl+P` cycling, `--list-models`, and session restoration all see only visible models
|
|
31
31
|
- `/hide-models reset` unpatches the registry — all models return immediately
|
|
32
32
|
- Changes via `/hide-models add` and `/hide-models remove` take effect immediately (no reload needed)
|
|
33
|
-
- Interactive `/hide-models` TUI lists visible
|
|
33
|
+
- Interactive `/hide-models` TUI lists visible models first in user-toggle order, then hidden models in their original registry order, and keeps the cursor at the same index after each toggle — matching pi core's `/scoped-models` UX
|
|
34
34
|
- `/hide-models` subcommands for adding, removing, and inspecting rules
|
|
35
35
|
|
|
36
36
|
No `settings.json` is modified. No 250+ entry explosion. No allowlist semantics.
|
package/hide-providers.ts
CHANGED
|
@@ -159,13 +159,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
159
159
|
|
|
160
160
|
if (currentRules.length > 0) {
|
|
161
161
|
patchRegistry(ctx.modelRegistry as unknown as PatchedRegistry, () => currentRules);
|
|
162
|
-
|
|
163
|
-
if (ctx.hasUI) {
|
|
164
|
-
ctx.ui.notify(
|
|
165
|
-
`pi-hide-providers: ${currentRules.length} rule(s) active — getAvailable/getAll/find patched to filter hidden models`,
|
|
166
|
-
"info",
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
162
|
}
|
|
170
163
|
});
|
|
171
164
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-hide-providers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Hide providers and models from pi's model selector — filter the /model list and Ctrl+P cycling via a configurable blocklist",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Tom X Nguyen",
|
|
@@ -30,26 +30,25 @@
|
|
|
30
30
|
"src/",
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
|
-
"scripts": {
|
|
34
|
-
"test": "vitest run",
|
|
35
|
-
"test:watch": "vitest",
|
|
36
|
-
"test:coverage": "vitest run --coverage",
|
|
37
|
-
"typecheck": "tsc --noEmit",
|
|
38
|
-
"lint:dead": "knip --no-gitignore"
|
|
39
|
-
},
|
|
40
33
|
"devDependencies": {
|
|
41
34
|
"@earendil-works/pi-coding-agent": "0.79.4",
|
|
35
|
+
"@earendil-works/pi-tui": "0.79.4",
|
|
42
36
|
"@types/node": "25.9.1",
|
|
43
37
|
"@vitest/coverage-v8": "4.1.7",
|
|
44
38
|
"knip": "6.14.1",
|
|
45
39
|
"typescript": "6.0.3",
|
|
46
|
-
"vitest": "4.1.7"
|
|
47
|
-
"@earendil-works/pi-tui": "0.79.4"
|
|
40
|
+
"vitest": "4.1.7"
|
|
48
41
|
},
|
|
49
42
|
"pi": {
|
|
50
43
|
"extensions": [
|
|
51
44
|
"./hide-providers.ts"
|
|
52
45
|
]
|
|
53
46
|
},
|
|
54
|
-
"
|
|
55
|
-
|
|
47
|
+
"scripts": {
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"test:watch": "vitest",
|
|
50
|
+
"test:coverage": "vitest run --coverage",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"lint:dead": "knip --no-gitignore"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/provider-selector.ts
CHANGED
|
@@ -61,6 +61,10 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
61
61
|
// model data
|
|
62
62
|
private allItems: DisplayItem[] = [];
|
|
63
63
|
|
|
64
|
+
// visible model fullIds in the order they were unhidden (mirrors pi core's
|
|
65
|
+
// enabledIds cycle order in the scoped models selector)
|
|
66
|
+
private visibleIds: string[] = [];
|
|
67
|
+
|
|
64
68
|
// current hide rules
|
|
65
69
|
private hiddenRules: HideRule[] = [];
|
|
66
70
|
|
|
@@ -93,7 +97,7 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
93
97
|
this.done = done;
|
|
94
98
|
this.hiddenRules = deduplicateRules(currentRules);
|
|
95
99
|
|
|
96
|
-
// Build display items
|
|
100
|
+
// Build display items in the original registry order.
|
|
97
101
|
for (const m of allModels) {
|
|
98
102
|
this.allItems.push({
|
|
99
103
|
fullId: `${m.provider}/${m.id}`,
|
|
@@ -103,9 +107,12 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
103
107
|
hidden: isHidden(currentRules, m.provider, m.id),
|
|
104
108
|
});
|
|
105
109
|
}
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
this.
|
|
110
|
+
// Track visible models in original order initially; toggle order changes
|
|
111
|
+
// during the session, matching pi core's /scoped-models behavior.
|
|
112
|
+
this.visibleIds = this.allItems
|
|
113
|
+
.filter((i) => !i.hidden)
|
|
114
|
+
.map((i) => i.fullId);
|
|
115
|
+
this.filteredItems = this.buildItems();
|
|
109
116
|
|
|
110
117
|
this.searchInput = new Input();
|
|
111
118
|
this.listContainer = new Container();
|
|
@@ -271,27 +278,24 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
271
278
|
private refresh(): void {
|
|
272
279
|
const query = this.searchInput.getValue();
|
|
273
280
|
|
|
274
|
-
// Recompute hidden status
|
|
275
|
-
//
|
|
276
|
-
//
|
|
281
|
+
// Recompute hidden status, then rebuild the list in pi core's order:
|
|
282
|
+
// visible models in user-toggle order, followed by hidden models in
|
|
283
|
+
// original registry order.
|
|
277
284
|
for (const item of this.allItems) {
|
|
278
285
|
item.hidden = isHidden(this.hiddenRules, item.provider, item.modelId);
|
|
279
286
|
}
|
|
280
|
-
this.sortItems(this.allItems);
|
|
281
287
|
|
|
288
|
+
const items = this.buildItems();
|
|
282
289
|
this.filteredItems = query
|
|
283
290
|
? fuzzyFilter(
|
|
284
|
-
|
|
291
|
+
items,
|
|
285
292
|
query,
|
|
286
293
|
(i) => `${i.provider} ${i.modelId} ${i.provider}/${i.modelId} ${i.modelName}`,
|
|
287
294
|
)
|
|
288
|
-
:
|
|
289
|
-
|
|
290
|
-
// Ensure filtered results also honor enabled-first ordering.
|
|
291
|
-
this.sortItems(this.filteredItems);
|
|
295
|
+
: items;
|
|
292
296
|
|
|
293
|
-
// Keep the cursor at the same
|
|
294
|
-
//
|
|
297
|
+
// Keep the cursor at the same numeric index after re-sorting. The selected
|
|
298
|
+
// model may change, matching pi core's /scoped-models behavior.
|
|
295
299
|
this.selectedIndex = Math.min(
|
|
296
300
|
this.selectedIndex,
|
|
297
301
|
Math.max(0, this.filteredItems.length - 1),
|
|
@@ -300,27 +304,30 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
300
304
|
this.updateList();
|
|
301
305
|
}
|
|
302
306
|
|
|
303
|
-
/**
|
|
304
|
-
* models
|
|
305
|
-
*
|
|
306
|
-
* provider to the top.
|
|
307
|
+
/** Build the display order used by pi core's scoped models selector:
|
|
308
|
+
* visible models first in the order they were unhidden, then hidden models
|
|
309
|
+
* in their original registry order.
|
|
307
310
|
*/
|
|
308
|
-
private
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
private buildItems(): DisplayItem[] {
|
|
312
|
+
const visibleSet = new Set(this.visibleIds);
|
|
313
|
+
const result: DisplayItem[] = [];
|
|
314
|
+
|
|
315
|
+
// Visible models in user-toggle order.
|
|
316
|
+
for (const fullId of this.visibleIds) {
|
|
317
|
+
const item = this.allItems.find((i) => i.fullId === fullId);
|
|
318
|
+
if (item && !item.hidden) {
|
|
319
|
+
result.push(item);
|
|
313
320
|
}
|
|
321
|
+
}
|
|
314
322
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
|
|
323
|
+
// Hidden models in original registry order.
|
|
324
|
+
for (const item of this.allItems) {
|
|
325
|
+
if (item.hidden && !visibleSet.has(item.fullId)) {
|
|
326
|
+
result.push(item);
|
|
319
327
|
}
|
|
328
|
+
}
|
|
320
329
|
|
|
321
|
-
|
|
322
|
-
return a.modelId.localeCompare(b.modelId);
|
|
323
|
-
});
|
|
330
|
+
return result;
|
|
324
331
|
}
|
|
325
332
|
|
|
326
333
|
private updateList(): void {
|
|
@@ -433,12 +440,20 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
433
440
|
!(r.provider === item.provider && r.model === item.modelId),
|
|
434
441
|
);
|
|
435
442
|
}
|
|
443
|
+
|
|
444
|
+
// Newly visible model goes to the end of the visible order (pi core).
|
|
445
|
+
if (!this.visibleIds.includes(item.fullId)) {
|
|
446
|
+
this.visibleIds.push(item.fullId);
|
|
447
|
+
}
|
|
436
448
|
} else {
|
|
437
449
|
// Add a rule for this specific model
|
|
438
450
|
this.hiddenRules = deduplicateRules([
|
|
439
451
|
...this.hiddenRules,
|
|
440
452
|
{ provider: item.provider, model: item.modelId },
|
|
441
453
|
]);
|
|
454
|
+
|
|
455
|
+
// Remove from the visible order.
|
|
456
|
+
this.visibleIds = this.visibleIds.filter((id) => id !== item.fullId);
|
|
442
457
|
}
|
|
443
458
|
this.hasChanges = true;
|
|
444
459
|
this.refresh();
|
|
@@ -456,12 +471,25 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
456
471
|
this.hiddenRules = this.hiddenRules.filter(
|
|
457
472
|
(r) => r.provider !== provider,
|
|
458
473
|
);
|
|
474
|
+
|
|
475
|
+
// Append newly visible provider models to the end of the visible order
|
|
476
|
+
// in original registry order (pi core).
|
|
477
|
+
const providerIds = providerItems.map((i) => i.fullId);
|
|
478
|
+
this.visibleIds = [
|
|
479
|
+
...this.visibleIds,
|
|
480
|
+
...providerIds.filter((id) => !this.visibleIds.includes(id)),
|
|
481
|
+
];
|
|
459
482
|
} else {
|
|
460
483
|
// Hide all — add a single provider-level rule
|
|
461
484
|
this.hiddenRules = deduplicateRules([
|
|
462
485
|
...this.hiddenRules,
|
|
463
486
|
{ provider },
|
|
464
487
|
]);
|
|
488
|
+
|
|
489
|
+
// Remove provider models from the visible order.
|
|
490
|
+
this.visibleIds = this.visibleIds.filter(
|
|
491
|
+
(id) => !providerItems.some((i) => i.fullId === id),
|
|
492
|
+
);
|
|
465
493
|
}
|
|
466
494
|
this.hasChanges = true;
|
|
467
495
|
this.refresh();
|
|
@@ -496,6 +524,10 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
496
524
|
}
|
|
497
525
|
}
|
|
498
526
|
}
|
|
527
|
+
|
|
528
|
+
// Remove hidden models from the visible order.
|
|
529
|
+
const hiddenFullIds = new Set(items.map((i) => i.fullId));
|
|
530
|
+
this.visibleIds = this.visibleIds.filter((id) => !hiddenFullIds.has(id));
|
|
499
531
|
}
|
|
500
532
|
|
|
501
533
|
/** Remove hide rules for the given items. */
|
|
@@ -548,6 +580,13 @@ export class HideProviderSelectorComponent implements Component {
|
|
|
548
580
|
}
|
|
549
581
|
}
|
|
550
582
|
}
|
|
583
|
+
|
|
584
|
+
// Append newly visible models to the end of the visible order (pi core).
|
|
585
|
+
for (const item of items) {
|
|
586
|
+
if (!this.visibleIds.includes(item.fullId)) {
|
|
587
|
+
this.visibleIds.push(item.fullId);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
551
590
|
}
|
|
552
591
|
|
|
553
592
|
/** Close and pass results to `done`. */
|