@tychenjiajun/pi-voice 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/package.json +1 -1
- package/src/model-picker.ts +17 -8
package/README.md
CHANGED
|
@@ -116,6 +116,13 @@ When FFmpeg is unavailable, `transcribe_file` reports platform-specific guidance
|
|
|
116
116
|
|
|
117
117
|
## Changelog
|
|
118
118
|
|
|
119
|
+
### 0.6.0
|
|
120
|
+
|
|
121
|
+
**Changed — Fuzzy model search**
|
|
122
|
+
|
|
123
|
+
- The model picker now uses the same fuzzy filter Pi's own model selector uses (`fuzzyFilter` from `@earendil-works/pi-tui`), so typing partial or abbreviated names finds matches that exact substring search could not — e.g. `wspr` matches `whisper-medium`, and `pkrt` matches `parakeet`. Results within each section are also sorted by match quality, putting the best-scoring model at the top.
|
|
124
|
+
- While a search query is active the cursor stays on the best match instead of following a model that may have moved or dropped out of the results, matching Pi's model selector interaction.
|
|
125
|
+
|
|
119
126
|
### 0.5.0
|
|
120
127
|
|
|
121
128
|
**Changed — Exclusive local / remote modes (no fallback)**
|
package/package.json
CHANGED
package/src/model-picker.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "@earendil-works/pi-tui";
|
|
15
15
|
import {
|
|
16
16
|
CATALOG_MODELS,
|
|
17
|
+
catalogModelSearchText,
|
|
17
18
|
canonicalLanguage,
|
|
18
19
|
languageIdentity,
|
|
19
20
|
displayLanguage,
|
|
@@ -32,7 +33,6 @@ import {
|
|
|
32
33
|
import {
|
|
33
34
|
MANUAL_LANGUAGE_TAG,
|
|
34
35
|
ON_DISK_LABEL,
|
|
35
|
-
matchesCatalogSearch,
|
|
36
36
|
modelDetailText,
|
|
37
37
|
modelTableLayout,
|
|
38
38
|
modelTableRow,
|
|
@@ -576,14 +576,19 @@ export class CatalogModelPicker extends Container implements Focusable {
|
|
|
576
576
|
|
|
577
577
|
// The sectioned list: models on disk first, then the ranked catalog with
|
|
578
578
|
// each of them left out, so a model is listed once. A search filters each
|
|
579
|
-
// section in place
|
|
580
|
-
// while a query is on they are a section of their
|
|
581
|
-
// says why it was folded.
|
|
579
|
+
// section in place by fuzzy match quality (best matches first) and reaches
|
|
580
|
+
// the folded models too: while a query is on they are a section of their
|
|
581
|
+
// own, so a match there says why it was folded.
|
|
582
582
|
private buildRows(query: string): ListRow[] {
|
|
583
583
|
const downloaded = this.downloadedModels();
|
|
584
584
|
const onDisk = new Set(downloaded.map((model) => model.id));
|
|
585
|
+
// fuzzyFilter is the same matcher Pi's own model selector uses: each
|
|
586
|
+
// token's characters must appear in order but not consecutively, so typing
|
|
587
|
+
// "wspr" finds "whisper". It also re-sorts each section by match quality so
|
|
588
|
+
// the best-scoring match is at the top, which makes a 1000+ model catalog
|
|
589
|
+
// navigable by typing rather than scrolling.
|
|
585
590
|
const matching = (models: readonly CatalogModel[]) =>
|
|
586
|
-
query ? models
|
|
591
|
+
query ? fuzzyFilter([...models], query, catalogModelSearchText) : models;
|
|
587
592
|
const keep = (models: readonly CatalogModel[]) =>
|
|
588
593
|
matching(models).filter((model) => !onDisk.has(model.id));
|
|
589
594
|
const rows: ListRow[] = [];
|
|
@@ -688,9 +693,13 @@ export class CatalogModelPicker extends Container implements Focusable {
|
|
|
688
693
|
this.body.addChild(this.footer);
|
|
689
694
|
|
|
690
695
|
const query = this.search.getValue().trim();
|
|
691
|
-
// Selecting a model reorders the Downloaded section, so the cursor
|
|
692
|
-
//
|
|
693
|
-
|
|
696
|
+
// Selecting a model reorders the Downloaded section, so the cursor follows
|
|
697
|
+
// the highlighted model rather than its old row number — but only when not
|
|
698
|
+
// searching. While a query is on, handleInput resets selectedIndex to 0
|
|
699
|
+
// on each keystroke, and fuzzyFilter re-sorts every section by match
|
|
700
|
+
// quality, so the best match should stay at the top rather than chasing a
|
|
701
|
+
// model that may have moved or dropped out of the results.
|
|
702
|
+
const highlightedId = query ? undefined : this.highlightedModel()?.id;
|
|
694
703
|
this.rows = this.buildRows(query);
|
|
695
704
|
this.filtered = this.rows.flatMap((row) => (row.type === "model" ? [row.model] : []));
|
|
696
705
|
const followed = highlightedId === undefined
|