@aiwayds/dsh-tui-pi 2.24.0 → 2.25.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/lib/model-list.d.ts +22 -7
- package/lib/model-list.js +34 -10
- package/lib/model-list.js.map +1 -1
- package/package.json +1 -1
package/lib/model-list.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure model-list assembly for the /model picker — favorites pinned on top,
|
|
3
|
-
* hidden models in a dim section at the bottom, everything between.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* hidden models in a dim section at the bottom, everything between. Every
|
|
4
|
+
* section lists its models aggregated under their provider (providers
|
|
5
|
+
* alphabetical, models alphabetical within a provider). No TUI imports:
|
|
6
|
+
* every function here is plain data-in/data-out, so the ordering, filtering
|
|
7
|
+
* and toggle semantics stay unit-testable without a terminal
|
|
6
8
|
* (test/model-list.test.mjs).
|
|
7
9
|
*/
|
|
8
10
|
/** One listed model route (provider + model id + display name). */
|
|
@@ -30,6 +32,15 @@ export type ModelRow = {
|
|
|
30
32
|
};
|
|
31
33
|
/** Case-insensitive substring match of `query` against name/id/provider. */
|
|
32
34
|
export declare function matchesModelFilter(model: ListedModel, query: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Display order of every picker section: providers aggregate alphabetically,
|
|
37
|
+
* and within a provider models sort by the label the MODEL column shows
|
|
38
|
+
* (name, falling back to id) with the id as the tiebreak. The listing
|
|
39
|
+
* arrives from pickModel as a Promise.all race across providers, so the
|
|
40
|
+
* input order interleaves providers by resolve speed — this comparator is
|
|
41
|
+
* what makes the rows deterministic.
|
|
42
|
+
*/
|
|
43
|
+
export declare function compareListedModels(a: ListedModel, b: ListedModel): number;
|
|
33
44
|
/**
|
|
34
45
|
* Toggle `key` in `list`: remove when present, append when absent (join
|
|
35
46
|
* order = favorite order). Returns a new array; the input is never mutated.
|
|
@@ -48,14 +59,18 @@ export declare function narrowStringList(value: unknown): string[];
|
|
|
48
59
|
/**
|
|
49
60
|
* Assemble the picker rows, top to bottom:
|
|
50
61
|
*
|
|
51
|
-
* 1. Favorites (`section: 'favorite'`, ★ prefix applied by renderCell)
|
|
52
|
-
*
|
|
62
|
+
* 1. Favorites (`section: 'favorite'`, ★ prefix applied by renderCell) —
|
|
63
|
+
* display order is the shared provider-grouped alphabetical order, not
|
|
64
|
+
* the join order of the persisted `favoriteModels` list (persistence
|
|
65
|
+
* keeps join order; only the rendering sorts). A favorited model is
|
|
66
|
+
* removed from every other section;
|
|
53
67
|
* 2. one full-width divider row — only when at least one favorite is visible
|
|
54
68
|
* AND something follows it;
|
|
55
|
-
* 3. the remaining models (`section: 'normal'`) in
|
|
69
|
+
* 3. the remaining models (`section: 'normal'`) in the same order;
|
|
56
70
|
* 4. the Hidden section — only without an active filter and when non-empty:
|
|
57
71
|
* a `hiddenHeader` row carrying the count, then the hidden models
|
|
58
|
-
* (`section: 'hidden'`, rendered dim) that are not also favorited
|
|
72
|
+
* (`section: 'hidden'`, rendered dim) that are not also favorited,
|
|
73
|
+
* likewise in the shared order.
|
|
59
74
|
*
|
|
60
75
|
* An active `filter` keeps the pinned structure but leaves only matching
|
|
61
76
|
* models per section; stale keys in `favorites`/`hidden` (models no longer
|
package/lib/model-list.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure model-list assembly for the /model picker — favorites pinned on top,
|
|
3
|
-
* hidden models in a dim section at the bottom, everything between.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* hidden models in a dim section at the bottom, everything between. Every
|
|
4
|
+
* section lists its models aggregated under their provider (providers
|
|
5
|
+
* alphabetical, models alphabetical within a provider). No TUI imports:
|
|
6
|
+
* every function here is plain data-in/data-out, so the ordering, filtering
|
|
7
|
+
* and toggle semantics stay unit-testable without a terminal
|
|
6
8
|
* (test/model-list.test.mjs).
|
|
7
9
|
*/
|
|
8
10
|
/** Composite settings key of a model: `${provider}/${id}`. */
|
|
@@ -18,6 +20,22 @@ export function matchesModelFilter(model, query) {
|
|
|
18
20
|
|| model.id.toLowerCase().includes(needle)
|
|
19
21
|
|| model.provider.toLowerCase().includes(needle));
|
|
20
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Display order of every picker section: providers aggregate alphabetically,
|
|
25
|
+
* and within a provider models sort by the label the MODEL column shows
|
|
26
|
+
* (name, falling back to id) with the id as the tiebreak. The listing
|
|
27
|
+
* arrives from pickModel as a Promise.all race across providers, so the
|
|
28
|
+
* input order interleaves providers by resolve speed — this comparator is
|
|
29
|
+
* what makes the rows deterministic.
|
|
30
|
+
*/
|
|
31
|
+
export function compareListedModels(a, b) {
|
|
32
|
+
const byProvider = a.provider.localeCompare(b.provider);
|
|
33
|
+
if (byProvider !== 0)
|
|
34
|
+
return byProvider;
|
|
35
|
+
const labelA = a.name === '' ? a.id : a.name;
|
|
36
|
+
const labelB = b.name === '' ? b.id : b.name;
|
|
37
|
+
return labelA.localeCompare(labelB) || a.id.localeCompare(b.id);
|
|
38
|
+
}
|
|
21
39
|
/**
|
|
22
40
|
* Toggle `key` in `list`: remove when present, append when absent (join
|
|
23
41
|
* order = favorite order). Returns a new array; the input is never mutated.
|
|
@@ -44,33 +62,39 @@ export function narrowStringList(value) {
|
|
|
44
62
|
/**
|
|
45
63
|
* Assemble the picker rows, top to bottom:
|
|
46
64
|
*
|
|
47
|
-
* 1. Favorites (`section: 'favorite'`, ★ prefix applied by renderCell)
|
|
48
|
-
*
|
|
65
|
+
* 1. Favorites (`section: 'favorite'`, ★ prefix applied by renderCell) —
|
|
66
|
+
* display order is the shared provider-grouped alphabetical order, not
|
|
67
|
+
* the join order of the persisted `favoriteModels` list (persistence
|
|
68
|
+
* keeps join order; only the rendering sorts). A favorited model is
|
|
69
|
+
* removed from every other section;
|
|
49
70
|
* 2. one full-width divider row — only when at least one favorite is visible
|
|
50
71
|
* AND something follows it;
|
|
51
|
-
* 3. the remaining models (`section: 'normal'`) in
|
|
72
|
+
* 3. the remaining models (`section: 'normal'`) in the same order;
|
|
52
73
|
* 4. the Hidden section — only without an active filter and when non-empty:
|
|
53
74
|
* a `hiddenHeader` row carrying the count, then the hidden models
|
|
54
|
-
* (`section: 'hidden'`, rendered dim) that are not also favorited
|
|
75
|
+
* (`section: 'hidden'`, rendered dim) that are not also favorited,
|
|
76
|
+
* likewise in the shared order.
|
|
55
77
|
*
|
|
56
78
|
* An active `filter` keeps the pinned structure but leaves only matching
|
|
57
79
|
* models per section; stale keys in `favorites`/`hidden` (models no longer
|
|
58
80
|
* listed by any provider) are skipped silently.
|
|
59
81
|
*/
|
|
60
82
|
export function buildModelRows(models, favorites, hidden, filter = '') {
|
|
61
|
-
const
|
|
83
|
+
const sorted = [...models].sort(compareListedModels);
|
|
84
|
+
const byKey = new Map(sorted.map(model => [modelKey(model), model]));
|
|
62
85
|
const favKeys = new Set(favorites);
|
|
63
86
|
const hiddenSet = new Set(hidden);
|
|
64
87
|
const favRows = favorites
|
|
65
88
|
.map(key => byKey.get(key))
|
|
66
89
|
.filter((model) => model !== undefined && matchesModelFilter(model, filter))
|
|
90
|
+
.sort(compareListedModels)
|
|
67
91
|
.map(model => ({ kind: 'model', section: 'favorite', model }));
|
|
68
|
-
const normalRows =
|
|
92
|
+
const normalRows = sorted
|
|
69
93
|
.filter(model => !favKeys.has(modelKey(model))
|
|
70
94
|
&& !hiddenSet.has(modelKey(model))
|
|
71
95
|
&& matchesModelFilter(model, filter))
|
|
72
96
|
.map(model => ({ kind: 'model', section: 'normal', model }));
|
|
73
|
-
const hiddenModels =
|
|
97
|
+
const hiddenModels = sorted.filter(model => hiddenSet.has(modelKey(model)) && !favKeys.has(modelKey(model)));
|
|
74
98
|
const showHidden = filter.trim() === '' && hiddenModels.length > 0;
|
|
75
99
|
const rows = [...favRows];
|
|
76
100
|
if (favRows.length > 0 && (normalRows.length > 0 || showHidden)) {
|
package/lib/model-list.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-list.js","sourceRoot":"","sources":["../src/model-list.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"model-list.js","sourceRoot":"","sources":["../src/model-list.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiwayds/dsh-tui-pi",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.25.0",
|
|
4
4
|
"description": "A fully-featured pi-style terminal UI for DeepSeek Harness (dsh) — history look-back & fork-at-turn, guided preset switching, live subagent steering, model profiles & themes",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|