pi-better-background-tasks 0.2.1 → 0.2.3
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/shared-navigator.ts +66 -14
package/package.json
CHANGED
package/src/shared-navigator.ts
CHANGED
|
@@ -83,6 +83,7 @@ type NavigatorState = {
|
|
|
83
83
|
deps?: HostDeps;
|
|
84
84
|
lastHint?: string | null;
|
|
85
85
|
lastMainListLines?: string[];
|
|
86
|
+
lastMainListSignature?: string;
|
|
86
87
|
mainListWidgetInstalled?: boolean;
|
|
87
88
|
mainListRequestRender?: () => void;
|
|
88
89
|
mainListSelectedId?: string;
|
|
@@ -110,7 +111,6 @@ const MAIN_LIST_FALLBACK_WIDTH = 100;
|
|
|
110
111
|
const DETAIL_OVERLAY_FOOTER_ROWS = 3;
|
|
111
112
|
const EVIDENCE_SECTION_ID = "__evidence__";
|
|
112
113
|
const RUNNING_DOT_GLYPH = "●";
|
|
113
|
-
const RUNNING_DOT_FRAMES = ["dim", "accent", "accent", "dim"] as const;
|
|
114
114
|
|
|
115
115
|
function state(): NavigatorState {
|
|
116
116
|
const g = globalThis as typeof globalThis & { [GLOBAL_KEY]?: NavigatorState };
|
|
@@ -199,6 +199,7 @@ export function disposeBackgroundWorkNavigator(ctx?: ExtensionContext): void {
|
|
|
199
199
|
}
|
|
200
200
|
s.lastHint = undefined;
|
|
201
201
|
s.lastMainListLines = undefined;
|
|
202
|
+
s.lastMainListSignature = undefined;
|
|
202
203
|
s.mainListDeadlineScheduler?.dispose();
|
|
203
204
|
s.mainListDeadlineScheduler = undefined;
|
|
204
205
|
s.mainListWidgetInstalled = false;
|
|
@@ -263,6 +264,12 @@ function refreshMainListWidget(): void {
|
|
|
263
264
|
s.mainListDeadlineScheduler?.schedule(nextExpiry - now);
|
|
264
265
|
}
|
|
265
266
|
syncMainListSelection(rows);
|
|
267
|
+
const nextSignature = rows.length ? mainListSignature(rows, {
|
|
268
|
+
selectedId: s.mainListFocused ? s.mainListSelectedId : undefined,
|
|
269
|
+
focused: s.mainListFocused === true,
|
|
270
|
+
}) : undefined;
|
|
271
|
+
const changed = nextSignature !== s.lastMainListSignature;
|
|
272
|
+
s.lastMainListSignature = nextSignature;
|
|
266
273
|
s.lastMainListLines = rows.length ? buildMainListLines(rows, MAIN_LIST_FALLBACK_WIDTH, deps.truncate, themeFg(ctx), {
|
|
267
274
|
selectedId: s.mainListFocused ? s.mainListSelectedId : undefined,
|
|
268
275
|
focused: s.mainListFocused === true,
|
|
@@ -272,6 +279,7 @@ function refreshMainListWidget(): void {
|
|
|
272
279
|
try { (ctx.ui as any).setWidget?.(MAIN_LIST_WIDGET_KEY, undefined); } catch { /* ignore */ }
|
|
273
280
|
s.mainListWidgetInstalled = false;
|
|
274
281
|
s.mainListRequestRender = undefined;
|
|
282
|
+
s.lastMainListSignature = undefined;
|
|
275
283
|
return;
|
|
276
284
|
}
|
|
277
285
|
if (!s.mainListWidgetInstalled) {
|
|
@@ -280,7 +288,9 @@ function refreshMainListWidget(): void {
|
|
|
280
288
|
s.mainListWidgetInstalled = true;
|
|
281
289
|
} catch { /* ignore */ }
|
|
282
290
|
}
|
|
283
|
-
|
|
291
|
+
if (changed) {
|
|
292
|
+
try { s.mainListRequestRender?.(); } catch { /* ignore */ }
|
|
293
|
+
}
|
|
284
294
|
}
|
|
285
295
|
|
|
286
296
|
function themeFg(ctx: ExtensionContext): (color: string, value: string) => string {
|
|
@@ -481,9 +491,40 @@ function statusGlyph(row: InternalRow): string {
|
|
|
481
491
|
}
|
|
482
492
|
|
|
483
493
|
function statusIndicator(row: InternalRow, now = Date.now()): { glyph: string; color: string } {
|
|
494
|
+
void now;
|
|
484
495
|
if (row.statusTone !== "running") return { glyph: statusGlyph(row), color: toneColor(row.statusTone, row.status) };
|
|
485
|
-
|
|
486
|
-
|
|
496
|
+
return { glyph: RUNNING_DOT_GLYPH, color: "accent" };
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function mainListSignature(rows: InternalRow[], options: { selectedId?: string; focused?: boolean } = {}): string {
|
|
500
|
+
return JSON.stringify({
|
|
501
|
+
focused: options.focused === true,
|
|
502
|
+
selectedId: options.focused === true ? options.selectedId ?? null : null,
|
|
503
|
+
rows: rows.map((row) => ({
|
|
504
|
+
navigatorId: row.navigatorId,
|
|
505
|
+
providerLabel: row.providerLabel,
|
|
506
|
+
parentRow: row.parentRow === true,
|
|
507
|
+
providerId: row.providerId,
|
|
508
|
+
id: row.id,
|
|
509
|
+
name: row.name ?? null,
|
|
510
|
+
model: row.model ?? null,
|
|
511
|
+
effort: row.effort ?? null,
|
|
512
|
+
tool: row.tool ?? null,
|
|
513
|
+
tokens: row.tokens ?? null,
|
|
514
|
+
command: row.command ?? null,
|
|
515
|
+
status: row.status,
|
|
516
|
+
statusTone: row.statusTone,
|
|
517
|
+
kind: row.kind,
|
|
518
|
+
primary: row.primary,
|
|
519
|
+
secondary: row.secondary ?? null,
|
|
520
|
+
facts: stableFacts(row.facts),
|
|
521
|
+
sortStartedAt: row.sortStartedAt,
|
|
522
|
+
})),
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function stableFacts(facts: string[] | undefined): string[] {
|
|
527
|
+
return (facts ?? []).filter((fact) => !/\bleft$/.test(singleLine(fact)));
|
|
487
528
|
}
|
|
488
529
|
|
|
489
530
|
function rowSummary(row: InternalRow): string {
|
|
@@ -868,13 +909,13 @@ function createOverlayComponent(
|
|
|
868
909
|
width,
|
|
869
910
|
deps.truncate,
|
|
870
911
|
fg,
|
|
871
|
-
{ minRows: detailRows },
|
|
912
|
+
{ minRows: detailRows, bottomFooter: false, logTailRows },
|
|
872
913
|
);
|
|
873
914
|
} else {
|
|
874
915
|
transcriptDetail = null;
|
|
875
916
|
transcriptComponent = null;
|
|
876
917
|
contentLines = mode === "detail"
|
|
877
|
-
? buildDetailLines(detail, width, deps.truncate, fg, { expandedSections, logTailRows, minRows: detailRows })
|
|
918
|
+
? buildDetailLines(detail, width, deps.truncate, fg, { expandedSections, logTailRows, minRows: detailRows, bottomFooter: false })
|
|
878
919
|
: buildListLines(overlayState, width, deps.truncate, fg);
|
|
879
920
|
}
|
|
880
921
|
if (mode !== "detail") return contentLines;
|
|
@@ -953,9 +994,11 @@ function buildTranscriptDetailLines(
|
|
|
953
994
|
width: number,
|
|
954
995
|
truncate: (s: string, width: number) => string,
|
|
955
996
|
fg: (color: string, value: string) => string,
|
|
956
|
-
options: { minRows?: number } = {},
|
|
997
|
+
options: { minRows?: number; bottomFooter?: boolean; logTailRows?: number } = {},
|
|
957
998
|
): string[] {
|
|
958
999
|
const actions = [...(detail.footerActions ?? ["x close"]), "Esc close"].join(" · ");
|
|
1000
|
+
const tailRows = options.logTailRows ?? DEFAULT_LOG_TAIL_ROWS;
|
|
1001
|
+
const shownTranscriptLines = transcriptLines.length ? transcriptLines.slice(-tailRows) : [" (no transcript yet)"];
|
|
959
1002
|
const lines: string[] = [
|
|
960
1003
|
fg("accent", rule(detail.title, width)),
|
|
961
1004
|
dim(` ← main · ${actions}`, fg),
|
|
@@ -964,10 +1007,11 @@ function buildTranscriptDetailLines(
|
|
|
964
1007
|
];
|
|
965
1008
|
if (detail.subtitle) lines.push(` summary ${detail.subtitle}`);
|
|
966
1009
|
for (const item of detail.metadata) lines.push(` ${item.label.padEnd(8, " ").slice(0, 8)} ${item.value}`);
|
|
967
|
-
lines.push("", dim(section(
|
|
1010
|
+
lines.push("", dim(section(`transcript · latest ${tailRows} rows`, width), fg));
|
|
968
1011
|
if (detail.transcriptDiagnostic) lines.push(` ${dim(detail.transcriptDiagnostic, fg)}`);
|
|
969
|
-
lines.push(...
|
|
1012
|
+
lines.push(...shownTranscriptLines);
|
|
970
1013
|
lines.push("");
|
|
1014
|
+
if (options.bottomFooter === false) return lines.map((line) => safeTruncate(line, width, truncate));
|
|
971
1015
|
const footerLines = [dim(` ← main · ${actions}`, fg), dim(rule("", width), fg)];
|
|
972
1016
|
padBeforeFooter(lines, footerLines.length, options.minRows);
|
|
973
1017
|
lines.push(...footerLines);
|
|
@@ -1051,10 +1095,11 @@ function buildDetailLines(
|
|
|
1051
1095
|
width: number,
|
|
1052
1096
|
truncate: (s: string, width: number) => string,
|
|
1053
1097
|
fg: (color: string, value: string) => string,
|
|
1054
|
-
options: { expandedSections?: Set<string>; logTailRows?: number; minRows?: number } = {},
|
|
1098
|
+
options: { expandedSections?: Set<string>; logTailRows?: number; minRows?: number; bottomFooter?: boolean } = {},
|
|
1055
1099
|
): string[] {
|
|
1056
1100
|
if (!detail) {
|
|
1057
1101
|
const lines = [rule("Work unavailable", width), dim(" ← back · Esc close", fg), ""];
|
|
1102
|
+
if (options.bottomFooter === false) return lines.map((line) => safeTruncate(line, width, truncate));
|
|
1058
1103
|
const footerLines = [dim(rule("", width), fg)];
|
|
1059
1104
|
padBeforeFooter(lines, footerLines.length, options.minRows);
|
|
1060
1105
|
lines.push(...footerLines);
|
|
@@ -1108,14 +1153,17 @@ function buildDetailLines(
|
|
|
1108
1153
|
for (const raw of shown) lines.push(raw ? ` ${raw}` : " ");
|
|
1109
1154
|
}
|
|
1110
1155
|
} else {
|
|
1111
|
-
const
|
|
1156
|
+
const tailEvidence = isTailEvidence(detail);
|
|
1157
|
+
const evidenceLabel = tailEvidence ? `${detail.evidence.label} · latest ${tailRows} rows` : detail.evidence.label;
|
|
1112
1158
|
lines.push(dim(section(evidenceLabel, width), fg));
|
|
1113
1159
|
const wrapped = /log/i.test(detail.evidence.label)
|
|
1114
1160
|
? wrapLogText(body, width - 6)
|
|
1115
|
-
: body
|
|
1116
|
-
|
|
1161
|
+
: wrapEvidenceText(body, width - 6);
|
|
1162
|
+
const shown = tailEvidence ? wrapped.slice(-tailRows) : wrapped;
|
|
1163
|
+
for (const raw of shown) lines.push(raw ? ` ${raw}` : " ");
|
|
1117
1164
|
}
|
|
1118
1165
|
lines.push("");
|
|
1166
|
+
if (options.bottomFooter === false) return lines.map((line) => safeTruncate(line, width, truncate));
|
|
1119
1167
|
const footerLines = [dim(` ← back · ${actions}`, fg), dim(rule("", width), fg)];
|
|
1120
1168
|
padBeforeFooter(lines, footerLines.length, options.minRows);
|
|
1121
1169
|
lines.push(...footerLines);
|
|
@@ -1141,7 +1189,11 @@ function applyDefaultExpandedSections(detail: BackgroundWorkDetail | null, expan
|
|
|
1141
1189
|
}
|
|
1142
1190
|
|
|
1143
1191
|
function isFoldableEvidence(detail: BackgroundWorkDetail): boolean {
|
|
1144
|
-
return
|
|
1192
|
+
return !isTailEvidence(detail);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
function isTailEvidence(detail: BackgroundWorkDetail): boolean {
|
|
1196
|
+
return /log|transcript/i.test(detail.evidence.label);
|
|
1145
1197
|
}
|
|
1146
1198
|
|
|
1147
1199
|
function sectionHeader(label: string, width: number): string {
|