@yusukeshib/pi-babysit 0.6.23 → 0.6.25
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/README.md +7 -3
- package/index.ts +63 -10
- package/log-viewer.ts +5 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -167,9 +167,13 @@ sessions, and click again to return to running-only. Both modes show newest firs
|
|
|
167
167
|
ten per page; `< 1/4 >` shows the current/total page when needed. Click the
|
|
168
168
|
arrows to page. Rows occupy one line, previewing the description (or the command
|
|
169
169
|
for older processes and task for older agents), with `…` when clipped. Click an
|
|
170
|
-
AGENT or PROCESS row to
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
AGENT or PROCESS row to expand a **log viewer directly below that row**. The summary
|
|
171
|
+
title, list header, and all other rows remain visible with their original colors.
|
|
172
|
+
Only one row is expanded at a time; selecting another closes the previous one.
|
|
173
|
+
The viewer is capped at ten lines including its existing row header and footer;
|
|
174
|
+
all saved history remains available by scrolling. Click the same row again to
|
|
175
|
+
collapse it, preserving the list's mode and page.
|
|
176
|
+
There is no separate Close button or Esc binding. The viewer uses Pi's `ScrollView` for
|
|
173
177
|
scroll position and follow behavior, with a widget-local scrollbar styled using
|
|
174
178
|
Pi's scrollbar theme. Wheel, scrollbar drag/track clicks, and ↑/↓ navigate the
|
|
175
179
|
log without requiring any Pi core changes. Home/End and PageUp/PageDown remain
|
package/index.ts
CHANGED
|
@@ -2600,6 +2600,7 @@ function renderWidgetSessionHeader(
|
|
|
2600
2600
|
// How many trailing output lines to show per session in the widget.
|
|
2601
2601
|
const WIDGET_COLLAPSED_TAIL_LINES = 1;
|
|
2602
2602
|
const WIDGET_SESSION_PAGE_SIZE = 10;
|
|
2603
|
+
const WIDGET_VIEWER_MAX_LINES = 10;
|
|
2603
2604
|
|
|
2604
2605
|
export interface WidgetSessionListState {
|
|
2605
2606
|
mode: "running" | "all";
|
|
@@ -2624,7 +2625,7 @@ interface WidgetMouseEvent {
|
|
|
2624
2625
|
}
|
|
2625
2626
|
|
|
2626
2627
|
/**
|
|
2627
|
-
* Compact session list. Item presses
|
|
2628
|
+
* Compact session list. Item presses toggle the session's inline viewer.
|
|
2628
2629
|
*/
|
|
2629
2630
|
export function createWidgetComponent(
|
|
2630
2631
|
summaryLines: string[],
|
|
@@ -2682,6 +2683,9 @@ export function createWidgetComponent(
|
|
|
2682
2683
|
}
|
|
2683
2684
|
return lines;
|
|
2684
2685
|
},
|
|
2686
|
+
getSessionLine(id: string) {
|
|
2687
|
+
return targetByLine.findIndex((target) => target?.type === "session" && target.id === id);
|
|
2688
|
+
},
|
|
2685
2689
|
handleMouse(event: WidgetMouseEvent) {
|
|
2686
2690
|
if (event.button !== "left") return undefined;
|
|
2687
2691
|
const target = targetByLine[event.y];
|
|
@@ -2726,7 +2730,19 @@ export function createSessionWidget(options: {
|
|
|
2726
2730
|
let displays: WidgetSessionDisplay[] = [];
|
|
2727
2731
|
let viewer: ReturnType<typeof createLogViewer> | undefined;
|
|
2728
2732
|
let source: FileLogSource | undefined;
|
|
2729
|
-
let
|
|
2733
|
+
let summaryLines: string[] = [];
|
|
2734
|
+
let listHeight = 0;
|
|
2735
|
+
let viewerRow = -1;
|
|
2736
|
+
let viewerLines = 0;
|
|
2737
|
+
let dragging = false;
|
|
2738
|
+
let list = createWidgetComponent([], [], toggle, listState);
|
|
2739
|
+
function rebuildList() {
|
|
2740
|
+
list = createWidgetComponent(summaryLines, displays, toggle, listState);
|
|
2741
|
+
}
|
|
2742
|
+
function toggle(id: string) {
|
|
2743
|
+
if (selectedId === id) close();
|
|
2744
|
+
else open(id);
|
|
2745
|
+
}
|
|
2730
2746
|
function refreshViewer() {
|
|
2731
2747
|
if (!selectedId || !viewer) return;
|
|
2732
2748
|
const log = options.readLog(selectedId);
|
|
@@ -2746,16 +2762,32 @@ export function createSessionWidget(options: {
|
|
|
2746
2762
|
}
|
|
2747
2763
|
function close() {
|
|
2748
2764
|
selectedId = undefined;
|
|
2765
|
+
viewerRow = -1;
|
|
2766
|
+
viewerLines = 0;
|
|
2767
|
+
dragging = false;
|
|
2749
2768
|
viewer?.dispose();
|
|
2750
2769
|
viewer = undefined;
|
|
2751
2770
|
source = undefined;
|
|
2752
2771
|
options.requestRender();
|
|
2753
2772
|
}
|
|
2754
2773
|
function open(id: string) {
|
|
2774
|
+
if (!displays.some((session) => session.id === id)) {
|
|
2775
|
+
displays = [...displays, { id, header: id, tail: [], viewable: true, active: true }];
|
|
2776
|
+
}
|
|
2777
|
+
if (listState.mode === "running" && !displays.find((session) => session.id === id)?.active)
|
|
2778
|
+
listState.mode = "all";
|
|
2779
|
+
const visible = listState.mode === "running" ? displays.filter((session) => session.active) : displays;
|
|
2780
|
+
listState.page = Math.floor(visible.findIndex((session) => session.id === id) / WIDGET_SESSION_PAGE_SIZE);
|
|
2781
|
+
rebuildList();
|
|
2782
|
+
dragging = false;
|
|
2755
2783
|
viewer?.dispose();
|
|
2756
2784
|
source = undefined;
|
|
2757
2785
|
selectedId = id;
|
|
2758
|
-
viewer = createLogViewer({
|
|
2786
|
+
viewer = createLogViewer({
|
|
2787
|
+
...options,
|
|
2788
|
+
getHeight: () => Math.max(3, Math.min(WIDGET_VIEWER_MAX_LINES, options.getHeight() - listHeight + 1)),
|
|
2789
|
+
onClose: close,
|
|
2790
|
+
});
|
|
2759
2791
|
refreshViewer();
|
|
2760
2792
|
options.requestRender();
|
|
2761
2793
|
}
|
|
@@ -2769,15 +2801,36 @@ export function createSessionWidget(options: {
|
|
|
2769
2801
|
},
|
|
2770
2802
|
update(summary: string[], sessions: WidgetSessionDisplay[]) {
|
|
2771
2803
|
displays = sessions;
|
|
2772
|
-
|
|
2804
|
+
summaryLines = summary;
|
|
2805
|
+
rebuildList();
|
|
2806
|
+
if (selectedId && !sessions.some((session) => session.id === selectedId && (listState.mode === "all" || session.active))) close();
|
|
2773
2807
|
refreshViewer();
|
|
2774
2808
|
options.requestRender();
|
|
2775
2809
|
},
|
|
2776
|
-
render(width: number) {
|
|
2810
|
+
render(width: number) {
|
|
2811
|
+
const lines = list.render(width);
|
|
2812
|
+
listHeight = lines.length;
|
|
2813
|
+
viewerRow = selectedId ? list.getSessionLine(selectedId) : -1;
|
|
2814
|
+
viewerLines = 0;
|
|
2815
|
+
if (viewer && viewerRow >= 0) {
|
|
2816
|
+
// Keep the original styled row as the toggle header.
|
|
2817
|
+
const body = viewer.render(width).slice(1);
|
|
2818
|
+
viewerLines = body.length;
|
|
2819
|
+
lines.splice(viewerRow + 1, 0, ...body);
|
|
2820
|
+
}
|
|
2821
|
+
return lines;
|
|
2822
|
+
},
|
|
2777
2823
|
handleMouse(event: TuiMouseEvent) {
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2824
|
+
if (viewer && viewerRow >= 0 && (dragging || (event.y > viewerRow && event.y <= viewerRow + viewerLines))) {
|
|
2825
|
+
const result = viewer.handleMouse({ ...event, y: event.y - viewerRow });
|
|
2826
|
+
if (result && "capture" in result && result.capture) dragging = true;
|
|
2827
|
+
if (event.type === "release") dragging = false;
|
|
2828
|
+
return result;
|
|
2829
|
+
}
|
|
2830
|
+
const mode = listState.mode, page = listState.page;
|
|
2831
|
+
const result = list.handleMouse({ ...event, y: event.y > viewerRow && viewerRow >= 0 ? event.y - viewerLines : event.y });
|
|
2832
|
+
if (mode !== listState.mode || page !== listState.page) close();
|
|
2833
|
+
return result;
|
|
2781
2834
|
},
|
|
2782
2835
|
handleKey(data: string) { return viewer?.handleKey(data) ?? false; },
|
|
2783
2836
|
invalidate() { list.invalidate(); viewer?.invalidate(); },
|
|
@@ -4186,7 +4239,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4186
4239
|
: d.count && d.count > 1
|
|
4187
4240
|
? theme.fg("muted", `×${d.count}`)
|
|
4188
4241
|
: "";
|
|
4189
|
-
const header = theme.fg("muted", theme.bold("babysit_run
|
|
4242
|
+
const header = theme.fg("muted", theme.bold("babysit_run PROCESS")) + (payload ? ` ${payload}` : "");
|
|
4190
4243
|
const box = new Box(1, 1, (t) => theme.bg("toolSuccessBg", t));
|
|
4191
4244
|
box.addChild(new Text(header, 0, 0));
|
|
4192
4245
|
box.addChild(new Text(renderStatus(status, theme), 0, 0));
|
|
@@ -4854,7 +4907,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4854
4907
|
// Legacy calls without descriptions still render their original payload safely.
|
|
4855
4908
|
renderCall(args, theme) {
|
|
4856
4909
|
const isSubagent = args.profile === "subagent";
|
|
4857
|
-
const kind = isSubagent ? "AGENT" : "
|
|
4910
|
+
const kind = isSubagent ? "AGENT" : "PROCESS";
|
|
4858
4911
|
const payload = isSubagent ? args.task : args.command;
|
|
4859
4912
|
const agent = isSubagent && args.agent ? ` [${escapeCommandForDisplay(args.agent)}]` : "";
|
|
4860
4913
|
const title = theme.fg("muted", `${theme.bold(`babysit_run ${kind}`)}${agent}`);
|
package/log-viewer.ts
CHANGED
|
@@ -244,21 +244,18 @@ export function createLogViewer(options: LogViewerOptions) {
|
|
|
244
244
|
const heading = {
|
|
245
245
|
invalidate() {},
|
|
246
246
|
render(width: number) {
|
|
247
|
-
const
|
|
248
|
-
const room = Math.max(0, width - visibleWidth(close) - 1);
|
|
249
|
-
const title = truncateToWidth(sanitize(header).replace(/\n/g, " "), room);
|
|
247
|
+
const title = truncateToWidth(sanitize(header).replace(/\n/g, " "), width);
|
|
250
248
|
return [
|
|
251
249
|
options.getTheme().fg("accent", title) +
|
|
252
250
|
" ".repeat(
|
|
253
|
-
Math.max(0, width - visibleWidth(title)
|
|
254
|
-
)
|
|
255
|
-
options.getTheme().fg("muted", close),
|
|
251
|
+
Math.max(0, width - visibleWidth(title)),
|
|
252
|
+
),
|
|
256
253
|
];
|
|
257
254
|
},
|
|
258
255
|
handleMouse(e: TuiMouseEvent) {
|
|
259
256
|
if (
|
|
260
257
|
e.button !== "left" ||
|
|
261
|
-
e.x <
|
|
258
|
+
e.x < 0 ||
|
|
262
259
|
e.x >= e.width
|
|
263
260
|
)
|
|
264
261
|
return;
|
|
@@ -272,7 +269,7 @@ export function createLogViewer(options: LogViewerOptions) {
|
|
|
272
269
|
const footer: Component = {
|
|
273
270
|
invalidate() {},
|
|
274
271
|
render: (width) => [
|
|
275
|
-
options.getTheme().fg("dim", truncateToWidth(source ? `↑↓ · bytes ${pages[0]?.start ?? 0}–${pages.at(-1)?.end ?? 0}/${source.size} (window)
|
|
272
|
+
options.getTheme().fg("dim", truncateToWidth(source ? `↑↓ · bytes ${pages[0]?.start ?? 0}–${pages.at(-1)?.end ?? 0}/${source.size} (window)` : "↑↓", width)),
|
|
276
273
|
],
|
|
277
274
|
};
|
|
278
275
|
let geometry = {
|
|
@@ -489,10 +486,6 @@ export function createLogViewer(options: LogViewerOptions) {
|
|
|
489
486
|
options.requestRender();
|
|
490
487
|
},
|
|
491
488
|
handleKey(data: string): boolean {
|
|
492
|
-
if (matchesKey(data, Key.escape)) {
|
|
493
|
-
options.onClose();
|
|
494
|
-
return true;
|
|
495
|
-
}
|
|
496
489
|
if (matchesKey(data, Key.up)) scrollView.scrollBy(-1);
|
|
497
490
|
else if (matchesKey(data, Key.down)) scrollView.scrollBy(1);
|
|
498
491
|
else return false;
|