@cortexkit/aft-opencode 0.58.1 → 0.59.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/bash-wait-detach.d.ts.map +1 -1
- package/dist/bg-notifications.d.ts +8 -0
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/bridge-bootstrap.d.ts +4 -4
- package/dist/config-live-reload.d.ts +44 -8
- package/dist/config-live-reload.d.ts.map +1 -1
- package/dist/config.d.ts +85 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/configure-warnings.d.ts.map +1 -1
- package/dist/entry/server.js +5329 -2607
- package/dist/hashline-tag-sources.d.ts +18 -0
- package/dist/hashline-tag-sources.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4511 -2373
- package/dist/lsp-auto-install.d.ts +30 -0
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/lsp-github-install.d.ts +5 -2
- package/dist/lsp-github-install.d.ts.map +1 -1
- package/dist/lsp-github-table.d.ts +4 -3
- package/dist/lsp-github-table.d.ts.map +1 -1
- package/dist/lsp-npm-table.d.ts +10 -0
- package/dist/lsp-npm-table.d.ts.map +1 -1
- package/dist/lsp-registry-probe.d.ts +8 -4
- package/dist/lsp-registry-probe.d.ts.map +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.d.ts.map +1 -1
- package/dist/permissions/v2-service.d.ts +110 -5
- package/dist/permissions/v2-service.d.ts.map +1 -1
- package/dist/rpc/contract.d.ts +1 -1
- package/dist/rpc/contract.d.ts.map +1 -1
- package/dist/rpc/register.d.ts +3 -5
- package/dist/rpc/register.d.ts.map +1 -1
- package/dist/shared/ignored-message.d.ts.map +1 -1
- package/dist/shared/read-vision.d.ts.map +1 -1
- package/dist/shared/rpc-client.d.ts +8 -0
- package/dist/shared/rpc-client.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/session-directory.d.ts +9 -0
- package/dist/shared/session-directory.d.ts.map +1 -1
- package/dist/shared/status.d.ts +1 -0
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/shared/subagent-detect.d.ts +11 -4
- package/dist/shared/subagent-detect.d.ts.map +1 -1
- package/dist/shared/v2-context.d.ts +3 -0
- package/dist/shared/v2-context.d.ts.map +1 -0
- package/dist/subc-tool-schemas.d.ts +23 -1
- package/dist/subc-tool-schemas.d.ts.map +1 -1
- package/dist/tool-registration.d.ts +11 -8
- package/dist/tool-registration.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts +16 -15
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/bash.d.ts +41 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash_watch.d.ts +14 -4
- package/dist/tools/bash_watch.d.ts.map +1 -1
- package/dist/tools/bash_write.d.ts.map +1 -1
- package/dist/tools/definitions/v2.d.ts +4 -0
- package/dist/tools/definitions/v2.d.ts.map +1 -1
- package/dist/tools/hoisted/v2.d.ts +8 -1
- package/dist/tools/hoisted/v2.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts +27 -7
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/inspect.d.ts +10 -1
- package/dist/tools/inspect.d.ts.map +1 -1
- package/dist/tools/permissions.d.ts +2 -1
- package/dist/tools/permissions.d.ts.map +1 -1
- package/dist/tools/reading.d.ts +0 -3
- package/dist/tools/reading.d.ts.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/semantic.d.ts.map +1 -1
- package/dist/tui/aft-rpc.d.ts +14 -0
- package/dist/tui/aft-rpc.d.ts.map +1 -1
- package/dist/tui/v2-status.d.ts.map +1 -1
- package/dist/v2-host-tool-overlap.d.ts +66 -0
- package/dist/v2-host-tool-overlap.d.ts.map +1 -0
- package/dist/v2-prompt-detach.d.ts +70 -0
- package/dist/v2-prompt-detach.d.ts.map +1 -0
- package/dist/v2-tool-hooks.d.ts +6 -0
- package/dist/v2-tool-hooks.d.ts.map +1 -0
- package/dist/v2-workflow-hints.d.ts +4 -0
- package/dist/v2-workflow-hints.d.ts.map +1 -0
- package/dist/wakes/runtime-consumer.d.ts +2 -0
- package/dist/wakes/runtime-consumer.d.ts.map +1 -1
- package/dist/wakes/session-delivery.d.ts +9 -0
- package/dist/wakes/session-delivery.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts +20 -7
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/entry/server-runtime.mjs +41 -5
- package/src/shared/ignored-message.ts +18 -0
- package/src/shared/read-vision.ts +14 -4
- package/src/shared/rpc-client.ts +46 -5
- package/src/shared/rpc-server.ts +10 -0
- package/src/shared/session-directory.ts +147 -7
- package/src/shared/status.ts +15 -5
- package/src/shared/subagent-detect.ts +89 -28
- package/src/shared/v2-context.ts +7 -0
- package/src/tui/aft-rpc.ts +11 -0
- package/src/tui/index.tsx +20 -16
- package/src/tui/sidebar-view.tsx +9 -1
- package/src/tui/v2-status.ts +7 -5
- package/src/tui/v2.tsx +47 -0
- package/src/tui-compiled/aft-rpc.ts +11 -0
- package/src/tui-compiled/index.tsx +27 -16
- package/src/tui-compiled/sidebar-view.tsx +11 -2
- package/src/tui-compiled/v2-status.ts +7 -5
- package/src/tui-compiled/v2.tsx +26 -0
package/src/tui/v2-status.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AftStatusSnapshot, degradedHeaderMarker, type StatusBar } from "../shared/status";
|
|
2
2
|
|
|
3
|
-
function count(value: number | undefined): string {
|
|
3
|
+
function count(value: number | undefined, off = false): string {
|
|
4
|
+
if (off) return "○";
|
|
4
5
|
return value === undefined ? "?" : String(value);
|
|
5
6
|
}
|
|
6
7
|
|
|
@@ -10,6 +11,7 @@ function count(value: number | undefined): string {
|
|
|
10
11
|
* indefinitely.
|
|
11
12
|
*/
|
|
12
13
|
function diagnosticsPart(bar: StatusBar): string {
|
|
14
|
+
if (bar.disabled_categories?.includes("diagnostics")) return "E○ W○";
|
|
13
15
|
if (
|
|
14
16
|
bar.errors === undefined &&
|
|
15
17
|
bar.warnings === undefined &&
|
|
@@ -36,8 +38,8 @@ export function formatAftStatusSegment(status: AftStatusSnapshot | null): string
|
|
|
36
38
|
const stale = bar.tier2_stale ? "~" : "";
|
|
37
39
|
return (
|
|
38
40
|
`AFT ${diagnosticsPart(bar)} | ` +
|
|
39
|
-
`${stale}D${count(bar.dead_code)} U${count(bar.unused_exports)} ` +
|
|
40
|
-
`C${count(bar.duplicates)} | T${count(bar.todos)}`
|
|
41
|
+
`${stale}D${count(bar.dead_code, bar.disabled_categories?.includes("dead_code"))} U${count(bar.unused_exports, bar.disabled_categories?.includes("unused_exports"))} ` +
|
|
42
|
+
`C${count(bar.duplicates, bar.disabled_categories?.includes("duplicates"))} | T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`
|
|
41
43
|
);
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -53,8 +55,8 @@ function healthSummary(bar: StatusBar | undefined): string {
|
|
|
53
55
|
const stale = bar.tier2_stale ? "~" : "";
|
|
54
56
|
return (
|
|
55
57
|
`${diagnosticsPart(bar)} ` +
|
|
56
|
-
`${stale}D${count(bar.dead_code)} U${count(bar.unused_exports)} ` +
|
|
57
|
-
`C${count(bar.duplicates)} T${count(bar.todos)}`
|
|
58
|
+
`${stale}D${count(bar.dead_code, bar.disabled_categories?.includes("dead_code"))} U${count(bar.unused_exports, bar.disabled_categories?.includes("unused_exports"))} ` +
|
|
59
|
+
`C${count(bar.duplicates, bar.disabled_categories?.includes("duplicates"))} T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`
|
|
58
60
|
);
|
|
59
61
|
}
|
|
60
62
|
|
package/src/tui/v2.tsx
CHANGED
|
@@ -28,6 +28,11 @@ type AftRpcClient = {
|
|
|
28
28
|
handler: (event: { data: { sessionID?: string } }) => void | Promise<void>,
|
|
29
29
|
options?: { signal?: AbortSignal },
|
|
30
30
|
): () => void;
|
|
31
|
+
on(
|
|
32
|
+
name: "hostToolOverlap",
|
|
33
|
+
handler: (event: { data: { message: string } }) => void | Promise<void>,
|
|
34
|
+
options?: { signal?: AbortSignal },
|
|
35
|
+
): () => void;
|
|
31
36
|
};
|
|
32
37
|
};
|
|
33
38
|
|
|
@@ -87,6 +92,14 @@ type V2TuiContext = {
|
|
|
87
92
|
};
|
|
88
93
|
ui: {
|
|
89
94
|
dialog: { alert(input: { title: string; message: string }): Promise<void> };
|
|
95
|
+
toast?: {
|
|
96
|
+
show(input: {
|
|
97
|
+
title?: string;
|
|
98
|
+
message: string;
|
|
99
|
+
variant?: "info" | "success" | "warning" | "error";
|
|
100
|
+
duration?: number;
|
|
101
|
+
}): void;
|
|
102
|
+
};
|
|
90
103
|
router: { current(): { type: string; sessionID?: string } };
|
|
91
104
|
slot(claim: {
|
|
92
105
|
append: "app" | "prompt.footer.status" | "sidebar.content";
|
|
@@ -316,6 +329,36 @@ function AftStatusCommands(props: { context: V2TuiContext; rpc: AftRpcClient })
|
|
|
316
329
|
return null;
|
|
317
330
|
}
|
|
318
331
|
|
|
332
|
+
/** How long the built-in tool overlap toast stays up: long enough to read the command. */
|
|
333
|
+
const HOST_TOOL_OVERLAP_TOAST_MS = 15_000;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Show the server's one-off built-in tool overlap notice as a toast. A toast
|
|
337
|
+
* reaches the person at the terminal and nothing else; the server sends this
|
|
338
|
+
* at most once per host process, so every TUI subscribed at that moment shows
|
|
339
|
+
* it once. A host without a toast surface shows nothing.
|
|
340
|
+
*/
|
|
341
|
+
export function subscribeV2HostToolOverlapToast(
|
|
342
|
+
context: Pick<V2TuiContext, "ui">,
|
|
343
|
+
rpc: AftRpcClient,
|
|
344
|
+
options?: { signal?: AbortSignal },
|
|
345
|
+
): () => void {
|
|
346
|
+
return rpc.events.on(
|
|
347
|
+
"hostToolOverlap",
|
|
348
|
+
(event) => {
|
|
349
|
+
const toast = context.ui.toast;
|
|
350
|
+
if (typeof toast?.show !== "function") return;
|
|
351
|
+
toast.show({
|
|
352
|
+
title: "AFT",
|
|
353
|
+
message: event.data.message,
|
|
354
|
+
variant: "warning",
|
|
355
|
+
duration: HOST_TOOL_OVERLAP_TOAST_MS,
|
|
356
|
+
});
|
|
357
|
+
},
|
|
358
|
+
options,
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
319
362
|
export async function setupV2Tui(context: V2TuiContext): Promise<() => void> {
|
|
320
363
|
const rpc = context.client.rpc(AftRpc);
|
|
321
364
|
const controller = new AbortController();
|
|
@@ -343,10 +386,14 @@ export async function setupV2Tui(context: V2TuiContext): Promise<() => void> {
|
|
|
343
386
|
(event) => showStatusDialog(context, rpc, event.data.sessionID ?? activeSessionID(context)),
|
|
344
387
|
{ signal: controller.signal },
|
|
345
388
|
);
|
|
389
|
+
const stopOverlapToasts = subscribeV2HostToolOverlapToast(context, rpc, {
|
|
390
|
+
signal: controller.signal,
|
|
391
|
+
});
|
|
346
392
|
|
|
347
393
|
return () => {
|
|
348
394
|
controller.abort();
|
|
349
395
|
stopDialogEvents();
|
|
396
|
+
stopOverlapToasts();
|
|
350
397
|
for (const cleanup of slotCleanups) cleanup();
|
|
351
398
|
};
|
|
352
399
|
}
|
|
@@ -24,8 +24,18 @@ export const IndexProgress = Schema.Struct({
|
|
|
24
24
|
total: Schema.optional(Schema.Number),
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* A one-off notice for the user, shown by the OpenCode 2 TUI as a toast. It
|
|
29
|
+
* travels over RPC rather than into the session because anything written into
|
|
30
|
+
* a session (a synthetic record included) is sent to the model on later turns.
|
|
31
|
+
*/
|
|
32
|
+
export const HostToolOverlapNotice = Schema.Struct({
|
|
33
|
+
message: Schema.String,
|
|
34
|
+
});
|
|
35
|
+
|
|
27
36
|
export type AftRpcSession = typeof RpcSession.Type;
|
|
28
37
|
export type AftIndexProgress = typeof IndexProgress.Type;
|
|
38
|
+
export type AftHostToolOverlapNotice = typeof HostToolOverlapNotice.Type;
|
|
29
39
|
|
|
30
40
|
export const AftRpc = Rpc.define({
|
|
31
41
|
id: "aft",
|
|
@@ -39,5 +49,6 @@ export const AftRpc = Rpc.define({
|
|
|
39
49
|
statusInvalidated: { schema: RpcSession },
|
|
40
50
|
showStatusDialog: { schema: RpcSession },
|
|
41
51
|
indexProgress: { schema: IndexProgress },
|
|
52
|
+
hostToolOverlap: { schema: HostToolOverlapNotice },
|
|
42
53
|
},
|
|
43
54
|
});
|
|
@@ -197,6 +197,7 @@ const StatusDialog = props => {
|
|
|
197
197
|
// The earlier `formatCompressionDialogRows` returned padded strings that
|
|
198
198
|
// looked offset against neighboring sections.
|
|
199
199
|
const compressionAggregateRows = () => formatCompressionSidebarRows(status()?.compression);
|
|
200
|
+
const statusBar = () => status()?.status_bar ?? status()?.status_bar_values;
|
|
200
201
|
return (() => {
|
|
201
202
|
var _el$4 = _$createElement("box"),
|
|
202
203
|
_el$5 = _$createElement("box"),
|
|
@@ -698,7 +699,7 @@ const StatusDialog = props => {
|
|
|
698
699
|
})() : null;
|
|
699
700
|
})(), _el$9);
|
|
700
701
|
_$insert(_el$4, (() => {
|
|
701
|
-
var _c$9 = _$memo(() => !!
|
|
702
|
+
var _c$9 = _$memo(() => !!statusBar());
|
|
702
703
|
return () => _c$9() ? (() => {
|
|
703
704
|
var _el$53 = _$createElement("box"),
|
|
704
705
|
_el$54 = _$createElement("text"),
|
|
@@ -708,85 +709,95 @@ const StatusDialog = props => {
|
|
|
708
709
|
_$setProp(_el$53, "width", "100%");
|
|
709
710
|
_$setProp(_el$53, "marginTop", 1);
|
|
710
711
|
_$insertNode(_el$54, _el$55);
|
|
711
|
-
_$insert(_el$55, () =>
|
|
712
|
+
_$insert(_el$55, () => statusBar().tier2_stale ? "Code Health ~" : "Code Health");
|
|
713
|
+
_$insert(_el$53, () => (statusBar().disabled_categories ?? []).map(key => _$createComponent(R, {
|
|
714
|
+
get theme() {
|
|
715
|
+
return t();
|
|
716
|
+
},
|
|
717
|
+
get label() {
|
|
718
|
+
return key.replaceAll("_", " ");
|
|
719
|
+
},
|
|
720
|
+
value: "\u25CB off",
|
|
721
|
+
tone: "muted"
|
|
722
|
+
})), null);
|
|
712
723
|
_$insert(_el$53, (() => {
|
|
713
|
-
var _c$14 = _$memo(() =>
|
|
724
|
+
var _c$14 = _$memo(() => statusBar().errors !== undefined);
|
|
714
725
|
return () => _c$14() ? _$createComponent(R, {
|
|
715
726
|
get theme() {
|
|
716
727
|
return t();
|
|
717
728
|
},
|
|
718
729
|
label: "Errors",
|
|
719
730
|
get value() {
|
|
720
|
-
return formatCountShort(
|
|
731
|
+
return formatCountShort(statusBar().errors);
|
|
721
732
|
},
|
|
722
733
|
get tone() {
|
|
723
|
-
return
|
|
734
|
+
return statusBar().errors > 0 ? "err" : "muted";
|
|
724
735
|
}
|
|
725
736
|
}) : null;
|
|
726
737
|
})(), null);
|
|
727
738
|
_$insert(_el$53, (() => {
|
|
728
|
-
var _c$15 = _$memo(() =>
|
|
739
|
+
var _c$15 = _$memo(() => statusBar().warnings !== undefined);
|
|
729
740
|
return () => _c$15() ? _$createComponent(R, {
|
|
730
741
|
get theme() {
|
|
731
742
|
return t();
|
|
732
743
|
},
|
|
733
744
|
label: "Warnings",
|
|
734
745
|
get value() {
|
|
735
|
-
return formatCountShort(
|
|
746
|
+
return formatCountShort(statusBar().warnings);
|
|
736
747
|
},
|
|
737
748
|
get tone() {
|
|
738
|
-
return
|
|
749
|
+
return statusBar().warnings > 0 ? "warn" : "muted";
|
|
739
750
|
}
|
|
740
751
|
}) : null;
|
|
741
752
|
})(), null);
|
|
742
753
|
_$insert(_el$53, (() => {
|
|
743
|
-
var _c$16 = _$memo(() =>
|
|
754
|
+
var _c$16 = _$memo(() => statusBar().dead_code !== undefined);
|
|
744
755
|
return () => _c$16() ? _$createComponent(R, {
|
|
745
756
|
get theme() {
|
|
746
757
|
return t();
|
|
747
758
|
},
|
|
748
759
|
label: "Dead Code",
|
|
749
760
|
get value() {
|
|
750
|
-
return formatCountShort(
|
|
761
|
+
return formatCountShort(statusBar().dead_code);
|
|
751
762
|
},
|
|
752
763
|
tone: "muted"
|
|
753
764
|
}) : null;
|
|
754
765
|
})(), null);
|
|
755
766
|
_$insert(_el$53, (() => {
|
|
756
|
-
var _c$17 = _$memo(() =>
|
|
767
|
+
var _c$17 = _$memo(() => statusBar().unused_exports !== undefined);
|
|
757
768
|
return () => _c$17() ? _$createComponent(R, {
|
|
758
769
|
get theme() {
|
|
759
770
|
return t();
|
|
760
771
|
},
|
|
761
772
|
label: "Unused Exports",
|
|
762
773
|
get value() {
|
|
763
|
-
return formatCountShort(
|
|
774
|
+
return formatCountShort(statusBar().unused_exports);
|
|
764
775
|
},
|
|
765
776
|
tone: "muted"
|
|
766
777
|
}) : null;
|
|
767
778
|
})(), null);
|
|
768
779
|
_$insert(_el$53, (() => {
|
|
769
|
-
var _c$18 = _$memo(() =>
|
|
780
|
+
var _c$18 = _$memo(() => statusBar().duplicates !== undefined);
|
|
770
781
|
return () => _c$18() ? _$createComponent(R, {
|
|
771
782
|
get theme() {
|
|
772
783
|
return t();
|
|
773
784
|
},
|
|
774
785
|
label: "Duplicates",
|
|
775
786
|
get value() {
|
|
776
|
-
return formatCountShort(
|
|
787
|
+
return formatCountShort(statusBar().duplicates);
|
|
777
788
|
},
|
|
778
789
|
tone: "muted"
|
|
779
790
|
}) : null;
|
|
780
791
|
})(), null);
|
|
781
792
|
_$insert(_el$53, (() => {
|
|
782
|
-
var _c$19 = _$memo(() =>
|
|
793
|
+
var _c$19 = _$memo(() => statusBar().todos !== undefined);
|
|
783
794
|
return () => _c$19() ? _$createComponent(R, {
|
|
784
795
|
get theme() {
|
|
785
796
|
return t();
|
|
786
797
|
},
|
|
787
798
|
label: "TODOs",
|
|
788
799
|
get value() {
|
|
789
|
-
return formatCountShort(
|
|
800
|
+
return formatCountShort(statusBar().todos);
|
|
790
801
|
},
|
|
791
802
|
tone: "muted"
|
|
792
803
|
}) : null;
|
|
@@ -407,7 +407,7 @@ export const AftSidebarPanel = props => {
|
|
|
407
407
|
const trigramBytes = () => s()?.disk?.trigram_disk_bytes ?? 0;
|
|
408
408
|
const semanticBytes = () => s()?.disk?.semantic_disk_bytes ?? 0;
|
|
409
409
|
const compressionRows = () => formatCompressionSidebarRows(s()?.compression);
|
|
410
|
-
const statusBar = () => s()?.status_bar;
|
|
410
|
+
const statusBar = () => s()?.status_bar ?? s()?.status_bar_values;
|
|
411
411
|
const degradedSummary = () => {
|
|
412
412
|
const snap = s();
|
|
413
413
|
if (!snap?.degraded) return null;
|
|
@@ -744,7 +744,16 @@ export const AftSidebarPanel = props => {
|
|
|
744
744
|
get title() {
|
|
745
745
|
return statusBar().tier2_stale ? "Code Health ~" : "Code Health";
|
|
746
746
|
}
|
|
747
|
-
}), _$memo(() =>
|
|
747
|
+
}), _$memo(() => (statusBar().disabled_categories ?? []).map(key => _$createComponent(StatRow, {
|
|
748
|
+
get palette() {
|
|
749
|
+
return props.palette;
|
|
750
|
+
},
|
|
751
|
+
get label() {
|
|
752
|
+
return key.replaceAll("_", " ");
|
|
753
|
+
},
|
|
754
|
+
value: "\u25CB off",
|
|
755
|
+
tone: "muted"
|
|
756
|
+
}))), _$memo(() => _$memo(() => statusBar().errors !== undefined)() && _$createComponent(StatRow, {
|
|
748
757
|
get palette() {
|
|
749
758
|
return props.palette;
|
|
750
759
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AftStatusSnapshot, degradedHeaderMarker, type StatusBar } from "../shared/status";
|
|
2
2
|
|
|
3
|
-
function count(value: number | undefined): string {
|
|
3
|
+
function count(value: number | undefined, off = false): string {
|
|
4
|
+
if (off) return "○";
|
|
4
5
|
return value === undefined ? "?" : String(value);
|
|
5
6
|
}
|
|
6
7
|
|
|
@@ -10,6 +11,7 @@ function count(value: number | undefined): string {
|
|
|
10
11
|
* indefinitely.
|
|
11
12
|
*/
|
|
12
13
|
function diagnosticsPart(bar: StatusBar): string {
|
|
14
|
+
if (bar.disabled_categories?.includes("diagnostics")) return "E○ W○";
|
|
13
15
|
if (
|
|
14
16
|
bar.errors === undefined &&
|
|
15
17
|
bar.warnings === undefined &&
|
|
@@ -36,8 +38,8 @@ export function formatAftStatusSegment(status: AftStatusSnapshot | null): string
|
|
|
36
38
|
const stale = bar.tier2_stale ? "~" : "";
|
|
37
39
|
return (
|
|
38
40
|
`AFT ${diagnosticsPart(bar)} | ` +
|
|
39
|
-
`${stale}D${count(bar.dead_code)} U${count(bar.unused_exports)} ` +
|
|
40
|
-
`C${count(bar.duplicates)} | T${count(bar.todos)}`
|
|
41
|
+
`${stale}D${count(bar.dead_code, bar.disabled_categories?.includes("dead_code"))} U${count(bar.unused_exports, bar.disabled_categories?.includes("unused_exports"))} ` +
|
|
42
|
+
`C${count(bar.duplicates, bar.disabled_categories?.includes("duplicates"))} | T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`
|
|
41
43
|
);
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -53,8 +55,8 @@ function healthSummary(bar: StatusBar | undefined): string {
|
|
|
53
55
|
const stale = bar.tier2_stale ? "~" : "";
|
|
54
56
|
return (
|
|
55
57
|
`${diagnosticsPart(bar)} ` +
|
|
56
|
-
`${stale}D${count(bar.dead_code)} U${count(bar.unused_exports)} ` +
|
|
57
|
-
`C${count(bar.duplicates)} T${count(bar.todos)}`
|
|
58
|
+
`${stale}D${count(bar.dead_code, bar.disabled_categories?.includes("dead_code"))} U${count(bar.unused_exports, bar.disabled_categories?.includes("unused_exports"))} ` +
|
|
59
|
+
`C${count(bar.duplicates, bar.disabled_categories?.includes("duplicates"))} T${count(bar.todos, bar.disabled_categories?.includes("todos"))}`
|
|
58
60
|
);
|
|
59
61
|
}
|
|
60
62
|
|
package/src/tui-compiled/v2.tsx
CHANGED
|
@@ -246,6 +246,28 @@ function AftStatusCommands(props) {
|
|
|
246
246
|
}));
|
|
247
247
|
return null;
|
|
248
248
|
}
|
|
249
|
+
|
|
250
|
+
/** How long the built-in tool overlap toast stays up: long enough to read the command. */
|
|
251
|
+
const HOST_TOOL_OVERLAP_TOAST_MS = 15_000;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Show the server's one-off built-in tool overlap notice as a toast. A toast
|
|
255
|
+
* reaches the person at the terminal and nothing else; the server sends this
|
|
256
|
+
* at most once per host process, so every TUI subscribed at that moment shows
|
|
257
|
+
* it once. A host without a toast surface shows nothing.
|
|
258
|
+
*/
|
|
259
|
+
export function subscribeV2HostToolOverlapToast(context, rpc, options) {
|
|
260
|
+
return rpc.events.on("hostToolOverlap", event => {
|
|
261
|
+
const toast = context.ui.toast;
|
|
262
|
+
if (typeof toast?.show !== "function") return;
|
|
263
|
+
toast.show({
|
|
264
|
+
title: "AFT",
|
|
265
|
+
message: event.data.message,
|
|
266
|
+
variant: "warning",
|
|
267
|
+
duration: HOST_TOOL_OVERLAP_TOAST_MS
|
|
268
|
+
});
|
|
269
|
+
}, options);
|
|
270
|
+
}
|
|
249
271
|
export async function setupV2Tui(context) {
|
|
250
272
|
const rpc = context.client.rpc(AftRpc);
|
|
251
273
|
const controller = new AbortController();
|
|
@@ -282,9 +304,13 @@ export async function setupV2Tui(context) {
|
|
|
282
304
|
const stopDialogEvents = rpc.events.on("showStatusDialog", event => showStatusDialog(context, rpc, event.data.sessionID ?? activeSessionID(context)), {
|
|
283
305
|
signal: controller.signal
|
|
284
306
|
});
|
|
307
|
+
const stopOverlapToasts = subscribeV2HostToolOverlapToast(context, rpc, {
|
|
308
|
+
signal: controller.signal
|
|
309
|
+
});
|
|
285
310
|
return () => {
|
|
286
311
|
controller.abort();
|
|
287
312
|
stopDialogEvents();
|
|
313
|
+
stopOverlapToasts();
|
|
288
314
|
for (const cleanup of slotCleanups) cleanup();
|
|
289
315
|
};
|
|
290
316
|
}
|