@sushant-kum/ccstatus 0.1.0 → 0.1.2
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.
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
COLORS,
|
|
4
|
+
LINKABLE,
|
|
4
5
|
configPath,
|
|
5
6
|
importCcstatusline,
|
|
6
7
|
isValidWhen,
|
|
8
|
+
linkedSurfaces,
|
|
7
9
|
loadConfigFile,
|
|
8
10
|
readSnapshot,
|
|
9
11
|
registry,
|
|
@@ -11,8 +13,9 @@ import {
|
|
|
11
13
|
rendererBg,
|
|
12
14
|
rendererColor,
|
|
13
15
|
saveConfigFile,
|
|
14
|
-
snapshotPath
|
|
15
|
-
|
|
16
|
+
snapshotPath,
|
|
17
|
+
writeLinkedLines
|
|
18
|
+
} from "./chunk-BCBGMRHQ.js";
|
|
16
19
|
|
|
17
20
|
// src/app.tsx
|
|
18
21
|
import { Box as Box12, Text as Text12, useApp, useInput as useInput10 } from "ink";
|
|
@@ -317,14 +320,15 @@ var NAMED_COLORS = [
|
|
|
317
320
|
];
|
|
318
321
|
|
|
319
322
|
// src/screens/items.tsx
|
|
320
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
321
|
-
var SURFACES =
|
|
323
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
324
|
+
var SURFACES = LINKABLE;
|
|
322
325
|
var FIELDS2 = ["fg", "bg", "raw", "merge", "align"];
|
|
323
326
|
var ALIGNS = ["left", "center", "right"];
|
|
324
327
|
var FG = NAMED_COLORS.filter((c) => !c.startsWith("bg"));
|
|
325
328
|
var BG = ["(none)", ...NAMED_COLORS.filter((c) => c.startsWith("bg"))];
|
|
326
329
|
var WIDGETS = Object.values(registry);
|
|
327
330
|
var wrap = (i, n) => (i + n) % n;
|
|
331
|
+
var makeId = (type) => `${type}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
328
332
|
var isStylable = (item) => item.type !== "flex-separator";
|
|
329
333
|
function Chip({ item, selected }) {
|
|
330
334
|
const fg = isStylable(item) ? item.fg : void 0;
|
|
@@ -349,16 +353,16 @@ function Items({ config, setConfig, goHome }) {
|
|
|
349
353
|
const [surface, setSurface] = useState3("band");
|
|
350
354
|
const [sel, setSel] = useState3(0);
|
|
351
355
|
const [mode, setMode] = useState3("strip");
|
|
356
|
+
const [linkPick, setLinkPick] = useState3(0);
|
|
357
|
+
const [confirm, setConfirm] = useState3(null);
|
|
352
358
|
const [field, setField] = useState3(0);
|
|
353
359
|
const [pick, setPick] = useState3(0);
|
|
354
360
|
const items = config.surfaces[surface].lines[0] ?? [];
|
|
355
361
|
const cur = items[Math.min(sel, items.length - 1)];
|
|
356
362
|
const idx = cur ? items.indexOf(cur) : -1;
|
|
357
363
|
const commit = (next) => {
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
const c = { ...config, surfaces: { ...config.surfaces, [surface]: { ...s, lines } } };
|
|
361
|
-
setConfig(c);
|
|
364
|
+
const lines = [next, ...config.surfaces[surface].lines.slice(1)];
|
|
365
|
+
setConfig({ ...config, surfaces: writeLinkedLines(config.surfaces, surface, lines) });
|
|
362
366
|
};
|
|
363
367
|
const patch = (p) => {
|
|
364
368
|
const base = items[idx];
|
|
@@ -410,6 +414,45 @@ function Items({ config, setConfig, goHome }) {
|
|
|
410
414
|
commit(next);
|
|
411
415
|
setSel(j);
|
|
412
416
|
};
|
|
417
|
+
const others = SURFACES.filter((s) => s !== surface);
|
|
418
|
+
const linkOptions = [
|
|
419
|
+
...others.map((s) => ({ label: s, targets: [s] })),
|
|
420
|
+
{ label: "all others", targets: others }
|
|
421
|
+
];
|
|
422
|
+
const linkReplacements = (targets) => SURFACES.filter((s) => s !== surface && (targets.includes(s) || config.surfaces[s].linked));
|
|
423
|
+
const applyLink = (targets) => {
|
|
424
|
+
const marked = { ...config.surfaces };
|
|
425
|
+
marked[surface] = { ...config.surfaces[surface], linked: true };
|
|
426
|
+
for (const t of targets) {
|
|
427
|
+
marked[t] = { ...config.surfaces[t], linked: true };
|
|
428
|
+
}
|
|
429
|
+
const surfaces = writeLinkedLines(marked, surface, config.surfaces[surface].lines);
|
|
430
|
+
setConfig({ ...config, surfaces });
|
|
431
|
+
};
|
|
432
|
+
const applyUnlink = () => {
|
|
433
|
+
const layout = config.surfaces[surface];
|
|
434
|
+
if (!layout.linked) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const surfaces = {
|
|
438
|
+
...config.surfaces,
|
|
439
|
+
[surface]: {
|
|
440
|
+
...layout,
|
|
441
|
+
linked: false,
|
|
442
|
+
lines: layout.lines.map(
|
|
443
|
+
(line) => line.map((it) => ({ ...it, id: makeId(it.type) }))
|
|
444
|
+
)
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
const remaining = linkedSurfaces(surfaces);
|
|
448
|
+
if (remaining.length === 1) {
|
|
449
|
+
const lone = remaining[0];
|
|
450
|
+
if (lone) {
|
|
451
|
+
surfaces[lone] = { ...surfaces[lone], linked: false };
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
setConfig({ ...config, surfaces });
|
|
455
|
+
};
|
|
413
456
|
useInput3((input, key) => {
|
|
414
457
|
if (mode === "picker") {
|
|
415
458
|
if (key.escape) {
|
|
@@ -422,7 +465,7 @@ function Items({ config, setConfig, goHome }) {
|
|
|
422
465
|
const picked = WIDGETS[pick];
|
|
423
466
|
if (picked) {
|
|
424
467
|
const type = picked.type;
|
|
425
|
-
const id =
|
|
468
|
+
const id = makeId(type);
|
|
426
469
|
const newItem = type === "custom-text" ? { id, type, text: "" } : type === "custom-command" ? { id, type, command: "" } : type === "flex-separator" ? { id, type } : { id, type };
|
|
427
470
|
commit([...items, newItem]);
|
|
428
471
|
setSel(items.length);
|
|
@@ -441,6 +484,35 @@ function Items({ config, setConfig, goHome }) {
|
|
|
441
484
|
} else if (key.rightArrow) {
|
|
442
485
|
change(1);
|
|
443
486
|
}
|
|
487
|
+
} else if (mode === "link") {
|
|
488
|
+
if (confirm) {
|
|
489
|
+
if (input === "y") {
|
|
490
|
+
applyLink(confirm);
|
|
491
|
+
setConfirm(null);
|
|
492
|
+
setMode("strip");
|
|
493
|
+
} else if (input === "n" || key.escape) {
|
|
494
|
+
setConfirm(null);
|
|
495
|
+
setMode("strip");
|
|
496
|
+
}
|
|
497
|
+
} else if (key.escape) {
|
|
498
|
+
setMode("strip");
|
|
499
|
+
} else if (key.upArrow) {
|
|
500
|
+
setLinkPick((p) => wrap(p - 1 + linkOptions.length, linkOptions.length));
|
|
501
|
+
} else if (key.downArrow) {
|
|
502
|
+
setLinkPick((p) => wrap(p + 1, linkOptions.length));
|
|
503
|
+
} else if (key.return) {
|
|
504
|
+
const chosen = linkOptions[linkPick];
|
|
505
|
+
if (chosen) {
|
|
506
|
+
const affected = linkReplacements(chosen.targets);
|
|
507
|
+
const nonEmpty = affected.some((t) => config.surfaces[t].lines.some((l) => l.length > 0));
|
|
508
|
+
if (nonEmpty) {
|
|
509
|
+
setConfirm(affected);
|
|
510
|
+
} else {
|
|
511
|
+
applyLink(chosen.targets);
|
|
512
|
+
setMode("strip");
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
444
516
|
} else {
|
|
445
517
|
if (key.escape) {
|
|
446
518
|
goHome();
|
|
@@ -464,6 +536,12 @@ function Items({ config, setConfig, goHome }) {
|
|
|
464
536
|
} else if (input === "e" && idx >= 0) {
|
|
465
537
|
setField(0);
|
|
466
538
|
setMode("editor");
|
|
539
|
+
} else if (input === "l") {
|
|
540
|
+
setLinkPick(0);
|
|
541
|
+
setConfirm(null);
|
|
542
|
+
setMode("link");
|
|
543
|
+
} else if (input === "u") {
|
|
544
|
+
applyUnlink();
|
|
467
545
|
}
|
|
468
546
|
}
|
|
469
547
|
});
|
|
@@ -482,8 +560,35 @@ function Items({ config, setConfig, goHome }) {
|
|
|
482
560
|
s === surface ? `[${s}]` : s,
|
|
483
561
|
" "
|
|
484
562
|
] }, s)) }),
|
|
485
|
-
|
|
486
|
-
|
|
563
|
+
config.surfaces[surface].linked && /* @__PURE__ */ jsxs4(Text5, { color: "magenta", children: [
|
|
564
|
+
"\u{1F517} linked: ",
|
|
565
|
+
SURFACES.filter((s) => config.surfaces[s].linked).join(", "),
|
|
566
|
+
" \u2014 edits apply to all"
|
|
567
|
+
] }),
|
|
568
|
+
/* @__PURE__ */ jsx4(Box5, { children: items.length === 0 ? /* @__PURE__ */ jsx4(Text5, { dimColor: true, children: "(no items \u2014 press a)" }) : (
|
|
569
|
+
// Item ids are unique within a surface. Linked surfaces share ids across
|
|
570
|
+
// surfaces (DEC-0018), but only one surface's items render here at a time,
|
|
571
|
+
// so these keys never collide. (The live Preview renders a RenderModel of
|
|
572
|
+
// positional segments — paint.tsx keys by index, not item id.)
|
|
573
|
+
items.map((it, i) => /* @__PURE__ */ jsx4(Chip, { item: it, selected: i === idx }, it.id))
|
|
574
|
+
) }),
|
|
575
|
+
mode === "link" ? /* @__PURE__ */ jsx4(Box5, { flexDirection: "column", marginTop: 1, children: confirm ? /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
576
|
+
"Replace ",
|
|
577
|
+
confirm.join(", "),
|
|
578
|
+
" layout with ",
|
|
579
|
+
surface,
|
|
580
|
+
"'s? (y/n)"
|
|
581
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
582
|
+
/* @__PURE__ */ jsxs4(Text5, { bold: true, children: [
|
|
583
|
+
"Link ",
|
|
584
|
+
surface,
|
|
585
|
+
" layout to:"
|
|
586
|
+
] }),
|
|
587
|
+
linkOptions.map((o, i) => /* @__PURE__ */ jsxs4(Text5, { color: i === linkPick ? "cyan" : void 0, children: [
|
|
588
|
+
i === linkPick ? "\u25B8 " : " ",
|
|
589
|
+
o.label
|
|
590
|
+
] }, o.label))
|
|
591
|
+
] }) }) : mode === "picker" ? /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
487
592
|
/* @__PURE__ */ jsx4(Text5, { bold: true, children: "Add widget" }),
|
|
488
593
|
WIDGETS.map((w, i) => /* @__PURE__ */ jsxs4(Text5, { color: i === pick ? "cyan" : void 0, children: [
|
|
489
594
|
i === pick ? "\u25B8 " : " ",
|
|
@@ -508,7 +613,7 @@ function Items({ config, setConfig, goHome }) {
|
|
|
508
613
|
] }),
|
|
509
614
|
/* @__PURE__ */ jsx4(Text5, { dimColor: true, children: "(flex separator \u2014 no style options)" })
|
|
510
615
|
] })),
|
|
511
|
-
/* @__PURE__ */ jsx4(Text5, { dimColor: true, children: mode === "strip" ? "\u2190/\u2192 select \xB7 [/] move \xB7 a add \xB7 x remove \xB7 e edit \xB7 tab surface \xB7 esc back" : mode === "editor" ? "\u2191/\u2193 field \xB7 \u2190/\u2192 change \xB7 esc done" : "\u2191/\u2193 choose \xB7 enter add \xB7 esc cancel" })
|
|
616
|
+
/* @__PURE__ */ jsx4(Text5, { dimColor: true, children: mode === "strip" ? "\u2190/\u2192 select \xB7 [/] move \xB7 a add \xB7 x remove \xB7 e edit \xB7 l link \xB7 u unlink \xB7 tab surface \xB7 esc back" : mode === "editor" ? "\u2191/\u2193 field \xB7 \u2190/\u2192 change \xB7 esc done" : mode === "link" ? confirm ? "y confirm \xB7 n cancel" : "\u2191/\u2193 choose \xB7 enter link \xB7 esc cancel" : "\u2191/\u2193 choose \xB7 enter add \xB7 esc cancel" })
|
|
512
617
|
] });
|
|
513
618
|
}
|
|
514
619
|
|
|
@@ -338,6 +338,41 @@ register({
|
|
|
338
338
|
return parts[parts.length - 1] ?? snapshot.cwd;
|
|
339
339
|
}
|
|
340
340
|
});
|
|
341
|
+
register({
|
|
342
|
+
type: "context-bar",
|
|
343
|
+
label: "Ctx Bar",
|
|
344
|
+
format: ({ snapshot }) => bar(snapshot.ctxPct)
|
|
345
|
+
});
|
|
346
|
+
register({
|
|
347
|
+
type: "context-remaining",
|
|
348
|
+
label: "Ctx Left",
|
|
349
|
+
format: ({ snapshot, item }) => labeled(rawOf(item), "Ctx Left", pct(100 - snapshot.ctxPct))
|
|
350
|
+
});
|
|
351
|
+
register({
|
|
352
|
+
type: "thinking-effort",
|
|
353
|
+
label: "Effort",
|
|
354
|
+
format: ({ snapshot, item }) => snapshot.effort ? labeled(rawOf(item), "Effort", snapshot.effort) : null
|
|
355
|
+
});
|
|
356
|
+
register({
|
|
357
|
+
type: "session-id",
|
|
358
|
+
label: "Session ID",
|
|
359
|
+
format: ({ snapshot, item }) => snapshot.sessionId ? rawOf(item) ? snapshot.sessionId : snapshot.sessionId.slice(0, 8) : null
|
|
360
|
+
});
|
|
361
|
+
register({
|
|
362
|
+
type: "context-window",
|
|
363
|
+
label: "Ctx Window",
|
|
364
|
+
format: ({ snapshot, item }) => snapshot.ctxWindow > 0 ? labeled(rawOf(item), "Window", fmtNum(snapshot.ctxWindow)) : null
|
|
365
|
+
});
|
|
366
|
+
register({
|
|
367
|
+
type: "output-style",
|
|
368
|
+
label: "Style",
|
|
369
|
+
format: ({ snapshot, item }) => snapshot.outputStyle ? labeled(rawOf(item), "Style", snapshot.outputStyle) : null
|
|
370
|
+
});
|
|
371
|
+
register({
|
|
372
|
+
type: "terminal-width",
|
|
373
|
+
label: "Width",
|
|
374
|
+
format: ({ snapshot, item }) => snapshot.terminalWidth > 0 ? labeled(rawOf(item), "Width", String(snapshot.terminalWidth)) : null
|
|
375
|
+
});
|
|
341
376
|
|
|
342
377
|
// ../core/src/widgets/git-widgets.ts
|
|
343
378
|
register({
|
|
@@ -360,6 +395,21 @@ register({
|
|
|
360
395
|
label: "Worktree",
|
|
361
396
|
format: ({ snapshot }) => snapshot.repo && snapshot.gitWorktree ? `\u2387 ${snapshot.gitWorktree}` : null
|
|
362
397
|
});
|
|
398
|
+
register({
|
|
399
|
+
type: "git-insertions",
|
|
400
|
+
label: "Insertions",
|
|
401
|
+
format: ({ snapshot }) => snapshot.repo ? `+${snapshot.insertions}` : null
|
|
402
|
+
});
|
|
403
|
+
register({
|
|
404
|
+
type: "git-deletions",
|
|
405
|
+
label: "Deletions",
|
|
406
|
+
format: ({ snapshot }) => snapshot.repo ? `-${snapshot.deletions}` : null
|
|
407
|
+
});
|
|
408
|
+
register({
|
|
409
|
+
type: "git-sha",
|
|
410
|
+
label: "SHA",
|
|
411
|
+
format: ({ snapshot }) => snapshot.repo && snapshot.gitSha ? snapshot.gitSha : null
|
|
412
|
+
});
|
|
363
413
|
|
|
364
414
|
// ../core/src/widgets/usage-widgets.ts
|
|
365
415
|
function until(iso, now) {
|
|
@@ -408,6 +458,46 @@ register({
|
|
|
408
458
|
return reset === null ? null : `Block: ${fmtDur(reset)}`;
|
|
409
459
|
}
|
|
410
460
|
});
|
|
461
|
+
register({
|
|
462
|
+
type: "session-usage",
|
|
463
|
+
label: "Session %",
|
|
464
|
+
format: ({ snapshot }) => snapshot.fivePct === null ? null : `Session: ${pct(snapshot.fivePct)}`
|
|
465
|
+
});
|
|
466
|
+
register({
|
|
467
|
+
type: "weekly-usage",
|
|
468
|
+
label: "Weekly %",
|
|
469
|
+
format: ({ snapshot }) => snapshot.weekPct === null ? null : `Weekly: ${pct(snapshot.weekPct)}`
|
|
470
|
+
});
|
|
471
|
+
register({
|
|
472
|
+
type: "reset-timer",
|
|
473
|
+
label: "Reset",
|
|
474
|
+
format: ({ snapshot }) => {
|
|
475
|
+
const r = until(snapshot.fiveReset, snapshot.now);
|
|
476
|
+
return r === null ? null : `Reset: ${fmtDur(r)}`;
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
register({
|
|
480
|
+
type: "weekly-reset-timer",
|
|
481
|
+
label: "Weekly Reset",
|
|
482
|
+
format: ({ snapshot }) => {
|
|
483
|
+
const r = until(snapshot.weekReset, snapshot.now);
|
|
484
|
+
return r === null ? null : `Weekly Reset: ${fmtDur(r)}`;
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
register({
|
|
488
|
+
type: "session-cost-rate",
|
|
489
|
+
label: "Cost/hr",
|
|
490
|
+
format: ({ snapshot }) => {
|
|
491
|
+
if (snapshot.cost === null) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const ms = snapshot.now - snapshot.startedAt;
|
|
495
|
+
if (ms < 6e4) {
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
return `$${(snapshot.cost / (ms / 36e5)).toFixed(2)}/hr`;
|
|
499
|
+
}
|
|
500
|
+
});
|
|
411
501
|
|
|
412
502
|
// ../core/src/widgets/custom-widgets.ts
|
|
413
503
|
register({
|
|
@@ -565,6 +655,53 @@ var defaultConfig = {
|
|
|
565
655
|
}
|
|
566
656
|
};
|
|
567
657
|
|
|
658
|
+
// ../core/src/config/links.ts
|
|
659
|
+
var LINKABLE = ["band", "statusline", "pane"];
|
|
660
|
+
var clone = (v) => JSON.parse(JSON.stringify(v));
|
|
661
|
+
function linkedSurfaces(surfaces) {
|
|
662
|
+
return LINKABLE.filter((name) => surfaces[name].linked);
|
|
663
|
+
}
|
|
664
|
+
function writeLinkedLines(surfaces, surface, lines) {
|
|
665
|
+
const next = { ...surfaces };
|
|
666
|
+
next[surface] = { ...surfaces[surface], lines: clone(lines) };
|
|
667
|
+
if (surfaces[surface].linked) {
|
|
668
|
+
for (const member of LINKABLE) {
|
|
669
|
+
if (member !== surface && surfaces[member].linked) {
|
|
670
|
+
next[member] = { ...surfaces[member], lines: clone(lines) };
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return next;
|
|
675
|
+
}
|
|
676
|
+
function normalizeLinks(surfaces, warn) {
|
|
677
|
+
const linked = linkedSurfaces(surfaces);
|
|
678
|
+
if (linked.length < 2) {
|
|
679
|
+
for (const name of linked) {
|
|
680
|
+
delete surfaces[name].linked;
|
|
681
|
+
warn(`dropped lone surface link on "${name}"`);
|
|
682
|
+
}
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
const canonical = linked[0];
|
|
686
|
+
if (!canonical) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const source = JSON.stringify(surfaces[canonical].lines);
|
|
690
|
+
let diverged = false;
|
|
691
|
+
for (const name of linked) {
|
|
692
|
+
if (name === canonical) {
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
if (JSON.stringify(surfaces[name].lines) !== source) {
|
|
696
|
+
surfaces[name].lines = clone(surfaces[canonical].lines);
|
|
697
|
+
diverged = true;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
if (diverged) {
|
|
701
|
+
warn(`linked surfaces diverged; synced to "${canonical}"`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
568
705
|
// ../../node_modules/zod/v3/external.js
|
|
569
706
|
var external_exports = {};
|
|
570
707
|
__export(external_exports, {
|
|
@@ -4623,7 +4760,8 @@ var itemSchema = external_exports.object({
|
|
|
4623
4760
|
});
|
|
4624
4761
|
var surfaceLayoutSchema = external_exports.object({
|
|
4625
4762
|
enabled: external_exports.boolean(),
|
|
4626
|
-
lines: external_exports.array(external_exports.array(itemSchema))
|
|
4763
|
+
lines: external_exports.array(external_exports.array(itemSchema)),
|
|
4764
|
+
linked: external_exports.boolean().optional()
|
|
4627
4765
|
});
|
|
4628
4766
|
var toastRuleSchema = external_exports.object({
|
|
4629
4767
|
when: external_exports.string(),
|
|
@@ -4669,13 +4807,28 @@ var WIDGET_TYPES = [
|
|
|
4669
4807
|
"rate-limit-5h",
|
|
4670
4808
|
"rate-limit-week",
|
|
4671
4809
|
"block-timer",
|
|
4810
|
+
"session-usage",
|
|
4811
|
+
"weekly-usage",
|
|
4812
|
+
"reset-timer",
|
|
4813
|
+
"weekly-reset-timer",
|
|
4814
|
+
"context-bar",
|
|
4815
|
+
"context-remaining",
|
|
4816
|
+
"thinking-effort",
|
|
4817
|
+
"git-insertions",
|
|
4818
|
+
"git-deletions",
|
|
4819
|
+
"session-id",
|
|
4820
|
+
"context-window",
|
|
4821
|
+
"session-cost-rate",
|
|
4822
|
+
"git-sha",
|
|
4823
|
+
"output-style",
|
|
4824
|
+
"terminal-width",
|
|
4672
4825
|
"custom-text",
|
|
4673
4826
|
"custom-command",
|
|
4674
4827
|
"flex-separator"
|
|
4675
4828
|
];
|
|
4676
4829
|
|
|
4677
4830
|
// ../core/src/config/validate.ts
|
|
4678
|
-
var
|
|
4831
|
+
var clone2 = (v) => JSON.parse(JSON.stringify(v));
|
|
4679
4832
|
var WIDGET_TYPE_SET = new Set(WIDGET_TYPES);
|
|
4680
4833
|
function cleanStyle(raw, type, warn) {
|
|
4681
4834
|
const style = {};
|
|
@@ -4751,7 +4904,7 @@ function cleanThemes(themes, warn) {
|
|
|
4751
4904
|
}
|
|
4752
4905
|
function cleanToasts(raw, warn) {
|
|
4753
4906
|
if (!raw) {
|
|
4754
|
-
return
|
|
4907
|
+
return clone2(defaultConfig.surfaces.toasts);
|
|
4755
4908
|
}
|
|
4756
4909
|
const rules = raw.rules.filter((r) => {
|
|
4757
4910
|
if (isValidWhen(r.when)) {
|
|
@@ -4776,22 +4929,26 @@ function loadConfig(raw) {
|
|
|
4776
4929
|
if (raw !== void 0) {
|
|
4777
4930
|
warn(`config invalid (${parsed.error.issues[0]?.message ?? "unknown"}); using defaults`);
|
|
4778
4931
|
}
|
|
4779
|
-
return { config:
|
|
4932
|
+
return { config: clone2(defaultConfig), warnings };
|
|
4780
4933
|
}
|
|
4781
4934
|
const p = parsed.data;
|
|
4782
4935
|
const surf = (name) => {
|
|
4783
4936
|
const s = p.surfaces[name];
|
|
4784
4937
|
if (!s) {
|
|
4785
|
-
return
|
|
4938
|
+
return clone2(defaultConfig.surfaces[name]);
|
|
4786
4939
|
}
|
|
4787
|
-
|
|
4940
|
+
const layout = {
|
|
4788
4941
|
enabled: s.enabled,
|
|
4789
4942
|
lines: s.lines.map(
|
|
4790
4943
|
(line) => line.map((it) => cleanItem(it, warn)).filter((x) => x !== null)
|
|
4791
4944
|
)
|
|
4792
4945
|
};
|
|
4946
|
+
if (s.linked) {
|
|
4947
|
+
layout.linked = true;
|
|
4948
|
+
}
|
|
4949
|
+
return layout;
|
|
4793
4950
|
};
|
|
4794
|
-
const themesToUse = Object.keys(p.themes).length ? p.themes :
|
|
4951
|
+
const themesToUse = Object.keys(p.themes).length ? p.themes : clone2(defaultConfig.themes);
|
|
4795
4952
|
const config = {
|
|
4796
4953
|
version: 1,
|
|
4797
4954
|
theme: p.theme,
|
|
@@ -4804,32 +4961,112 @@ function loadConfig(raw) {
|
|
|
4804
4961
|
toasts: cleanToasts(p.surfaces.toasts, warn)
|
|
4805
4962
|
}
|
|
4806
4963
|
};
|
|
4964
|
+
normalizeLinks(config.surfaces, warn);
|
|
4807
4965
|
return { config, warnings };
|
|
4808
4966
|
}
|
|
4809
4967
|
|
|
4810
4968
|
// ../core/src/config/import-ccstatusline.ts
|
|
4811
|
-
var
|
|
4969
|
+
var clone3 = (v) => JSON.parse(JSON.stringify(v));
|
|
4812
4970
|
var TYPE_MAP = {
|
|
4813
|
-
version: "version",
|
|
4814
4971
|
model: "model",
|
|
4815
|
-
|
|
4972
|
+
version: "version",
|
|
4973
|
+
"thinking-effort": "thinking-effort",
|
|
4816
4974
|
"context-length": "context-length",
|
|
4817
4975
|
"context-percentage": "context-percentage",
|
|
4818
|
-
"
|
|
4976
|
+
"context-window": "context-window",
|
|
4977
|
+
"context-bar": "context-bar",
|
|
4819
4978
|
"tokens-input": "tokens-input",
|
|
4820
4979
|
"tokens-output": "tokens-output",
|
|
4980
|
+
"tokens-cached": "tokens-cached",
|
|
4821
4981
|
"tokens-total": "tokens-total",
|
|
4822
4982
|
"git-root-dir": "git-root-dir",
|
|
4823
4983
|
"git-branch": "git-branch",
|
|
4824
4984
|
"git-worktree": "git-worktree",
|
|
4825
4985
|
"git-changes": "git-changes",
|
|
4826
|
-
"
|
|
4986
|
+
"git-insertions": "git-insertions",
|
|
4987
|
+
"git-deletions": "git-deletions",
|
|
4988
|
+
"git-sha": "git-sha",
|
|
4989
|
+
"session-clock": "session-clock",
|
|
4990
|
+
"session-id": "session-id",
|
|
4991
|
+
"current-working-dir": "cwd",
|
|
4992
|
+
cwd: "cwd",
|
|
4993
|
+
"session-cost": "cost",
|
|
4994
|
+
cost: "cost",
|
|
4995
|
+
"session-cost-rate": "session-cost-rate",
|
|
4996
|
+
"session-usage": "session-usage",
|
|
4997
|
+
"weekly-usage": "weekly-usage",
|
|
4998
|
+
"reset-timer": "reset-timer",
|
|
4999
|
+
"weekly-reset-timer": "weekly-reset-timer",
|
|
5000
|
+
"block-timer": "block-timer",
|
|
5001
|
+
"terminal-width": "terminal-width",
|
|
5002
|
+
"output-style": "output-style"
|
|
4827
5003
|
};
|
|
5004
|
+
var UNSUPPORTED = {
|
|
5005
|
+
"weekly-sonnet-usage": "needs the Anthropic usage API, not available to the mod",
|
|
5006
|
+
"weekly-opus-usage": "needs the Anthropic usage API, not available to the mod",
|
|
5007
|
+
"fable-weekly-usage": "needs the Anthropic usage API, not available to the mod",
|
|
5008
|
+
"extra-usage-utilization": "needs the Anthropic usage API, not available to the mod",
|
|
5009
|
+
"extra-usage-remaining": "needs the Anthropic usage API, not available to the mod",
|
|
5010
|
+
"extra-usage-used": "needs the Anthropic usage API, not available to the mod",
|
|
5011
|
+
"extra-usage-daily-budget": "needs the Anthropic usage API, not available to the mod",
|
|
5012
|
+
"input-speed": "needs transcript parsing, not available to the mod",
|
|
5013
|
+
"output-speed": "needs transcript parsing, not available to the mod",
|
|
5014
|
+
"total-speed": "needs transcript parsing, not available to the mod",
|
|
5015
|
+
"cache-hit-rate": "needs transcript parsing, not available to the mod",
|
|
5016
|
+
"cache-read": "needs transcript parsing, not available to the mod",
|
|
5017
|
+
"cache-write": "needs transcript parsing, not available to the mod",
|
|
5018
|
+
"compaction-counter": "needs transcript parsing, not available to the mod",
|
|
5019
|
+
skills: "needs transcript parsing, not available to the mod",
|
|
5020
|
+
"session-name": "needs transcript parsing, not available to the mod",
|
|
5021
|
+
"cache-timer": "needs cache-TTL tracking, not available to the mod",
|
|
5022
|
+
"free-memory": "reads OS memory, not available to the mod",
|
|
5023
|
+
"claude-status": "needs a network status fetch, not available to the mod",
|
|
5024
|
+
"claude-account-email": "needs local Claude config access, not available to the mod",
|
|
5025
|
+
"claude-session-id": "renamed; use the session-id widget",
|
|
5026
|
+
"vim-mode": "engine state not exposed to the mod",
|
|
5027
|
+
"voice-status": "engine state not exposed to the mod",
|
|
5028
|
+
"sandbox-status": "engine state not exposed to the mod",
|
|
5029
|
+
"remote-control-status": "engine state not exposed to the mod",
|
|
5030
|
+
"worktree-mode": "needs Claude Code's worktree object; use the git-worktree widget",
|
|
5031
|
+
"worktree-name": "needs Claude Code's worktree object; use the git-worktree widget",
|
|
5032
|
+
"worktree-branch": "needs Claude Code's worktree object; use the git-worktree widget",
|
|
5033
|
+
"worktree-original-branch": "needs Claude Code's worktree object; use the git-worktree widget",
|
|
5034
|
+
"context-percentage-usable": "needs usable-window data, not available to the mod",
|
|
5035
|
+
"context-window-size": "renamed; use the context-window widget",
|
|
5036
|
+
"git-staged-files": "needs a deeper git probe, not available to the mod",
|
|
5037
|
+
"git-unstaged-files": "needs a deeper git probe, not available to the mod",
|
|
5038
|
+
"git-untracked-files": "needs a deeper git probe, not available to the mod",
|
|
5039
|
+
"git-clean-status": "needs a deeper git probe, not available to the mod",
|
|
5040
|
+
"git-status": "needs a deeper git probe, not available to the mod",
|
|
5041
|
+
"git-staged": "needs a deeper git probe, not available to the mod",
|
|
5042
|
+
"git-unstaged": "needs a deeper git probe, not available to the mod",
|
|
5043
|
+
"git-untracked": "needs a deeper git probe, not available to the mod",
|
|
5044
|
+
"git-ahead-behind": "needs a deeper git probe, not available to the mod",
|
|
5045
|
+
"git-conflicts": "needs a deeper git probe, not available to the mod",
|
|
5046
|
+
"git-origin-owner": "needs a deeper git probe, not available to the mod",
|
|
5047
|
+
"git-origin-repo": "needs a deeper git probe, not available to the mod",
|
|
5048
|
+
"git-origin-owner-repo": "needs a deeper git probe, not available to the mod",
|
|
5049
|
+
"git-upstream-owner": "needs a deeper git probe, not available to the mod",
|
|
5050
|
+
"git-upstream-repo": "needs a deeper git probe, not available to the mod",
|
|
5051
|
+
"git-upstream-owner-repo": "needs a deeper git probe, not available to the mod",
|
|
5052
|
+
"git-is-fork": "needs a deeper git probe, not available to the mod",
|
|
5053
|
+
"git-review": "needs the gh/glab CLI, not available to the mod",
|
|
5054
|
+
"git-ci-status": "needs the gh/glab CLI, not available to the mod",
|
|
5055
|
+
link: "OSC8 links are not yet supported"
|
|
5056
|
+
};
|
|
5057
|
+
function baseStyle(raw, idFallback) {
|
|
5058
|
+
return {
|
|
5059
|
+
id: String(raw["id"] ?? `${idFallback}-${Math.random().toString(36).slice(2)}`),
|
|
5060
|
+
bg: typeof raw["backgroundColor"] === "string" ? raw["backgroundColor"] : void 0,
|
|
5061
|
+
rawValue: raw["rawValue"] === true || void 0,
|
|
5062
|
+
merge: raw["merge"] === true || void 0
|
|
5063
|
+
};
|
|
5064
|
+
}
|
|
4828
5065
|
function importCcstatusline(raw) {
|
|
4829
5066
|
const warnings = [];
|
|
4830
5067
|
if (!raw || typeof raw !== "object" || !Array.isArray(raw.lines)) {
|
|
4831
5068
|
warnings.push("input is not a ccstatusline config; using defaults");
|
|
4832
|
-
return { config:
|
|
5069
|
+
return { config: clone3(defaultConfig), warnings };
|
|
4833
5070
|
}
|
|
4834
5071
|
const lines = raw.lines.map(
|
|
4835
5072
|
(line) => (Array.isArray(line) ? line : []).flatMap((item) => {
|
|
@@ -4839,19 +5076,39 @@ function importCcstatusline(raw) {
|
|
|
4839
5076
|
return [];
|
|
4840
5077
|
}
|
|
4841
5078
|
const srcType = String(raw2["type"]);
|
|
5079
|
+
switch (srcType) {
|
|
5080
|
+
case "custom-text":
|
|
5081
|
+
case "custom-symbol":
|
|
5082
|
+
case "custom-command": {
|
|
5083
|
+
const field = srcType === "custom-text" ? "customText" : srcType === "custom-symbol" ? "customSymbol" : "commandPath";
|
|
5084
|
+
const payload = raw2[field];
|
|
5085
|
+
if (payload === void 0 || payload === null || String(payload) === "") {
|
|
5086
|
+
warnings.push(`dropped "${srcType}" \u2014 no ${field} value`);
|
|
5087
|
+
return [];
|
|
5088
|
+
}
|
|
5089
|
+
return [
|
|
5090
|
+
srcType === "custom-command" ? { ...baseStyle(raw2, srcType), type: "custom-command", command: String(payload) } : { ...baseStyle(raw2, srcType), type: "custom-text", text: String(payload) }
|
|
5091
|
+
];
|
|
5092
|
+
}
|
|
5093
|
+
case "flex-separator":
|
|
5094
|
+
return [{ id: baseStyle(raw2, srcType).id, type: "flex-separator" }];
|
|
5095
|
+
case "separator":
|
|
5096
|
+
warnings.push(
|
|
5097
|
+
'dropped "separator" \u2014 ccstatus uses a global separator (set it on the Powerline screen)'
|
|
5098
|
+
);
|
|
5099
|
+
return [];
|
|
5100
|
+
default:
|
|
5101
|
+
}
|
|
4842
5102
|
const type = Object.hasOwn(TYPE_MAP, srcType) ? TYPE_MAP[srcType] : void 0;
|
|
4843
|
-
if (
|
|
4844
|
-
|
|
5103
|
+
if (type) {
|
|
5104
|
+
return [{ ...baseStyle(raw2, type), type }];
|
|
5105
|
+
}
|
|
5106
|
+
if (Object.hasOwn(UNSUPPORTED, srcType)) {
|
|
5107
|
+
warnings.push(`dropped "${srcType}" \u2014 ${UNSUPPORTED[srcType]}`);
|
|
4845
5108
|
return [];
|
|
4846
5109
|
}
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
type,
|
|
4850
|
-
bg: typeof raw2["backgroundColor"] === "string" ? raw2["backgroundColor"] : void 0,
|
|
4851
|
-
rawValue: raw2["rawValue"] === true || void 0,
|
|
4852
|
-
merge: raw2["merge"] === true || void 0
|
|
4853
|
-
};
|
|
4854
|
-
return [mapped];
|
|
5110
|
+
warnings.push(`dropped unmapped ccstatusline item "${srcType}"`);
|
|
5111
|
+
return [];
|
|
4855
5112
|
})
|
|
4856
5113
|
);
|
|
4857
5114
|
const draft = { version: 1, surfaces: { band: { enabled: true, lines } } };
|
|
@@ -4946,6 +5203,8 @@ var sampleSnapshot = {
|
|
|
4946
5203
|
added: 1,
|
|
4947
5204
|
modified: 2,
|
|
4948
5205
|
deleted: 0,
|
|
5206
|
+
insertions: 124,
|
|
5207
|
+
deletions: 37,
|
|
4949
5208
|
ctxTokens: 42e3,
|
|
4950
5209
|
ctxPct: 21,
|
|
4951
5210
|
cached: 1e3,
|
|
@@ -4953,13 +5212,17 @@ var sampleSnapshot = {
|
|
|
4953
5212
|
output: 500,
|
|
4954
5213
|
total: 3500,
|
|
4955
5214
|
startedAt: 0,
|
|
4956
|
-
cost:
|
|
5215
|
+
cost: 0.42,
|
|
4957
5216
|
fivePct: 30,
|
|
4958
5217
|
fiveReset: null,
|
|
4959
5218
|
weekPct: 10,
|
|
4960
5219
|
weekReset: null,
|
|
4961
5220
|
blockReset: null,
|
|
4962
|
-
terminalWidth:
|
|
5221
|
+
terminalWidth: 120,
|
|
5222
|
+
sessionId: "sess-abc1234",
|
|
5223
|
+
ctxWindow: 2e5,
|
|
5224
|
+
gitSha: "a1b2c3d",
|
|
5225
|
+
outputStyle: null,
|
|
4963
5226
|
now: 65e3
|
|
4964
5227
|
};
|
|
4965
5228
|
|
|
@@ -4968,6 +5231,8 @@ var NUMBER_FIELDS = [
|
|
|
4968
5231
|
"added",
|
|
4969
5232
|
"modified",
|
|
4970
5233
|
"deleted",
|
|
5234
|
+
"insertions",
|
|
5235
|
+
"deletions",
|
|
4971
5236
|
"ctxTokens",
|
|
4972
5237
|
"ctxPct",
|
|
4973
5238
|
"cached",
|
|
@@ -4976,11 +5241,27 @@ var NUMBER_FIELDS = [
|
|
|
4976
5241
|
"total",
|
|
4977
5242
|
"startedAt",
|
|
4978
5243
|
"terminalWidth",
|
|
4979
|
-
"now"
|
|
5244
|
+
"now",
|
|
5245
|
+
"ctxWindow"
|
|
4980
5246
|
];
|
|
4981
5247
|
var NULLABLE_NUMBER_FIELDS = ["cost", "fivePct", "weekPct"];
|
|
4982
|
-
var STRING_FIELDS = [
|
|
4983
|
-
|
|
5248
|
+
var STRING_FIELDS = [
|
|
5249
|
+
"version",
|
|
5250
|
+
"model",
|
|
5251
|
+
"cwd",
|
|
5252
|
+
"gitRoot",
|
|
5253
|
+
"gitBranch",
|
|
5254
|
+
"gitWorktree",
|
|
5255
|
+
"sessionId",
|
|
5256
|
+
"gitSha"
|
|
5257
|
+
];
|
|
5258
|
+
var NULLABLE_STRING_FIELDS = [
|
|
5259
|
+
"effort",
|
|
5260
|
+
"fiveReset",
|
|
5261
|
+
"weekReset",
|
|
5262
|
+
"blockReset",
|
|
5263
|
+
"outputStyle"
|
|
5264
|
+
];
|
|
4984
5265
|
var BOOLEAN_FIELDS = ["repo"];
|
|
4985
5266
|
var isNum = (v) => typeof v === "number" && Number.isFinite(v);
|
|
4986
5267
|
function sanitize(parsed) {
|
|
@@ -5024,6 +5305,9 @@ export {
|
|
|
5024
5305
|
toAnsi,
|
|
5025
5306
|
COLORS,
|
|
5026
5307
|
isValidWhen,
|
|
5308
|
+
LINKABLE,
|
|
5309
|
+
linkedSurfaces,
|
|
5310
|
+
writeLinkedLines,
|
|
5027
5311
|
importCcstatusline,
|
|
5028
5312
|
rendererColor,
|
|
5029
5313
|
rendererBg,
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
var sub = process.argv[2];
|
|
6
6
|
if (sub === "statusline") {
|
|
7
|
-
const { runStatusline } = await import("./statusline-cmd-
|
|
7
|
+
const { runStatusline } = await import("./statusline-cmd-2YHMLVSM.js");
|
|
8
8
|
await runStatusline();
|
|
9
9
|
} else {
|
|
10
10
|
const { render } = await import("ink");
|
|
11
|
-
const { App } = await import("./app-
|
|
11
|
+
const { App } = await import("./app-WR7CHOQI.js");
|
|
12
12
|
render(/* @__PURE__ */ jsx(App, {}));
|
|
13
13
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sushant-kum/ccstatus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Interactive configurator (npx @sushant-kum/ccstatus) for the ccstatus Claude Code status bar — band, status line, pane, and threshold toasts from one config.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sushant Kumar",
|