@modelstatus/cli 0.1.64 → 0.1.65
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/package.json +1 -1
- package/src/fix.js +5 -3
- package/src/tui/views/whatsnew.js +18 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelstatus/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.65",
|
|
4
4
|
"description": "Track which AI models you use, where, and never get surprised by a retirement. Free offline model-health for any repo (mm status), browser sign-in for cloud inventory + alerts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
package/src/fix.js
CHANGED
|
@@ -55,7 +55,8 @@ export function recordFixes(dir, applied, { source = "tui" } = {}) {
|
|
|
55
55
|
if (Array.isArray(j)) log = j;
|
|
56
56
|
} catch { /* first write */ }
|
|
57
57
|
const ts = Date.now();
|
|
58
|
-
const
|
|
58
|
+
const clip = (t) => (typeof t === "string" && t.length > 240 ? t.slice(0, 237) + "…" : t);
|
|
59
|
+
const entries = applied.map((p) => ({ ts, dir: path.resolve(dir), file: p.file, line: p.line, from: p.from, to: p.to, before: clip(p.before), after: clip(p.after), source }));
|
|
59
60
|
log = [...entries, ...log].slice(0, FIXES_CAP);
|
|
60
61
|
fs.mkdirSync(path.dirname(FIXES_FILE), { recursive: true, mode: 0o700 });
|
|
61
62
|
fs.writeFileSync(FIXES_FILE, JSON.stringify(log));
|
|
@@ -190,14 +191,15 @@ export function applyFixes(dir, plans) {
|
|
|
190
191
|
stale.push({ ...p, error: "line out of range — rescan" });
|
|
191
192
|
continue;
|
|
192
193
|
}
|
|
193
|
-
const
|
|
194
|
+
const before = lines[idx];
|
|
195
|
+
const { out, n } = replaceOnLine(before, p.from, p.to);
|
|
194
196
|
if (n === 0) {
|
|
195
197
|
stale.push({ ...p, error: "string not on that line anymore — rescan" });
|
|
196
198
|
continue;
|
|
197
199
|
}
|
|
198
200
|
lines[idx] = out;
|
|
199
201
|
dirty = true;
|
|
200
|
-
applied.push({ ...p, count: n });
|
|
202
|
+
applied.push({ ...p, count: n, before, after: out });
|
|
201
203
|
}
|
|
202
204
|
if (dirty) {
|
|
203
205
|
try {
|
|
@@ -206,9 +206,11 @@ export function WhatsNewView({ client, dir, ui, active, width = 78, height = 14
|
|
|
206
206
|
if (!fixes.length) {
|
|
207
207
|
body = h(Text, { color: C.FG_DIM }, " No fixes applied yet. Press f on the Here tab (or run mm fix) to rewrite dying model ids.");
|
|
208
208
|
} else {
|
|
209
|
-
// Windowed like the Alerts section so ↑↓ reaches every row
|
|
209
|
+
// Windowed like the Alerts section so ↑↓ reaches every row — minus 4 rows
|
|
210
|
+
// reserved for the selected fix's diff underneath.
|
|
211
|
+
const FROWS = Math.max(3, ROWS - 4);
|
|
210
212
|
const cur = clampCursor(cursor, fixes.length);
|
|
211
|
-
const start = Math.max(0, Math.min(cur -
|
|
213
|
+
const start = Math.max(0, Math.min(cur - FROWS + 1, fixes.length - FROWS));
|
|
212
214
|
const ago = (ts) => {
|
|
213
215
|
const m = Math.max(0, Math.round((Date.now() - ts) / 60000));
|
|
214
216
|
if (m < 1) return "now";
|
|
@@ -220,7 +222,7 @@ export function WhatsNewView({ client, dir, ui, active, width = 78, height = 14
|
|
|
220
222
|
body = h(
|
|
221
223
|
Box,
|
|
222
224
|
{ flexDirection: "column" },
|
|
223
|
-
...fixes.slice(start, start +
|
|
225
|
+
...fixes.slice(start, start + FROWS).map((f, i) => {
|
|
224
226
|
const cells = [
|
|
225
227
|
{ text: `${GLYPH.check} `, color: "#16a34a" },
|
|
226
228
|
{ text: cellE(`${path.basename(f.dir)} · ${f.file}:${f.line}`, 38), color: C.FG },
|
|
@@ -230,6 +232,19 @@ export function WhatsNewView({ client, dir, ui, active, width = 78, height = 14
|
|
|
230
232
|
];
|
|
231
233
|
return h(ListRow, { key: `f${start + i}`, active: start + i === cur, cells, width });
|
|
232
234
|
}),
|
|
235
|
+
// The selected fix's diff — same red/green visual as the f preview + the fix PR.
|
|
236
|
+
h(Text, { key: "drule" }, ""),
|
|
237
|
+
...(() => {
|
|
238
|
+
const sel = fixes[cur];
|
|
239
|
+
if (!sel) return [];
|
|
240
|
+
if (!sel.before || !sel.after) return [h(Text, { key: "dnone", color: C.FG_DIM }, " (diff not recorded for this entry — older fix)")];
|
|
241
|
+
const w = Math.max(20, width - 4);
|
|
242
|
+
return [
|
|
243
|
+
h(Text, { key: "dh", color: C.FG_DIM }, ` ${cellE(`${sel.file}:${sel.line}`, w)}`),
|
|
244
|
+
h(Text, { key: "dd", color: "#f87171" }, cellE(` - ${sel.before.trimEnd()}`, w)),
|
|
245
|
+
h(Text, { key: "da", color: "#4ade80" }, cellE(` + ${sel.after.trimEnd()}`, w)),
|
|
246
|
+
];
|
|
247
|
+
})(),
|
|
233
248
|
);
|
|
234
249
|
}
|
|
235
250
|
} else {
|