@xynogen/pix-models 0.1.26 → 0.1.31
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/package.json +4 -4
- package/src/models.test.ts +20 -0
- package/src/models.ts +29 -4
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Pi extension — enhanced `/models` picker with coding score/rank.
|
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
Registers a `/models` slash command that replaces Pi's built-in `/model` selector with a richer TUI picker. Each row shows the model id, context window, per-million-token cost, and a coding-focused score/rank (with star bar) when available. The list is sorted by coding score (best first), then alphabetically for unscored models. Fuzzy search filters the list as you type. Selecting a model switches the active model for the session. Model metadata is sourced from `~/.cache/pi/` via `pix-data`; the coding score/rank is computed locally from the modelgrep catalog (best = #1). Requires `@xynogen/pix-data` as a dependency.
|
|
7
|
+
Registers a `/models` slash command that replaces Pi's built-in `/model` selector with a richer TUI picker. Each row shows the model id, context window, per-million-token cost, and a coding-focused score/rank (with star bar) when available. The list is sorted by coding score (best first), then alphabetically for unscored models. Fuzzy search filters the list as you type. Left/right changes the thinking level (`off` → `minimal` → `low` → `medium` → `high` → `xhigh`), with the effective level shown live in the picker header. Selecting a model switches the active model for the session. Model metadata is sourced from `~/.cache/pi/` via `pix-data`; the coding score/rank is computed locally from the modelgrep catalog (best = #1). Requires `@xynogen/pix-data` as a dependency.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-models",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"description": "Pi extension — enhanced /models picker with BenchLM ranks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@xynogen/pix-data": "^0.4.
|
|
42
|
-
"@xynogen/pix-pretty": "^1.
|
|
43
|
-
"@xynogen/pix-runtime": "^0.
|
|
41
|
+
"@xynogen/pix-data": "^0.4.3",
|
|
42
|
+
"@xynogen/pix-pretty": "^1.11.2",
|
|
43
|
+
"@xynogen/pix-runtime": "^0.5.3"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@earendil-works/pi-coding-agent": "*",
|
package/src/models.test.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
fmtCtx,
|
|
7
7
|
type ModelSearchLookup,
|
|
8
8
|
normalizeModelText,
|
|
9
|
+
resolveContextWindow,
|
|
9
10
|
sortModels,
|
|
10
11
|
stepEffectiveThinkingLevel,
|
|
11
12
|
stepThinkingLevel,
|
|
@@ -57,6 +58,25 @@ describe("stepEffectiveThinkingLevel", () => {
|
|
|
57
58
|
});
|
|
58
59
|
});
|
|
59
60
|
|
|
61
|
+
describe("resolveContextWindow", () => {
|
|
62
|
+
it("prefers provider contextWindow over fallback", () => {
|
|
63
|
+
expect(resolveContextWindow({ contextWindow: 200_000 }, 128_000)).toBe(200_000);
|
|
64
|
+
});
|
|
65
|
+
it("falls back to dev limit when provider is 0/missing", () => {
|
|
66
|
+
expect(resolveContextWindow({ contextWindow: 0 }, 128_000)).toBe(128_000);
|
|
67
|
+
expect(resolveContextWindow({}, 64_000)).toBe(64_000);
|
|
68
|
+
});
|
|
69
|
+
it("ignores non-finite and negative values", () => {
|
|
70
|
+
expect(resolveContextWindow({ contextWindow: Number.NaN }, 128_000)).toBe(128_000);
|
|
71
|
+
expect(resolveContextWindow({ contextWindow: Number.POSITIVE_INFINITY }, 50_000)).toBe(50_000);
|
|
72
|
+
expect(resolveContextWindow({ contextWindow: -1 }, 32_000)).toBe(32_000);
|
|
73
|
+
});
|
|
74
|
+
it("returns 0 when both missing/invalid", () => {
|
|
75
|
+
expect(resolveContextWindow({}, undefined)).toBe(0);
|
|
76
|
+
expect(resolveContextWindow({ contextWindow: null }, null)).toBe(0);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
60
80
|
describe("fmtCtx", () => {
|
|
61
81
|
it("formats 0 as 0", () => expect(fmtCtx(0)).toBe("0"));
|
|
62
82
|
it("formats small numbers as-is", () => expect(fmtCtx(512)).toBe("512"));
|
package/src/models.ts
CHANGED
|
@@ -31,6 +31,20 @@ import { patchOutBuiltinModelCommand } from "./patch-builtin";
|
|
|
31
31
|
|
|
32
32
|
// ─── Pure logic (exported for tests) ─────────────────────────────────────────
|
|
33
33
|
|
|
34
|
+
export function resolveContextWindow(
|
|
35
|
+
model: { contextWindow?: number | null },
|
|
36
|
+
fallback?: number | null,
|
|
37
|
+
): number {
|
|
38
|
+
if (
|
|
39
|
+
typeof model.contextWindow === "number" &&
|
|
40
|
+
Number.isFinite(model.contextWindow) &&
|
|
41
|
+
model.contextWindow > 0
|
|
42
|
+
)
|
|
43
|
+
return model.contextWindow;
|
|
44
|
+
if (typeof fallback === "number" && Number.isFinite(fallback) && fallback > 0) return fallback;
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
export function fmtCtx(n: number): string {
|
|
35
49
|
if (!n || n < 1_000) return `${n}`;
|
|
36
50
|
if (n >= 1_000_000) {
|
|
@@ -286,6 +300,14 @@ async function showEnhancedPicker(pi: ExtensionAPI, ctx: ExtensionContext): Prom
|
|
|
286
300
|
1,
|
|
287
301
|
);
|
|
288
302
|
|
|
303
|
+
// Widest cost string so the cost column pads to a common width and the
|
|
304
|
+
// following ⚡score/stars stay column-aligned (e.g. "10.00/50.00" is 11
|
|
305
|
+
// chars — a fixed pad of 10 shifted those rows right by one).
|
|
306
|
+
const maxCostWidth = Math.max(
|
|
307
|
+
...dedupedRows.map((r) => fmtCost(r.dev).length),
|
|
308
|
+
"free".length,
|
|
309
|
+
);
|
|
310
|
+
|
|
289
311
|
// Mute low-info parts (separators, padding, #, ☆) so the actual values pop.
|
|
290
312
|
const mute = (s: string) => theme.fg("muted", s);
|
|
291
313
|
const sep = mute(" · ");
|
|
@@ -338,16 +360,19 @@ async function showEnhancedPicker(pi: ExtensionAPI, ctx: ExtensionContext): Prom
|
|
|
338
360
|
|
|
339
361
|
// Description: ctx · cost · score stars
|
|
340
362
|
// Colors: ctx muted · cost success (free muted) · score+stars warning
|
|
341
|
-
|
|
363
|
+
// Context: provider's `contextWindow` (source of truth) → fallback to modelgrep `dev.limit.context`.
|
|
364
|
+
const ctxRaw = fmtCtx(
|
|
365
|
+
resolveContextWindow(m as { contextWindow?: number }, dev?.limit?.context),
|
|
366
|
+
);
|
|
342
367
|
const ctxStr = mute(ctxRaw.padStart(4));
|
|
343
368
|
const rawCost = fmtCost(dev);
|
|
344
369
|
let costSeg: string;
|
|
345
370
|
if (rawCost === "—") {
|
|
346
|
-
costSeg = theme.fg("dim", "—".padEnd(
|
|
371
|
+
costSeg = theme.fg("dim", "—".padEnd(maxCostWidth));
|
|
347
372
|
} else if (rawCost === "free") {
|
|
348
|
-
costSeg = mute("free".padEnd(
|
|
373
|
+
costSeg = mute("free".padEnd(maxCostWidth));
|
|
349
374
|
} else {
|
|
350
|
-
costSeg = theme.fg("success", rawCost.padEnd(
|
|
375
|
+
costSeg = theme.fg("success", rawCost.padEnd(maxCostWidth));
|
|
351
376
|
}
|
|
352
377
|
let benchSeg = "";
|
|
353
378
|
if (bench) {
|