pi-landstrip 0.18.7 → 0.18.8
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/index.ts +147 -88
- package/package.json +2 -2
package/dist/index.ts
CHANGED
|
@@ -1733,7 +1733,28 @@ var MAX_DEPTH = 3;
|
|
|
1733
1733
|
var packageDir = dirname4(fileURLToPath(import.meta.url));
|
|
1734
1734
|
var MAX_TASK_OUTPUT_BYTES = 64 * 1024;
|
|
1735
1735
|
var INSPECTOR_BODY_LINES = 16;
|
|
1736
|
+
var TASK_PREVIEW_MIN_WIDTH = 92;
|
|
1737
|
+
var TASK_PREVIEW_LINES = 7;
|
|
1736
1738
|
var PI_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
1739
|
+
var AGENTS_HELP_ROWS = [
|
|
1740
|
+
["Tab", "Next tab"],
|
|
1741
|
+
["Shift+Tab / S", "Switch scope in Agents or Settings"],
|
|
1742
|
+
["↑ / ↓", "Select item or scroll when follow is off"],
|
|
1743
|
+
["F", "Toggle task log follow"],
|
|
1744
|
+
["Page Up / Down", "Scroll task output by page"],
|
|
1745
|
+
["Home / End", "Jump to task output boundary"],
|
|
1746
|
+
["Enter", "Inspect task, set primary, or save"],
|
|
1747
|
+
["Esc", "Back or close"],
|
|
1748
|
+
["Ctrl+C", "Close"],
|
|
1749
|
+
["Space", "Enable agent or toggle sandbox"],
|
|
1750
|
+
["E", "Edit project agent"],
|
|
1751
|
+
["X", "Delete project agent"],
|
|
1752
|
+
["Y / N", "Confirm or cancel deletion"],
|
|
1753
|
+
["I", "Use global value"],
|
|
1754
|
+
["R", "Discard setting changes"],
|
|
1755
|
+
["0-9 / + / -", "Set subagent limit"],
|
|
1756
|
+
["Backspace", "Open parent task"]
|
|
1757
|
+
];
|
|
1737
1758
|
var MIN_SUPPORTED_PI_VERSION = [0, 82, 0];
|
|
1738
1759
|
var cachedPiPackage;
|
|
1739
1760
|
var piPackageResolved = false;
|
|
@@ -1845,6 +1866,40 @@ function taskDuration(details) {
|
|
|
1845
1866
|
const seconds = Math.max(0, end - details.startedAt) / 1000;
|
|
1846
1867
|
return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;
|
|
1847
1868
|
}
|
|
1869
|
+
function activeTaskRecords(tasks) {
|
|
1870
|
+
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
1871
|
+
const visibleIds = new Set;
|
|
1872
|
+
for (const task of tasks) {
|
|
1873
|
+
if (task.state !== "queued" && task.state !== "running")
|
|
1874
|
+
continue;
|
|
1875
|
+
const seen = new Set;
|
|
1876
|
+
let current = task;
|
|
1877
|
+
while (current && !seen.has(current.id)) {
|
|
1878
|
+
seen.add(current.id);
|
|
1879
|
+
visibleIds.add(current.id);
|
|
1880
|
+
current = current.parentTaskId ? byId.get(current.parentTaskId) : undefined;
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
return tasks.filter((task) => visibleIds.has(task.id));
|
|
1884
|
+
}
|
|
1885
|
+
function taskProgress(task) {
|
|
1886
|
+
if (task.state === "queued")
|
|
1887
|
+
return ["waiting for slot"];
|
|
1888
|
+
if (task.state !== "running")
|
|
1889
|
+
return [];
|
|
1890
|
+
const progress = [];
|
|
1891
|
+
if (task.currentTool)
|
|
1892
|
+
progress.push(`→ ${task.currentTool}`);
|
|
1893
|
+
if (task.toolCalls !== undefined) {
|
|
1894
|
+
progress.push(`${task.toolCalls} call${task.toolCalls === 1 ? "" : "s"}`);
|
|
1895
|
+
}
|
|
1896
|
+
const duration = taskDuration(taskDetails(task));
|
|
1897
|
+
if (duration)
|
|
1898
|
+
progress.push(duration);
|
|
1899
|
+
if (task.retryAttempt)
|
|
1900
|
+
progress.push(`retry ${task.retryAttempt}`);
|
|
1901
|
+
return progress;
|
|
1902
|
+
}
|
|
1848
1903
|
function taskOutput(details, fallback) {
|
|
1849
1904
|
return details.error ?? details.output ?? fallback;
|
|
1850
1905
|
}
|
|
@@ -2392,6 +2447,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
2392
2447
|
let editing = false;
|
|
2393
2448
|
let confirmingDeleteAgent;
|
|
2394
2449
|
let detail = requested.length > 0;
|
|
2450
|
+
let follow = detail;
|
|
2395
2451
|
let scroll = 0;
|
|
2396
2452
|
const reloadAgents = () => {
|
|
2397
2453
|
const selectedName = agents[selectedAgent]?.name;
|
|
@@ -2444,7 +2500,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
2444
2500
|
return `${clipped}${" ".repeat(Math.max(0, cellWidth - visibleWidth2(clipped)))}`;
|
|
2445
2501
|
};
|
|
2446
2502
|
refreshTasks();
|
|
2447
|
-
const tabs = `${dialogTabs(theme, ["Agents", "Tasks", "Settings"], `${tab[0]?.toUpperCase()}${tab.slice(1)}`)}${tab === "tasks" ? "" : theme.fg("dim", ` · Scope: ${scope === "project" ? "Project" : "Global"}`)}`;
|
|
2503
|
+
const tabs = `${dialogTabs(theme, ["Agents", "Tasks", "Settings", "Help"], `${tab[0]?.toUpperCase()}${tab.slice(1)}`)}${tab === "tasks" ? "" : theme.fg("dim", ` · Scope: ${scope === "project" ? "Project" : "Global"}`)}`;
|
|
2448
2504
|
if (tab === "agents") {
|
|
2449
2505
|
const start = Math.max(0, Math.min(selectedAgent - 3, agents.length - 7));
|
|
2450
2506
|
const shown2 = agents.slice(start, start + 7);
|
|
@@ -2513,34 +2569,13 @@ ${this.primaryAgent.prompt}` };
|
|
|
2513
2569
|
lines2.push(` ${theme.fg("error", diagnostic)}`);
|
|
2514
2570
|
}
|
|
2515
2571
|
}
|
|
2516
|
-
lines2.push("");
|
|
2517
2572
|
if (confirmingDeleteAgent) {
|
|
2518
|
-
lines2.push(theme.fg("error", `Delete @${confirmingDeleteAgent}? This removes its project file.`), dialogKeys(theme, [
|
|
2573
|
+
lines2.push("", theme.fg("error", `Delete @${confirmingDeleteAgent}? This removes its project file.`), dialogKeys(theme, [
|
|
2519
2574
|
["Y", "delete"],
|
|
2520
2575
|
["N / Esc", "cancel"]
|
|
2521
2576
|
]));
|
|
2522
2577
|
} else if (saving) {
|
|
2523
|
-
lines2.push(theme.fg("dim", "Saving…"));
|
|
2524
|
-
} else {
|
|
2525
|
-
const mainHints = [["↑↓", "select"]];
|
|
2526
|
-
if (agent && !agent.disabled && agentSupportsMode(agent, "primary")) {
|
|
2527
|
-
mainHints.push(["Enter", "set primary"]);
|
|
2528
|
-
}
|
|
2529
|
-
if (agent && scopedAgent(agent))
|
|
2530
|
-
mainHints.push(["Space", "enable / disable"]);
|
|
2531
|
-
const actionHints = [];
|
|
2532
|
-
if (agent && projectTrusted)
|
|
2533
|
-
actionHints.push(["E", "edit"]);
|
|
2534
|
-
if (agent && projectTrusted && canDeleteProjectAgent(ctx.cwd, agent)) {
|
|
2535
|
-
actionHints.push(["X", "delete"]);
|
|
2536
|
-
}
|
|
2537
|
-
if (agent && scope === "project" && disabledOverrides.project.has(agent.name)) {
|
|
2538
|
-
actionHints.push(["I", "inherit"]);
|
|
2539
|
-
}
|
|
2540
|
-
if (projectTrusted)
|
|
2541
|
-
actionHints.push(["S", "scope"]);
|
|
2542
|
-
actionHints.push(["Tab", "next tab"], ["Esc", "close"]);
|
|
2543
|
-
lines2.push(dialogKeys(theme, mainHints), dialogKeys(theme, actionHints));
|
|
2578
|
+
lines2.push("", theme.fg("dim", "Saving…"));
|
|
2544
2579
|
}
|
|
2545
2580
|
return box(lines2);
|
|
2546
2581
|
}
|
|
@@ -2566,57 +2601,73 @@ ${this.primaryAgent.prompt}` };
|
|
|
2566
2601
|
lines2.push(`${cursor} ${value} ${label}${dirty}`);
|
|
2567
2602
|
}
|
|
2568
2603
|
lines2.push("", theme.fg("dim", selectedSetting === 0 ? "Sets concurrent subagents. Zero disables the task tool." : "Controls OS sandboxing. Use /sandbox to inspect its policy."));
|
|
2569
|
-
if (saving)
|
|
2604
|
+
if (saving)
|
|
2570
2605
|
lines2.push("", theme.fg("dim", "Saving…"));
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
if (dirtySettings.has(selectedSetting))
|
|
2583
|
-
actionHints.push(["Enter", "save"]);
|
|
2584
|
-
actionHints.push(["R", "discard"]);
|
|
2585
|
-
} else {
|
|
2586
|
-
actionHints.push(["S", "scope"], ["Tab", "next tab"], ["Esc", "close"]);
|
|
2587
|
-
}
|
|
2588
|
-
lines2.push("", dialogKeys(theme, editHints), dialogKeys(theme, actionHints));
|
|
2589
|
-
}
|
|
2606
|
+
return box(lines2);
|
|
2607
|
+
}
|
|
2608
|
+
if (tab === "help") {
|
|
2609
|
+
const shortcutWidth = Math.max(visibleWidth2("Shortcut"), ...AGENTS_HELP_ROWS.map(([shortcut]) => visibleWidth2(shortcut)));
|
|
2610
|
+
const descriptionWidth = Math.max(1, contentWidth - shortcutWidth - 4);
|
|
2611
|
+
const lines2 = [
|
|
2612
|
+
tabs,
|
|
2613
|
+
"",
|
|
2614
|
+
theme.fg("dim", ` ${pad("Shortcut", shortcutWidth)} Description`),
|
|
2615
|
+
...AGENTS_HELP_ROWS.map(([shortcut, description]) => ` ${theme.fg("accent", pad(shortcut, shortcutWidth))} ${theme.fg("text", truncateToWidth2(description, descriptionWidth))}`)
|
|
2616
|
+
];
|
|
2590
2617
|
return box(lines2);
|
|
2591
2618
|
}
|
|
2592
2619
|
if (!detail) {
|
|
2593
|
-
const
|
|
2620
|
+
const listLines = [];
|
|
2594
2621
|
if (tasks.length === 0) {
|
|
2595
|
-
|
|
2622
|
+
listLines.push("No task sessions in this session.");
|
|
2596
2623
|
} else {
|
|
2597
2624
|
const start = Math.max(0, Math.min(selectedTask - 5, tasks.length - 11));
|
|
2598
2625
|
const shown2 = tasks.slice(start, start + 11);
|
|
2599
|
-
for (const [offset,
|
|
2626
|
+
for (const [offset, task3] of shown2.entries()) {
|
|
2600
2627
|
const index = start + offset;
|
|
2601
2628
|
const cursor = index === selectedTask ? theme.fg("accent", "›") : " ";
|
|
2602
|
-
const indent = " ".repeat(Math.max(0,
|
|
2603
|
-
|
|
2629
|
+
const indent = " ".repeat(Math.max(0, task3.depth - 1));
|
|
2630
|
+
listLines.push(`${cursor} ${indent}${taskState(theme, task3)} ${theme.fg("accent", `@${task3.agent}`)} ${theme.fg("text", task3.description)} ${theme.fg("dim", task3.id.slice(0, 8))}`);
|
|
2604
2631
|
}
|
|
2605
2632
|
}
|
|
2606
|
-
|
|
2607
|
-
["
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2633
|
+
if (width < TASK_PREVIEW_MIN_WIDTH || tasks.length === 0) {
|
|
2634
|
+
return box([tabs, "", ...listLines]);
|
|
2635
|
+
}
|
|
2636
|
+
const task2 = tasks[selectedTask];
|
|
2637
|
+
if (!task2)
|
|
2638
|
+
return box([tabs, "", ...listLines]);
|
|
2639
|
+
const leftWidth = Math.max(44, Math.min(64, Math.floor(contentWidth * 0.52)));
|
|
2640
|
+
const rightWidth = Math.max(1, contentWidth - leftWidth - 3);
|
|
2641
|
+
const transcript2 = taskTranscript(task2).flatMap((line) => wrapTextWithAnsi(line, rightWidth));
|
|
2642
|
+
const duration2 = taskDuration(taskDetails(task2));
|
|
2643
|
+
const metrics2 = [
|
|
2644
|
+
task2.currentTool ? `→ ${task2.currentTool}` : undefined,
|
|
2645
|
+
task2.toolCalls === undefined ? undefined : `${task2.toolCalls} tool call${task2.toolCalls === 1 ? "" : "s"}`,
|
|
2646
|
+
duration2,
|
|
2647
|
+
task2.retryAttempt ? `retry ${task2.retryAttempt}` : undefined
|
|
2648
|
+
].filter(Boolean);
|
|
2649
|
+
const previewLines = [
|
|
2650
|
+
`${theme.fg("accent", theme.bold(`@${task2.agent}`))} ${theme.fg("text", task2.description)}`,
|
|
2651
|
+
`${taskState(theme, task2)} ${theme.fg("dim", task2.id)}`,
|
|
2652
|
+
metrics2.length > 0 ? theme.fg("dim", metrics2.join(" · ")) : "",
|
|
2653
|
+
theme.fg("dim", "Latest activity"),
|
|
2654
|
+
...transcript2.slice(-TASK_PREVIEW_LINES).map((line) => theme.fg("toolOutput", line))
|
|
2655
|
+
];
|
|
2656
|
+
const divider = theme.fg("border", "│");
|
|
2657
|
+
const rowCount = Math.max(listLines.length, previewLines.length);
|
|
2658
|
+
const lines2 = Array.from({ length: rowCount }, (_, index) => {
|
|
2659
|
+
const left = pad(listLines[index] ?? "", leftWidth);
|
|
2660
|
+
const right = truncateToWidth2(previewLines[index] ?? "", rightWidth);
|
|
2661
|
+
return `${left} ${divider} ${right}`;
|
|
2662
|
+
});
|
|
2663
|
+
return box([tabs, "", ...lines2]);
|
|
2613
2664
|
}
|
|
2614
2665
|
const task = tasks[selectedTask];
|
|
2615
2666
|
if (!task)
|
|
2616
2667
|
return box([tabs, "", "No task sessions in this session."]);
|
|
2617
2668
|
const transcript = taskTranscript(task).flatMap((line) => wrapTextWithAnsi(line, contentWidth));
|
|
2618
2669
|
const maxScroll = Math.max(0, transcript.length - INSPECTOR_BODY_LINES);
|
|
2619
|
-
scroll = Math.min(scroll, maxScroll);
|
|
2670
|
+
scroll = follow ? maxScroll : Math.min(scroll, maxScroll);
|
|
2620
2671
|
const shown = transcript.slice(scroll, scroll + INSPECTOR_BODY_LINES);
|
|
2621
2672
|
const duration = taskDuration(taskDetails(task));
|
|
2622
2673
|
const metrics = [
|
|
@@ -2628,7 +2679,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
2628
2679
|
tabs,
|
|
2629
2680
|
"",
|
|
2630
2681
|
`${theme.fg("accent", theme.bold(`@${task.agent}`))} ${theme.fg("text", task.description)}`,
|
|
2631
|
-
`${taskState(theme, task)} ${theme.fg("dim", metrics.join(" · "))}`,
|
|
2682
|
+
`${taskState(theme, task)} ${theme.fg("dim", metrics.join(" · "))} ${theme.fg("dim", "·")} ${theme.fg(follow ? "accent" : "muted", `Follow: ${follow ? "on" : "off"}`)}`,
|
|
2632
2683
|
"",
|
|
2633
2684
|
...shown.map((line) => theme.fg("toolOutput", line))
|
|
2634
2685
|
];
|
|
@@ -2637,12 +2688,6 @@ ${this.primaryAgent.prompt}` };
|
|
|
2637
2688
|
if (transcript.length > INSPECTOR_BODY_LINES) {
|
|
2638
2689
|
lines.push(theme.fg("dim", `${scroll + 1}–${scroll + shown.length} of ${transcript.length}`));
|
|
2639
2690
|
}
|
|
2640
|
-
lines.push("", dialogKeys(theme, [
|
|
2641
|
-
["↑↓", "scroll"],
|
|
2642
|
-
...task.parentTaskId ? [["Backspace", "parent"]] : [],
|
|
2643
|
-
["Esc", "task list"],
|
|
2644
|
-
["Tab", "next tab"]
|
|
2645
|
-
]));
|
|
2646
2691
|
return box(lines.map((line) => truncateToWidth2(line, contentWidth)));
|
|
2647
2692
|
},
|
|
2648
2693
|
handleInput: (data) => {
|
|
@@ -2674,7 +2719,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
2674
2719
|
}
|
|
2675
2720
|
return;
|
|
2676
2721
|
}
|
|
2677
|
-
if (data.toLowerCase() === "s" && tab
|
|
2722
|
+
if ((matchesKey(data, "shift+tab") || data.toLowerCase() === "s") && (tab === "agents" || tab === "settings")) {
|
|
2678
2723
|
if (saving)
|
|
2679
2724
|
return;
|
|
2680
2725
|
if (dirtySettings.size > 0) {
|
|
@@ -2697,9 +2742,10 @@ ${this.primaryAgent.prompt}` };
|
|
|
2697
2742
|
ctx.ui.notify("Save changes with Enter or discard them with R before leaving", "warning");
|
|
2698
2743
|
return;
|
|
2699
2744
|
}
|
|
2700
|
-
const tabs = ["agents", "tasks", "settings"];
|
|
2745
|
+
const tabs = ["agents", "tasks", "settings", "help"];
|
|
2701
2746
|
tab = tabs[(tabs.indexOf(tab) + 1) % tabs.length] ?? "agents";
|
|
2702
2747
|
detail = false;
|
|
2748
|
+
follow = false;
|
|
2703
2749
|
editing = false;
|
|
2704
2750
|
scroll = 0;
|
|
2705
2751
|
tui.requestRender();
|
|
@@ -2865,6 +2911,11 @@ ${this.primaryAgent.prompt}` };
|
|
|
2865
2911
|
tui.requestRender();
|
|
2866
2912
|
return;
|
|
2867
2913
|
}
|
|
2914
|
+
if (tab === "help") {
|
|
2915
|
+
if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c"))
|
|
2916
|
+
done();
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2868
2919
|
if (!detail) {
|
|
2869
2920
|
if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c"))
|
|
2870
2921
|
done();
|
|
@@ -2874,6 +2925,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
2874
2925
|
selectedTask = Math.min(tasks.length - 1, selectedTask + 1);
|
|
2875
2926
|
} else if (matchesKey(data, "return") && tasks.length > 0) {
|
|
2876
2927
|
detail = true;
|
|
2928
|
+
follow = true;
|
|
2877
2929
|
scroll = 0;
|
|
2878
2930
|
} else
|
|
2879
2931
|
return;
|
|
@@ -2885,19 +2937,33 @@ ${this.primaryAgent.prompt}` };
|
|
|
2885
2937
|
return;
|
|
2886
2938
|
if (matchesKey(data, "escape")) {
|
|
2887
2939
|
detail = false;
|
|
2940
|
+
follow = false;
|
|
2888
2941
|
scroll = 0;
|
|
2889
2942
|
} else if (matchesKey(data, "ctrl+c")) {
|
|
2890
2943
|
done();
|
|
2891
|
-
} else if (
|
|
2944
|
+
} else if (data.toLowerCase() === "f") {
|
|
2945
|
+
follow = !follow;
|
|
2946
|
+
} else if (!follow && matchesKey(data, "up")) {
|
|
2892
2947
|
scroll = Math.max(0, scroll - 1);
|
|
2893
|
-
} else if (matchesKey(data, "down")) {
|
|
2948
|
+
} else if (!follow && matchesKey(data, "down")) {
|
|
2894
2949
|
scroll += 1;
|
|
2950
|
+
} else if (!follow && matchesKey(data, "pageUp")) {
|
|
2951
|
+
scroll = Math.max(0, scroll - INSPECTOR_BODY_LINES);
|
|
2952
|
+
} else if (!follow && matchesKey(data, "pageDown")) {
|
|
2953
|
+
scroll += INSPECTOR_BODY_LINES;
|
|
2954
|
+
} else if (!follow && matchesKey(data, "home")) {
|
|
2955
|
+
scroll = 0;
|
|
2956
|
+
} else if (!follow && matchesKey(data, "end")) {
|
|
2957
|
+
scroll = Number.MAX_SAFE_INTEGER;
|
|
2895
2958
|
} else if (matchesKey(data, "backspace")) {
|
|
2896
2959
|
const parentIndex = task.parentTaskId ? tasks.findIndex((candidate) => candidate.id === task.parentTaskId) : -1;
|
|
2897
|
-
if (parentIndex >= 0)
|
|
2960
|
+
if (parentIndex >= 0) {
|
|
2898
2961
|
selectedTask = parentIndex;
|
|
2899
|
-
|
|
2962
|
+
follow = true;
|
|
2963
|
+
} else {
|
|
2900
2964
|
detail = false;
|
|
2965
|
+
follow = false;
|
|
2966
|
+
}
|
|
2901
2967
|
scroll = 0;
|
|
2902
2968
|
} else
|
|
2903
2969
|
return;
|
|
@@ -3661,33 +3727,26 @@ ${renderTaskResult(task.id, "error", message)}`);
|
|
|
3661
3727
|
if (!ctx.hasUI || ctx.mode !== undefined && ctx.mode !== "tui")
|
|
3662
3728
|
return;
|
|
3663
3729
|
const tasks = [...this.tasks.values()];
|
|
3664
|
-
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
3665
|
-
const rootId = (task) => {
|
|
3666
|
-
const seen = new Set;
|
|
3667
|
-
let current = task;
|
|
3668
|
-
while (current.parentTaskId && !seen.has(current.id)) {
|
|
3669
|
-
seen.add(current.id);
|
|
3670
|
-
const parent = byId.get(current.parentTaskId);
|
|
3671
|
-
if (!parent)
|
|
3672
|
-
break;
|
|
3673
|
-
current = parent;
|
|
3674
|
-
}
|
|
3675
|
-
return current.id;
|
|
3676
|
-
};
|
|
3677
3730
|
const active = tasks.filter((task) => task.state === "queued" || task.state === "running");
|
|
3678
|
-
|
|
3679
|
-
if (activeRoots.size === 0) {
|
|
3731
|
+
if (active.length === 0) {
|
|
3680
3732
|
ctx.ui.setWidget(TASK_WIDGET, undefined);
|
|
3681
3733
|
return;
|
|
3682
3734
|
}
|
|
3683
|
-
const visible = tasks
|
|
3735
|
+
const visible = activeTaskRecords(tasks);
|
|
3736
|
+
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
3737
|
+
const running = active.filter((task) => task.state === "running").length;
|
|
3738
|
+
const queued = active.length - running;
|
|
3739
|
+
const runningSummary = this.maxSubagents > 0 ? `${running}/${this.maxSubagents} running` : `${running} running`;
|
|
3740
|
+
const summary = queued > 0 ? `${runningSummary} · ${queued} queued` : runningSummary;
|
|
3684
3741
|
ctx.ui.setWidget(TASK_WIDGET, (_tui, theme) => ({
|
|
3685
3742
|
render: (width) => {
|
|
3686
|
-
const header = theme.fg("accent", theme.bold("Subagents")) + theme.fg("dim", ` ${
|
|
3743
|
+
const header = theme.fg("accent", theme.bold("Subagents")) + theme.fg("dim", ` ${summary}`);
|
|
3687
3744
|
const tree = taskTreeLines(visible, (task) => {
|
|
3688
3745
|
const agent = theme.fg("accent", `@${task.agent}`);
|
|
3689
3746
|
const description = theme.fg("text", task.description);
|
|
3690
|
-
|
|
3747
|
+
const progress = taskProgress(byId.get(task.id));
|
|
3748
|
+
const suffix = progress.length > 0 ? theme.fg("dim", ` · ${progress.join(" · ")}`) : "";
|
|
3749
|
+
return `${taskState(theme, task)} ${agent} ${description}${suffix}`;
|
|
3691
3750
|
});
|
|
3692
3751
|
const shown = tree.slice(0, 8);
|
|
3693
3752
|
if (tree.length > shown.length) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-landstrip",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.8",
|
|
4
4
|
"description": "Sandboxed Bash and process-backed agents for Pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"landstrip",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"ci:test": "npm run test"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@landstrip/landstrip": "^0.18.
|
|
42
|
+
"@landstrip/landstrip": "^0.18.8",
|
|
43
43
|
"jsonc-parser": "^3.3.1",
|
|
44
44
|
"minimatch": "^10.2.5",
|
|
45
45
|
"yaml": "^2.9.0"
|