@victor-software-house/pi-openai-proxy 4.2.2 → 4.2.3
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/extensions/proxy.ts +168 -30
- package/package.json +1 -1
package/extensions/proxy.ts
CHANGED
|
@@ -33,6 +33,9 @@ import {
|
|
|
33
33
|
import {
|
|
34
34
|
type Component,
|
|
35
35
|
Container,
|
|
36
|
+
fuzzyFilter,
|
|
37
|
+
getKeybindings,
|
|
38
|
+
Input,
|
|
36
39
|
type SettingItem,
|
|
37
40
|
SettingsList,
|
|
38
41
|
Text,
|
|
@@ -550,46 +553,181 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
550
553
|
_currentValue: string,
|
|
551
554
|
done: (selectedValue?: string) => void,
|
|
552
555
|
): Component {
|
|
553
|
-
|
|
556
|
+
interface ModelEntry {
|
|
557
|
+
canonical: string;
|
|
558
|
+
provider: string;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const models: ModelEntry[] = getAvailableModels().map((m) => ({
|
|
562
|
+
canonical: `${m.provider}/${m.id}`,
|
|
563
|
+
provider: m.provider,
|
|
564
|
+
}));
|
|
565
|
+
|
|
554
566
|
const selected = new Set(config.customModels);
|
|
567
|
+
let selectedIndex = 0;
|
|
568
|
+
const searchInput = new Input();
|
|
569
|
+
let filtered: ModelEntry[] = models;
|
|
570
|
+
const maxVisible = 20;
|
|
571
|
+
|
|
572
|
+
// Precompute provider boundary indices in the full list
|
|
573
|
+
function providerBoundaries(list: ModelEntry[]): {
|
|
574
|
+
firstOf: Map<string, number>;
|
|
575
|
+
lastOf: Map<string, number>;
|
|
576
|
+
} {
|
|
577
|
+
const firstOf = new Map<string, number>();
|
|
578
|
+
const lastOf = new Map<string, number>();
|
|
579
|
+
for (let i = 0; i < list.length; i++) {
|
|
580
|
+
const entry = list[i];
|
|
581
|
+
if (entry === undefined) continue;
|
|
582
|
+
if (!firstOf.has(entry.provider)) firstOf.set(entry.provider, i);
|
|
583
|
+
lastOf.set(entry.provider, i);
|
|
584
|
+
}
|
|
585
|
+
return { firstOf, lastOf };
|
|
586
|
+
}
|
|
555
587
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
});
|
|
588
|
+
function jumpProvider(direction: "prev" | "next"): void {
|
|
589
|
+
if (filtered.length === 0) return;
|
|
590
|
+
const { firstOf, lastOf } = providerBoundaries(filtered);
|
|
591
|
+
const current = filtered[selectedIndex];
|
|
592
|
+
if (current === undefined) return;
|
|
593
|
+
|
|
594
|
+
const providers = [...firstOf.keys()]; // insertion-order = list order
|
|
595
|
+
const provIdx = providers.indexOf(current.provider);
|
|
565
596
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
getSettingsListTheme(),
|
|
570
|
-
(id: string, newValue: string) => {
|
|
571
|
-
if (newValue === "[x]") {
|
|
572
|
-
selected.add(id);
|
|
597
|
+
if (direction === "prev") {
|
|
598
|
+
if (provIdx <= 0) {
|
|
599
|
+
selectedIndex = 0;
|
|
573
600
|
} else {
|
|
574
|
-
|
|
601
|
+
const prevProvider = providers[provIdx - 1];
|
|
602
|
+
if (prevProvider !== undefined) {
|
|
603
|
+
selectedIndex = lastOf.get(prevProvider) ?? 0;
|
|
604
|
+
}
|
|
575
605
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
606
|
+
} else {
|
|
607
|
+
if (provIdx >= providers.length - 1) {
|
|
608
|
+
selectedIndex = filtered.length - 1;
|
|
609
|
+
} else {
|
|
610
|
+
const nextProvider = providers[provIdx + 1];
|
|
611
|
+
if (nextProvider !== undefined) {
|
|
612
|
+
selectedIndex = firstOf.get(nextProvider) ?? filtered.length - 1;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function toggle(idx: number): void {
|
|
619
|
+
const entry = filtered[idx];
|
|
620
|
+
if (entry === undefined) return;
|
|
621
|
+
if (selected.has(entry.canonical)) {
|
|
622
|
+
selected.delete(entry.canonical);
|
|
623
|
+
} else {
|
|
624
|
+
selected.add(entry.canonical);
|
|
625
|
+
}
|
|
626
|
+
config = { ...config, customModels: [...selected] };
|
|
627
|
+
saveConfigToFile(config);
|
|
628
|
+
config = loadConfigFromFile();
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function applyFilter(query: string): void {
|
|
632
|
+
if (query === "") {
|
|
633
|
+
filtered = models;
|
|
634
|
+
} else {
|
|
635
|
+
filtered = fuzzyFilter(models, query, (m) => m.canonical);
|
|
636
|
+
}
|
|
637
|
+
selectedIndex = 0;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const theme = getSettingsListTheme();
|
|
583
641
|
|
|
584
642
|
return {
|
|
585
643
|
render(width: number): string[] {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
644
|
+
const lines: string[] = [];
|
|
645
|
+
lines.push(...searchInput.render(width));
|
|
646
|
+
lines.push("");
|
|
647
|
+
|
|
648
|
+
if (filtered.length === 0) {
|
|
649
|
+
lines.push(theme.hint(" No matching models"));
|
|
650
|
+
lines.push("");
|
|
651
|
+
lines.push(theme.hint(" Type to filter | Left/Right: jump provider | Esc: done"));
|
|
652
|
+
return lines;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const start = Math.max(
|
|
656
|
+
0,
|
|
657
|
+
Math.min(selectedIndex - Math.floor(maxVisible / 2), filtered.length - maxVisible),
|
|
658
|
+
);
|
|
659
|
+
const end = Math.min(start + maxVisible, filtered.length);
|
|
660
|
+
|
|
661
|
+
let lastProvider = "";
|
|
662
|
+
for (let i = start; i < end; i++) {
|
|
663
|
+
const entry = filtered[i];
|
|
664
|
+
if (entry === undefined) continue;
|
|
665
|
+
|
|
666
|
+
// Provider separator
|
|
667
|
+
if (entry.provider !== lastProvider) {
|
|
668
|
+
if (lastProvider !== "") lines.push("");
|
|
669
|
+
lastProvider = entry.provider;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const check = selected.has(entry.canonical) ? "[x]" : "[ ]";
|
|
673
|
+
const cursor = i === selectedIndex ? theme.cursor : " ";
|
|
674
|
+
const label =
|
|
675
|
+
i === selectedIndex
|
|
676
|
+
? theme.label(`${check} ${entry.canonical}`, true)
|
|
677
|
+
: theme.label(`${check} ${entry.canonical}`, false);
|
|
678
|
+
lines.push(`${cursor}${label}`.slice(0, width));
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
if (start > 0 || end < filtered.length) {
|
|
682
|
+
lines.push(theme.hint(` (${String(selectedIndex + 1)}/${String(filtered.length)})`));
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
lines.push("");
|
|
686
|
+
lines.push(
|
|
687
|
+
theme.description(` ${String(selected.size)} of ${String(models.length)} selected`),
|
|
688
|
+
);
|
|
689
|
+
lines.push("");
|
|
690
|
+
lines.push(
|
|
691
|
+
theme.hint(" Type to filter | Space: toggle | Left/Right: jump provider | Esc: done"),
|
|
692
|
+
);
|
|
693
|
+
return lines;
|
|
590
694
|
},
|
|
695
|
+
invalidate(): void {},
|
|
591
696
|
handleInput(data: string): void {
|
|
592
|
-
|
|
697
|
+
const kb = getKeybindings();
|
|
698
|
+
|
|
699
|
+
if (kb.matches(data, "tui.select.cancel")) {
|
|
700
|
+
done(`${String(selected.size)} selected`);
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
if (filtered.length === 0) {
|
|
704
|
+
// Still allow typing to refine filter
|
|
705
|
+
const sanitized = data.replace(/ /g, "");
|
|
706
|
+
if (sanitized !== "") {
|
|
707
|
+
searchInput.handleInput(sanitized);
|
|
708
|
+
applyFilter(searchInput.getValue());
|
|
709
|
+
}
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
713
|
+
selectedIndex = selectedIndex <= 0 ? filtered.length - 1 : selectedIndex - 1;
|
|
714
|
+
} else if (kb.matches(data, "tui.select.down")) {
|
|
715
|
+
selectedIndex = selectedIndex >= filtered.length - 1 ? 0 : selectedIndex + 1;
|
|
716
|
+
} else if (data === "\x1B[D") {
|
|
717
|
+
// Left arrow: previous provider
|
|
718
|
+
jumpProvider("prev");
|
|
719
|
+
} else if (data === "\x1B[C") {
|
|
720
|
+
// Right arrow: next provider
|
|
721
|
+
jumpProvider("next");
|
|
722
|
+
} else if (kb.matches(data, "tui.select.confirm") || data === " ") {
|
|
723
|
+
toggle(selectedIndex);
|
|
724
|
+
} else {
|
|
725
|
+
const sanitized = data.replace(/ /g, "");
|
|
726
|
+
if (sanitized !== "") {
|
|
727
|
+
searchInput.handleInput(sanitized);
|
|
728
|
+
applyFilter(searchInput.getValue());
|
|
729
|
+
}
|
|
730
|
+
}
|
|
593
731
|
},
|
|
594
732
|
};
|
|
595
733
|
}
|
package/package.json
CHANGED