@cortexkit/aft-opencode 0.63.5 → 0.65.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/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config-live-reload.d.ts +4 -28
- package/dist/config-live-reload.d.ts.map +1 -1
- package/dist/config.d.ts +11 -40
- package/dist/config.d.ts.map +1 -1
- package/dist/entry/server.js +1726 -674
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1726 -674
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/shared/session-directory.d.ts +11 -4
- package/dist/shared/session-directory.d.ts.map +1 -1
- package/dist/shared/status.d.ts +2 -6
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/subc-tool-schemas.d.ts +4 -3
- package/dist/subc-tool-schemas.d.ts.map +1 -1
- package/dist/tool-registration.d.ts +1 -1
- package/dist/tool-registration.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts +11 -17
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash_watch.d.ts +6 -3
- package/dist/tools/bash_watch.d.ts.map +1 -1
- package/dist/tools/definitions/v2.d.ts +26 -1
- package/dist/tools/definitions/v2.d.ts.map +1 -1
- package/dist/tools/inspect.d.ts +0 -15
- package/dist/tools/inspect.d.ts.map +1 -1
- package/dist/tui/preferences.d.ts +1 -1
- package/dist/tui/shared-sidebar.d.ts +4 -0
- package/dist/tui/shared-sidebar.d.ts.map +1 -0
- package/dist/tui/v2-status.d.ts +3 -2
- package/dist/tui/v2-status.d.ts.map +1 -1
- package/dist/v2-session-lifecycle.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts +1 -5
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +14 -12
- package/src/shared/session-directory.ts +90 -17
- package/src/shared/status.ts +6 -26
- package/src/tui/index.tsx +8 -28
- package/src/tui/preferences.ts +1 -1
- package/src/tui/shared-sidebar.ts +14 -0
- package/src/tui/sidebar-view.tsx +257 -283
- package/src/tui/v2-status.ts +5 -14
- package/src/tui-compiled/index.tsx +6 -44
- package/src/tui-compiled/preferences.ts +1 -1
- package/src/tui-compiled/shared-sidebar-host.tsx +816 -0
- package/src/tui-compiled/shared-sidebar-local.tsx +816 -0
- package/src/tui-compiled/shared-sidebar.LICENSE +21 -0
- package/src/tui-compiled/shared-sidebar.ts +14 -0
- package/src/tui-compiled/sidebar-view.tsx +185 -261
- package/src/tui-compiled/sidebar.tsx +1 -0
- package/src/tui-compiled/v2-status.ts +5 -14
- package/src/tui-compiled/v2.tsx +1 -0
package/src/tui/sidebar-view.tsx
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
seedCollapsedFromPrefs,
|
|
34
34
|
watchTuiPreferences,
|
|
35
35
|
} from "./preferences";
|
|
36
|
+
import { SidebarFrame, type SidebarTheme } from "./shared-sidebar";
|
|
36
37
|
|
|
37
38
|
const SINGLE_BORDER = { type: "single" } as any;
|
|
38
39
|
|
|
@@ -301,7 +302,6 @@ export function degradedReasonLabel(reason: string): string {
|
|
|
301
302
|
|
|
302
303
|
export interface HealthLights {
|
|
303
304
|
diagnostics: HealthLightTone;
|
|
304
|
-
code: HealthLightTone;
|
|
305
305
|
todos: HealthLightTone;
|
|
306
306
|
}
|
|
307
307
|
|
|
@@ -317,15 +317,9 @@ export function collapsedHealthLights(statusBar: StatusBar | undefined): HealthL
|
|
|
317
317
|
: statusBar.errors === 0 && statusBar.warnings === 0
|
|
318
318
|
? "ok"
|
|
319
319
|
: "muted";
|
|
320
|
-
const codeValues = [statusBar.dead_code, statusBar.unused_exports, statusBar.duplicates];
|
|
321
|
-
const code: HealthLightTone = codeValues.some((value) => value !== undefined && value > 0)
|
|
322
|
-
? "warn"
|
|
323
|
-
: codeValues.every((value) => value === 0)
|
|
324
|
-
? "ok"
|
|
325
|
-
: "muted";
|
|
326
320
|
const todos: HealthLightTone =
|
|
327
321
|
statusBar.todos === undefined ? "muted" : statusBar.todos > 0 ? "warn" : "ok";
|
|
328
|
-
return { diagnostics,
|
|
322
|
+
return { diagnostics, todos };
|
|
329
323
|
}
|
|
330
324
|
|
|
331
325
|
export interface AftSidebarPanelProps {
|
|
@@ -436,317 +430,297 @@ export const AftSidebarPanel = (props: AftSidebarPanelProps) => {
|
|
|
436
430
|
// entry. Keep this muted and separate from the DEGRADED badge above.
|
|
437
431
|
const worktreeNote = () => worktreeCacheRoleNote(s()?.cache_role);
|
|
438
432
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
paddingBottom={1}
|
|
447
|
-
paddingLeft={1}
|
|
448
|
-
paddingRight={1}
|
|
449
|
-
>
|
|
450
|
-
{/* Header: triangle toggle + AFT badge + binary version + degraded badge.
|
|
451
|
-
Clicking the header row collapses/expands the panel (mirrors OpenCode's
|
|
452
|
-
native MCP sidebar section). Only interactive once initialized — the
|
|
453
|
-
lazy-bridge placeholder has nothing to collapse. */}
|
|
454
|
-
<box
|
|
455
|
-
flexDirection="row"
|
|
456
|
-
justifyContent="space-between"
|
|
457
|
-
alignItems="center"
|
|
458
|
-
onMouseDown={() => {
|
|
459
|
-
if (notInitialized()) return;
|
|
460
|
-
props.onToggleCollapsed();
|
|
461
|
-
}}
|
|
462
|
-
>
|
|
463
|
-
<box flexDirection="row" alignItems="center">
|
|
464
|
-
{/* Triangle lives inside the accent badge so the toggle reads as one
|
|
465
|
-
unit: "▶ AFT" / "▼ AFT". Hidden pre-init (nothing to collapse). */}
|
|
466
|
-
<box paddingLeft={1} paddingRight={1} backgroundColor={props.palette.accent}>
|
|
467
|
-
<text fg={badgeForeground(props.palette.accent, props.palette.background)}>
|
|
468
|
-
<b>
|
|
469
|
-
{notInitialized() ? "" : props.collapsed ? "▶ " : "▼ "}
|
|
470
|
-
{props.prefs.header.label}
|
|
471
|
-
</b>
|
|
472
|
-
</text>
|
|
473
|
-
</box>
|
|
474
|
-
{s()?.degraded && degradedHeaderMarker(s()?.degraded_reasons ?? []).calm && (
|
|
475
|
-
<box marginLeft={1}>
|
|
476
|
-
<text fg={props.palette.warning}>
|
|
477
|
-
{degradedHeaderMarker(s()?.degraded_reasons ?? []).text}
|
|
478
|
-
</text>
|
|
479
|
-
</box>
|
|
480
|
-
)}
|
|
481
|
-
{s()?.degraded && !degradedHeaderMarker(s()?.degraded_reasons ?? []).calm && (
|
|
482
|
-
<box
|
|
483
|
-
paddingLeft={1}
|
|
484
|
-
paddingRight={1}
|
|
485
|
-
marginLeft={1}
|
|
486
|
-
backgroundColor={props.palette.warning}
|
|
487
|
-
>
|
|
488
|
-
<text fg={badgeForeground(props.palette.warning, props.palette.background)}>
|
|
489
|
-
<b>{degradedHeaderMarker(s()?.degraded_reasons ?? []).text}</b>
|
|
490
|
-
</text>
|
|
491
|
-
</box>
|
|
492
|
-
)}
|
|
433
|
+
const headerMarkers = () => (
|
|
434
|
+
<>
|
|
435
|
+
{s()?.degraded && degradedHeaderMarker(s()?.degraded_reasons ?? []).calm && (
|
|
436
|
+
<box marginLeft={1}>
|
|
437
|
+
<text fg={props.palette.warning}>
|
|
438
|
+
{degradedHeaderMarker(s()?.degraded_reasons ?? []).text}
|
|
439
|
+
</text>
|
|
493
440
|
</box>
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
441
|
+
)}
|
|
442
|
+
{s()?.degraded && !degradedHeaderMarker(s()?.degraded_reasons ?? []).calm && (
|
|
443
|
+
<box
|
|
444
|
+
paddingLeft={1}
|
|
445
|
+
paddingRight={1}
|
|
446
|
+
marginLeft={1}
|
|
447
|
+
backgroundColor={props.palette.warning}
|
|
448
|
+
>
|
|
449
|
+
<text fg={badgeForeground(props.palette.warning, props.palette.background)}>
|
|
450
|
+
<b>{degradedHeaderMarker(s()?.degraded_reasons ?? []).text}</b>
|
|
451
|
+
</text>
|
|
452
|
+
</box>
|
|
453
|
+
)}
|
|
454
|
+
</>
|
|
455
|
+
);
|
|
498
456
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
457
|
+
const notices = () => (
|
|
458
|
+
<>
|
|
459
|
+
{/* These explanations remain visible when the metric rows are collapsed. */}
|
|
502
460
|
{s()?.degraded && degradedSummary() && (
|
|
503
461
|
<box marginTop={1} width="100%">
|
|
504
462
|
<text fg={props.palette.warning}>⚠ {degradedSummary()}</text>
|
|
505
463
|
</box>
|
|
506
464
|
)}
|
|
507
|
-
|
|
508
465
|
{!notInitialized() && worktreeNote() && (
|
|
509
466
|
<box marginTop={1} width="100%">
|
|
510
467
|
<text fg={props.palette.textMuted}>{worktreeNote()}</text>
|
|
511
468
|
</box>
|
|
512
469
|
)}
|
|
513
|
-
|
|
514
|
-
{/* Lazy-bridge placeholder. AFT skips spawning the `aft` binary at
|
|
515
|
-
plugin init to keep memory/CPU low on OpenCode Desktop sessions
|
|
516
|
-
that have many projects pinned in the sidebar. The RPC server
|
|
517
|
-
returns a synthetic `cache_role === "not_initialized"` snapshot
|
|
518
|
-
until the first tool call routes through `callBridge()` and warms
|
|
519
|
-
the bridge. Show the explanatory message instead of empty status
|
|
520
|
-
rows so users understand why metrics are blank. */}
|
|
521
470
|
{notInitialized() && (
|
|
522
471
|
<box marginTop={1} width="100%">
|
|
523
472
|
{s()!.config_error ? (
|
|
524
|
-
// Config error state: no bridge will ever start in this process,
|
|
525
|
-
// so the placeholder text would mislead; show the error instead.
|
|
526
473
|
<text fg={props.palette.error}>✖ {s()!.message}</text>
|
|
527
474
|
) : (
|
|
528
475
|
<text fg={props.palette.textMuted}>{s()!.message || NOT_STARTED_STATUS_TEXT}</text>
|
|
529
476
|
)}
|
|
530
477
|
</box>
|
|
531
478
|
)}
|
|
479
|
+
</>
|
|
480
|
+
);
|
|
532
481
|
|
|
533
|
-
|
|
482
|
+
return (
|
|
483
|
+
<box
|
|
484
|
+
width="100%"
|
|
485
|
+
flexDirection="column"
|
|
486
|
+
border={SINGLE_BORDER}
|
|
487
|
+
borderColor={props.palette.border}
|
|
488
|
+
paddingTop={1}
|
|
489
|
+
paddingBottom={1}
|
|
490
|
+
paddingLeft={1}
|
|
491
|
+
paddingRight={1}
|
|
492
|
+
>
|
|
493
|
+
<SidebarFrame
|
|
494
|
+
header={{
|
|
495
|
+
badge: props.prefs.header.label,
|
|
496
|
+
version:
|
|
497
|
+
!notInitialized() && props.prefs.header.showVersion
|
|
498
|
+
? `v${s()?.version ?? props.pluginVersion}`
|
|
499
|
+
: undefined,
|
|
500
|
+
afterBadge: headerMarkers,
|
|
501
|
+
}}
|
|
502
|
+
accounts={[]}
|
|
503
|
+
theme={
|
|
504
|
+
{
|
|
505
|
+
...props.palette,
|
|
506
|
+
// The shared background role is used only as the badge foreground.
|
|
507
|
+
background: badgeForeground(props.palette.accent, props.palette.background),
|
|
508
|
+
} as SidebarTheme
|
|
509
|
+
}
|
|
510
|
+
appearance={{
|
|
511
|
+
barWidth: 0,
|
|
512
|
+
barFilledChar: "",
|
|
513
|
+
barEmptyChar: "",
|
|
514
|
+
warnThreshold: 70,
|
|
515
|
+
errorThreshold: 90,
|
|
516
|
+
}}
|
|
517
|
+
showQuota={false}
|
|
518
|
+
now={0}
|
|
519
|
+
collapsed={props.collapsed}
|
|
520
|
+
collapsible={!notInitialized()}
|
|
521
|
+
onToggle={props.onToggleCollapsed}
|
|
522
|
+
collapsedSections={() => (
|
|
523
|
+
<>
|
|
524
|
+
{notices()}
|
|
525
|
+
{/* Collapsed view — condensed status dots + compact compression. Shown
|
|
534
526
|
only when initialized AND collapsed. Three rows mirroring the section
|
|
535
527
|
order of the expanded grid. */}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
528
|
+
{!notInitialized() && props.collapsed && (
|
|
529
|
+
<box width="100%" flexDirection="column">
|
|
530
|
+
{props.prefs.sections.searchIndex && (
|
|
531
|
+
<CollapsedRow palette={props.palette} label="Search Index">
|
|
532
|
+
<text fg={toneColor(props.palette, searchStatus().tone)}>●</text>
|
|
533
|
+
</CollapsedRow>
|
|
534
|
+
)}
|
|
535
|
+
{props.prefs.sections.semanticIndex && (
|
|
536
|
+
<CollapsedRow palette={props.palette} label="Semantic Index">
|
|
537
|
+
<text fg={toneColor(props.palette, semanticStatus().tone)}>●</text>
|
|
538
|
+
</CollapsedRow>
|
|
539
|
+
)}
|
|
540
|
+
{props.prefs.sections.codeHealth && collapsedHealthLights(statusBar()) && (
|
|
541
|
+
<CollapsedRow palette={props.palette} label="Code Health">
|
|
542
|
+
<box flexDirection="row" gap={1}>
|
|
543
|
+
<text
|
|
544
|
+
fg={toneColor(
|
|
545
|
+
props.palette,
|
|
546
|
+
collapsedHealthLights(statusBar())!.diagnostics,
|
|
547
|
+
)}
|
|
548
|
+
>
|
|
549
|
+
●
|
|
550
|
+
</text>
|
|
551
|
+
<text
|
|
552
|
+
fg={toneColor(props.palette, collapsedHealthLights(statusBar())!.todos)}
|
|
553
|
+
>
|
|
554
|
+
●
|
|
555
|
+
</text>
|
|
556
|
+
</box>
|
|
557
|
+
</CollapsedRow>
|
|
558
|
+
)}
|
|
559
|
+
{props.prefs.sections.compression &&
|
|
560
|
+
collapsedCompressionValue(s()?.compression) && (
|
|
561
|
+
<CollapsedRow palette={props.palette} label="Compression">
|
|
562
|
+
<text fg={props.palette.textMuted}>
|
|
563
|
+
<b>{collapsedCompressionValue(s()?.compression)}</b>
|
|
564
|
+
</text>
|
|
565
|
+
</CollapsedRow>
|
|
566
|
+
)}
|
|
562
567
|
</box>
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
label="Disk"
|
|
598
|
-
value={formatBytes(trigramBytes())}
|
|
599
|
-
tone="muted"
|
|
600
|
-
/>
|
|
601
|
-
</>
|
|
602
|
-
)}
|
|
568
|
+
)}
|
|
569
|
+
</>
|
|
570
|
+
)}
|
|
571
|
+
sections={() => (
|
|
572
|
+
<>
|
|
573
|
+
{notices()}
|
|
574
|
+
{/* Search index */}
|
|
575
|
+
{!notInitialized() && !props.collapsed && (
|
|
576
|
+
<>
|
|
577
|
+
{props.prefs.sections.searchIndex && (
|
|
578
|
+
<>
|
|
579
|
+
<SectionHeader palette={props.palette} title="Search Index" />
|
|
580
|
+
<StatRow
|
|
581
|
+
palette={props.palette}
|
|
582
|
+
label="Status"
|
|
583
|
+
value={searchStatus().label}
|
|
584
|
+
tone={searchStatus().tone}
|
|
585
|
+
/>
|
|
586
|
+
{(s()?.search_index?.files ?? null) != null && (
|
|
587
|
+
<StatRow
|
|
588
|
+
palette={props.palette}
|
|
589
|
+
label="Files"
|
|
590
|
+
value={formatCount(s()!.search_index.files)}
|
|
591
|
+
tone="muted"
|
|
592
|
+
/>
|
|
593
|
+
)}
|
|
594
|
+
<StatRow
|
|
595
|
+
palette={props.palette}
|
|
596
|
+
label="Disk"
|
|
597
|
+
value={formatBytes(trigramBytes())}
|
|
598
|
+
tone="muted"
|
|
599
|
+
/>
|
|
600
|
+
</>
|
|
601
|
+
)}
|
|
603
602
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
603
|
+
{props.prefs.sections.semanticIndex && (
|
|
604
|
+
<>
|
|
605
|
+
<SectionHeader palette={props.palette} title="Semantic Index" />
|
|
606
|
+
<StatRow
|
|
607
|
+
palette={props.palette}
|
|
608
|
+
label="Status"
|
|
609
|
+
value={semanticStatus().label}
|
|
610
|
+
tone={semanticStatus().tone}
|
|
611
|
+
/>
|
|
612
|
+
{semanticRefreshing() && (
|
|
613
|
+
<box width="100%">
|
|
614
|
+
<text fg={props.palette.textMuted}>{semanticRefreshing()}</text>
|
|
615
|
+
</box>
|
|
616
|
+
)}
|
|
617
|
+
{/* Show loading progress so background work does not look stalled. */}
|
|
618
|
+
{s()?.semantic_index?.status === "loading" &&
|
|
619
|
+
s()?.semantic_index?.entries_total != null &&
|
|
620
|
+
s()!.semantic_index.entries_total! > 0 && (
|
|
621
|
+
<StatRow
|
|
622
|
+
palette={props.palette}
|
|
623
|
+
label="Progress"
|
|
624
|
+
value={`${formatCount(s()!.semantic_index.entries_done)} / ${formatCount(
|
|
625
|
+
s()!.semantic_index.entries_total,
|
|
626
|
+
)}`}
|
|
627
|
+
tone="warn"
|
|
628
|
+
/>
|
|
629
|
+
)}
|
|
630
|
+
{(s()?.semantic_index?.entries ?? null) != null && (
|
|
631
|
+
<StatRow
|
|
632
|
+
palette={props.palette}
|
|
633
|
+
label="Entries"
|
|
634
|
+
value={formatCount(s()!.semantic_index.entries)}
|
|
635
|
+
tone="muted"
|
|
636
|
+
/>
|
|
637
|
+
)}
|
|
638
|
+
<StatRow
|
|
639
|
+
palette={props.palette}
|
|
640
|
+
label="Disk"
|
|
641
|
+
value={formatBytes(semanticBytes())}
|
|
642
|
+
tone="muted"
|
|
643
|
+
/>
|
|
644
|
+
</>
|
|
631
645
|
)}
|
|
632
|
-
{(s()?.semantic_index?.entries ?? null) != null && (
|
|
633
|
-
<StatRow
|
|
634
|
-
palette={props.palette}
|
|
635
|
-
label="Entries"
|
|
636
|
-
value={formatCount(s()!.semantic_index.entries)}
|
|
637
|
-
tone="muted"
|
|
638
|
-
/>
|
|
639
|
-
)}
|
|
640
|
-
<StatRow
|
|
641
|
-
palette={props.palette}
|
|
642
|
-
label="Disk"
|
|
643
|
-
value={formatBytes(semanticBytes())}
|
|
644
|
-
tone="muted"
|
|
645
|
-
/>
|
|
646
|
-
</>
|
|
647
|
-
)}
|
|
648
646
|
|
|
649
|
-
|
|
647
|
+
{/* Human health values are optional. A category stays absent until the
|
|
650
648
|
server proves it, rather than appearing as a clean zero. */}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
)}
|
|
689
|
-
{statusBar()!.unused_exports !== undefined && (
|
|
690
|
-
<StatRow
|
|
691
|
-
palette={props.palette}
|
|
692
|
-
label="Unused Exports"
|
|
693
|
-
value={formatCount(statusBar()!.unused_exports)}
|
|
694
|
-
tone="muted"
|
|
695
|
-
/>
|
|
696
|
-
)}
|
|
697
|
-
{statusBar()!.duplicates !== undefined && (
|
|
698
|
-
<StatRow
|
|
699
|
-
palette={props.palette}
|
|
700
|
-
label="Duplicates"
|
|
701
|
-
value={formatCount(statusBar()!.duplicates)}
|
|
702
|
-
tone="muted"
|
|
703
|
-
/>
|
|
704
|
-
)}
|
|
705
|
-
{statusBar()!.todos !== undefined && (
|
|
706
|
-
<StatRow
|
|
707
|
-
palette={props.palette}
|
|
708
|
-
label="TODOs"
|
|
709
|
-
value={formatCount(statusBar()!.todos)}
|
|
710
|
-
tone="muted"
|
|
711
|
-
/>
|
|
712
|
-
)}
|
|
713
|
-
</>
|
|
714
|
-
)}
|
|
649
|
+
{props.prefs.sections.codeHealth && statusBar() && (
|
|
650
|
+
<>
|
|
651
|
+
<SectionHeader palette={props.palette} title="Code Health" />
|
|
652
|
+
{(statusBar()!.disabled_categories ?? []).map((key) => (
|
|
653
|
+
<StatRow
|
|
654
|
+
palette={props.palette}
|
|
655
|
+
label={key.replaceAll("_", " ")}
|
|
656
|
+
value="○ off"
|
|
657
|
+
tone="muted"
|
|
658
|
+
/>
|
|
659
|
+
))}
|
|
660
|
+
{statusBar()!.errors !== undefined && (
|
|
661
|
+
<StatRow
|
|
662
|
+
palette={props.palette}
|
|
663
|
+
label="Errors"
|
|
664
|
+
value={formatCount(statusBar()!.errors)}
|
|
665
|
+
tone={statusBar()!.errors! > 0 ? "err" : "muted"}
|
|
666
|
+
/>
|
|
667
|
+
)}
|
|
668
|
+
{statusBar()!.warnings !== undefined && (
|
|
669
|
+
<StatRow
|
|
670
|
+
palette={props.palette}
|
|
671
|
+
label="Warnings"
|
|
672
|
+
value={formatCount(statusBar()!.warnings)}
|
|
673
|
+
tone={statusBar()!.warnings! > 0 ? "warn" : "muted"}
|
|
674
|
+
/>
|
|
675
|
+
)}
|
|
676
|
+
{statusBar()!.todos !== undefined && (
|
|
677
|
+
<StatRow
|
|
678
|
+
palette={props.palette}
|
|
679
|
+
label="TODOs"
|
|
680
|
+
value={formatCount(statusBar()!.todos)}
|
|
681
|
+
tone="muted"
|
|
682
|
+
/>
|
|
683
|
+
)}
|
|
684
|
+
</>
|
|
685
|
+
)}
|
|
715
686
|
|
|
716
|
-
|
|
687
|
+
{/* Compression aggregates. Tabular layout matching Search/Semantic
|
|
717
688
|
Index above: each scope ("Session", "Project") renders as a
|
|
718
689
|
subheader followed by two StatRows (Tokens Saved, Compression
|
|
719
690
|
Ratio). Keeps numbers right-aligned in the value column instead
|
|
720
691
|
of jamming them after the label on the same line. */}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
692
|
+
{props.prefs.sections.compression && compressionRows().length > 0 && (
|
|
693
|
+
<>
|
|
694
|
+
<SectionHeader palette={props.palette} title="Compression" />
|
|
695
|
+
{compressionRows().map((row) =>
|
|
696
|
+
row.kind === "scope" ? (
|
|
697
|
+
<box width="100%">
|
|
698
|
+
<text fg={props.palette.text}>{row.label}</text>
|
|
699
|
+
</box>
|
|
700
|
+
) : (
|
|
701
|
+
<StatRow
|
|
702
|
+
palette={props.palette}
|
|
703
|
+
label={row.label}
|
|
704
|
+
value={row.value}
|
|
705
|
+
tone="muted"
|
|
706
|
+
/>
|
|
707
|
+
),
|
|
708
|
+
)}
|
|
709
|
+
</>
|
|
710
|
+
)}
|
|
740
711
|
|
|
741
|
-
|
|
712
|
+
{/* Surface failures clearly so users know to act (install ONNX Runtime,
|
|
742
713
|
fix config, etc.) rather than silently leaving the panel "off". */}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
714
|
+
{s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && (
|
|
715
|
+
<box marginTop={1} width="100%">
|
|
716
|
+
<text fg={props.palette.error}>⚠ {s()!.semantic_index.error}</text>
|
|
717
|
+
</box>
|
|
718
|
+
)}
|
|
719
|
+
</>
|
|
720
|
+
)}
|
|
721
|
+
</>
|
|
722
|
+
)}
|
|
723
|
+
/>
|
|
750
724
|
</box>
|
|
751
725
|
);
|
|
752
726
|
};
|
package/src/tui/v2-status.ts
CHANGED
|
@@ -27,8 +27,9 @@ function diagnosticsPart(bar: StatusBar): string {
|
|
|
27
27
|
* The V2 footer segment. "AFT starting…" is only true before the bridge has
|
|
28
28
|
* delivered a real snapshot. After that the footer shows every health category
|
|
29
29
|
* that has a value and `?` for any that does not, because a producer that is
|
|
30
|
-
* unavailable (for example
|
|
31
|
-
*
|
|
30
|
+
* unavailable (for example no language server) can leave the complete
|
|
31
|
+
* `status_bar` missing for the whole session. Dead code, unused exports and
|
|
32
|
+
* duplicates are not shown: they are computed only by aft_inspect.
|
|
32
33
|
*/
|
|
33
34
|
export function formatAftStatusSegment(status: AftStatusSnapshot | null): string {
|
|
34
35
|
// The config error state never produces a real snapshot; say so instead of
|
|
@@ -36,12 +37,7 @@ export function formatAftStatusSegment(status: AftStatusSnapshot | null): string
|
|
|
36
37
|
if (status?.config_error) return "AFT config error";
|
|
37
38
|
if (!status || status.cache_role === "not_initialized") return "AFT starting…";
|
|
38
39
|
const bar: StatusBar = status.status_bar ?? status.status_bar_values ?? {};
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
`AFT ${diagnosticsPart(bar)} | ` +
|
|
42
|
-
`${stale}D${count(bar.dead_code, bar.disabled_categories?.includes("dead_code"))} U${count(bar.unused_exports, bar.disabled_categories?.includes("unused_exports"))} ` +
|
|
43
|
-
`C${count(bar.duplicates, bar.disabled_categories?.includes("duplicates"))} | T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`
|
|
44
|
-
);
|
|
40
|
+
return `AFT ${diagnosticsPart(bar)} | T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
export type AftSidebarSummary = {
|
|
@@ -53,12 +49,7 @@ export type AftSidebarSummary = {
|
|
|
53
49
|
};
|
|
54
50
|
function healthSummary(bar: StatusBar | undefined): string {
|
|
55
51
|
if (!bar) return "health pending";
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
`${diagnosticsPart(bar)} ` +
|
|
59
|
-
`${stale}D${count(bar.dead_code, bar.disabled_categories?.includes("dead_code"))} U${count(bar.unused_exports, bar.disabled_categories?.includes("unused_exports"))} ` +
|
|
60
|
-
`C${count(bar.duplicates, bar.disabled_categories?.includes("duplicates"))} T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`
|
|
61
|
-
);
|
|
52
|
+
return `${diagnosticsPart(bar)} T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`;
|
|
62
53
|
}
|
|
63
54
|
|
|
64
55
|
/**
|