@aemonge-dev/pi-stardeck 0.6.0 → 0.7.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/package.json +1 -1
- package/packages/pi-stardeck/src/deck.ts +79 -44
package/package.json
CHANGED
|
@@ -386,21 +386,25 @@ function globalLeft(state: HeaderDeckState, theme: Theme): string {
|
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
function projectDeckLeft(state: HeaderDeckState, theme: Theme, width: number): string {
|
|
389
|
-
// Line 1 left: the
|
|
390
|
-
//
|
|
391
|
-
// chips
|
|
392
|
-
|
|
393
|
-
const path =
|
|
389
|
+
// Line 1 left: the path; the git segment yields below 79 columns before
|
|
390
|
+
// the path does. The devbox marker moved to the line-1 corner with the
|
|
391
|
+
// companion chips (deck-machine-corner); the identity cluster never
|
|
392
|
+
// drops, so the path never carries it again.
|
|
393
|
+
const path = color(theme, 'success', ` \u{F07B} ${safeText(state.cwd)}`);
|
|
394
394
|
const gitSegment =
|
|
395
395
|
width >= 79 ? truncateToWidth(gitRight(state, theme), 52, '…') : '';
|
|
396
396
|
return gitSegment ? `${path} ${semanticSeparator(theme)} ${gitSegment}` : path;
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
-
|
|
399
|
+
type CompanionSpec = {
|
|
400
400
|
keys: readonly string[];
|
|
401
401
|
icons: readonly string[];
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
/** Render the chip bracketed even at one icon (engram identity). */
|
|
403
|
+
bracket?: boolean;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
const KNOWN_COMPANION_ICONS: ReadonlyArray<CompanionSpec> = [
|
|
407
|
+
{ keys: ['engram'], icons: ['\u{21BB}'], bracket: true },
|
|
404
408
|
{ keys: ['graphify'], icons: ['\u{232C}'] },
|
|
405
409
|
{ keys: ['appa', 'openappa'], icons: ['\u{26E8}'] },
|
|
406
410
|
];
|
|
@@ -424,15 +428,22 @@ function extensionStatusCodes(state: HeaderDeckState, theme: Theme): string {
|
|
|
424
428
|
texts.set(item.key, item.text);
|
|
425
429
|
}
|
|
426
430
|
const parts: Array<{ bare: boolean; text: string }> = [];
|
|
431
|
+
if (state.devbox) {
|
|
432
|
+
// Corner lead chip (deck-machine-corner): the devbox marker joins
|
|
433
|
+
// the identity cluster ahead of the companions, success-colored as
|
|
434
|
+
// it was as a path prefix.
|
|
435
|
+
parts.push({ bare: false, text: color(theme, 'success', '[\u{F01A7}]', true) });
|
|
436
|
+
}
|
|
427
437
|
for (const companion of KNOWN_COMPANION_ICONS) {
|
|
428
438
|
const published = companion.keys
|
|
429
439
|
.map((key) => texts.get(key))
|
|
430
440
|
.find((text) => text !== undefined);
|
|
431
441
|
for (const key of companion.keys) texts.delete(key);
|
|
432
442
|
const joined = companion.icons.join(' ');
|
|
433
|
-
const
|
|
443
|
+
const bracketed = companion.bracket === true || companion.icons.length > 1;
|
|
444
|
+
const chip = bracketed ? `[${joined}]` : joined;
|
|
434
445
|
parts.push({
|
|
435
|
-
bare:
|
|
446
|
+
bare: !bracketed,
|
|
436
447
|
text: color(
|
|
437
448
|
theme,
|
|
438
449
|
companionIconColor(published, published !== undefined),
|
|
@@ -516,37 +527,64 @@ function telemetryRowLeft(state: HeaderDeckState, theme: Theme): string {
|
|
|
516
527
|
return modelGroupLeft(state, theme);
|
|
517
528
|
}
|
|
518
529
|
|
|
519
|
-
function
|
|
530
|
+
export function machineCornerSegments(
|
|
520
531
|
state: HeaderDeckState,
|
|
521
532
|
theme: Theme,
|
|
522
533
|
nowMs = Date.now(),
|
|
523
|
-
): string {
|
|
524
|
-
//
|
|
525
|
-
// quota flame with its countdown,
|
|
526
|
-
//
|
|
527
|
-
|
|
534
|
+
): string[] {
|
|
535
|
+
// Machine corner (deck-machine-corner): icon-led machine readings for
|
|
536
|
+
// the line-1 corner — coding quota flame with its countdown, CPU,
|
|
537
|
+
// memory, MCP availability, global cost — in that frozen order, joined
|
|
538
|
+
// by minor separators. Segments yield right-to-left on narrow frames.
|
|
539
|
+
const segments: string[] = [];
|
|
540
|
+
const flame = windowQuotaTiles(state, theme, nowMs);
|
|
541
|
+
if (flame !== '') segments.push(flame);
|
|
528
542
|
const resources = state.resources;
|
|
529
543
|
if (resources) {
|
|
530
544
|
const resourceColor =
|
|
531
545
|
resources.cpuWarning || resources.memoryWarning ? 'warning' : 'accent';
|
|
532
|
-
|
|
533
|
-
color(theme, resourceColor,
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
546
|
+
segments.push(
|
|
547
|
+
color(theme, resourceColor, `\u{F035B} ${formatDeckCpu(resources.cpuPercent)}`),
|
|
548
|
+
);
|
|
549
|
+
segments.push(
|
|
550
|
+
color(
|
|
551
|
+
theme,
|
|
552
|
+
resourceColor,
|
|
553
|
+
`\u{F061A} ${formatDeckBytes(resources.memoryBytes)}`,
|
|
554
|
+
),
|
|
555
|
+
);
|
|
537
556
|
}
|
|
538
557
|
if (state.mcp) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
558
|
+
segments.push(color(theme, 'accent', `${state.mcp.healthy}/${state.mcp.total}`));
|
|
559
|
+
}
|
|
560
|
+
const cost = costTile(state, theme);
|
|
561
|
+
if (cost !== '') segments.push(cost);
|
|
562
|
+
return segments;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function deckCornerRight(
|
|
566
|
+
state: HeaderDeckState,
|
|
567
|
+
theme: Theme,
|
|
568
|
+
width: number,
|
|
569
|
+
nowMs = Date.now(),
|
|
570
|
+
): string {
|
|
571
|
+
// Line 1 corner: the identity cluster (devbox lead, companion chips)
|
|
572
|
+
// split from the machine group by one major separator. Machine segments
|
|
573
|
+
// yield right-to-left (cost first) before the path truncates below a
|
|
574
|
+
// 20-column floor; the identity cluster never drops (always-visible
|
|
575
|
+
// contract).
|
|
576
|
+
const identity = extensionStatusCodes(state, theme);
|
|
577
|
+
const segments = machineCornerSegments(state, theme, nowMs);
|
|
578
|
+
const pathFloor = 20;
|
|
579
|
+
for (let keep = segments.length; keep >= 0; keep -= 1) {
|
|
580
|
+
const tail = segments.slice(0, keep).join(` ${minorSeparator(theme)} `);
|
|
581
|
+
const corner =
|
|
582
|
+
tail === '' ? identity : `${identity} ${semanticSeparator(theme)} ${tail}`;
|
|
583
|
+
if (keep === 0 || width - visibleWidth(corner) - 1 >= pathFloor) {
|
|
584
|
+
return corner;
|
|
585
|
+
}
|
|
542
586
|
}
|
|
543
|
-
return
|
|
544
|
-
windowQuotaTiles(state, theme, nowMs),
|
|
545
|
-
machineSegments.join(` ${semanticSeparator(theme)} `),
|
|
546
|
-
costTile(state, theme),
|
|
547
|
-
]
|
|
548
|
-
.filter((group) => group !== '')
|
|
549
|
-
.join(` ${semanticSeparator(theme)} `);
|
|
587
|
+
return identity;
|
|
550
588
|
}
|
|
551
589
|
|
|
552
590
|
function modelGroupLeft(state: HeaderDeckState, theme: Theme): string {
|
|
@@ -760,19 +798,16 @@ export function renderHeaderDeck(
|
|
|
760
798
|
turnCostTile(state, theme),
|
|
761
799
|
boundedWidth,
|
|
762
800
|
);
|
|
763
|
-
// Line 4 (
|
|
764
|
-
//
|
|
765
|
-
//
|
|
766
|
-
//
|
|
767
|
-
// narrow-frame yield (the right group renders only when it fits beside
|
|
768
|
-
// the engine group at full width; the engine group never yields to it).
|
|
801
|
+
// Line 4 (deck-machine-corner amendment): the engine group holds the
|
|
802
|
+
// row's left end; the right end is notice-only. The machine group moved
|
|
803
|
+
// to the line-1 corner, so notices can no longer starve machine
|
|
804
|
+
// readings — the old wholesale yield is gone with the group itself.
|
|
769
805
|
const engineGroup = telemetryRowLeft(state, theme);
|
|
770
806
|
const noticeGroup = noticeTile(state, theme);
|
|
771
|
-
const rightGroup = noticeGroup !== '' ? noticeGroup : telemetryRowRight(state, theme);
|
|
772
807
|
const telemetryRow =
|
|
773
|
-
|
|
774
|
-
visibleWidth(engineGroup) + 1 + visibleWidth(
|
|
775
|
-
? alignedSingleRow(engineGroup,
|
|
808
|
+
noticeGroup !== '' &&
|
|
809
|
+
visibleWidth(engineGroup) + 1 + visibleWidth(noticeGroup) <= boundedWidth
|
|
810
|
+
? alignedSingleRow(engineGroup, noticeGroup, boundedWidth)
|
|
776
811
|
: fit(engineGroup, boundedWidth);
|
|
777
812
|
|
|
778
813
|
// Band adjacency (Human-directed, accepted mockups; third 2.4
|
|
@@ -781,17 +816,17 @@ export function renderHeaderDeck(
|
|
|
781
816
|
// line 4; pi's own prompt chrome below closes the visual block — while
|
|
782
817
|
// the internal seams stay dotted ┈ between lines 2 and 3 and between
|
|
783
818
|
// line 3 (spans rows included) and line 4.
|
|
784
|
-
const
|
|
819
|
+
const corner = deckCornerRight(state, theme, boundedWidth);
|
|
785
820
|
const alert = statusAlertTile(
|
|
786
821
|
state,
|
|
787
|
-
Math.max(0, boundedWidth - visibleWidth(
|
|
822
|
+
Math.max(0, boundedWidth - visibleWidth(corner) - 2),
|
|
788
823
|
theme,
|
|
789
824
|
lineColor,
|
|
790
825
|
);
|
|
791
826
|
const rows = [
|
|
792
827
|
alignedSingleRow(
|
|
793
828
|
projectDeckLeft(state, theme, boundedWidth),
|
|
794
|
-
alert ? `${alert} ${
|
|
829
|
+
alert ? `${alert} ${corner}` : corner,
|
|
795
830
|
boundedWidth,
|
|
796
831
|
),
|
|
797
832
|
solidRule,
|