pi-landstrip 0.18.21 → 0.18.22
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 +203 -97
- package/package.json +2 -2
package/dist/index.ts
CHANGED
|
@@ -94,6 +94,7 @@ import {
|
|
|
94
94
|
SessionManager
|
|
95
95
|
} from "@earendil-works/pi-coding-agent";
|
|
96
96
|
import {
|
|
97
|
+
decodeKittyPrintable,
|
|
97
98
|
matchesKey,
|
|
98
99
|
Text,
|
|
99
100
|
truncateToWidth as truncateToWidth2,
|
|
@@ -1609,17 +1610,16 @@ var AGENTS_HELP_ROWS = [
|
|
|
1609
1610
|
["F", "Toggle task log follow"],
|
|
1610
1611
|
["Page Up / Down", "Scroll task output by page"],
|
|
1611
1612
|
["Home / End", "Jump to task output boundary"],
|
|
1612
|
-
["Enter", "Open log, set primary, or
|
|
1613
|
-
["Esc", "
|
|
1613
|
+
["Enter", "Open log, set primary, or edit setting"],
|
|
1614
|
+
["Esc", "Cancel edit, go back, or close"],
|
|
1614
1615
|
["Ctrl+C", "Close"],
|
|
1615
|
-
["
|
|
1616
|
+
["Ctrl+D", "Delete selected task sessions"],
|
|
1617
|
+
["Space", "Enable agent or select task"],
|
|
1616
1618
|
["E", "Edit project agent"],
|
|
1617
1619
|
["X", "Delete project agent"],
|
|
1618
1620
|
["Y / N", "Confirm or cancel deletion"],
|
|
1619
|
-
["
|
|
1620
|
-
["
|
|
1621
|
-
["0-9 / + / -", "Set subagent limit"],
|
|
1622
|
-
["Backspace", "Open parent task"]
|
|
1621
|
+
["Empty + Enter", "Use global setting in Project scope"],
|
|
1622
|
+
["Backspace", "Open parent task or edit setting"]
|
|
1623
1623
|
];
|
|
1624
1624
|
var MIN_SUPPORTED_PI_VERSION = [0, 82, 0];
|
|
1625
1625
|
var cachedPiPackage;
|
|
@@ -1693,6 +1693,10 @@ function readPiPackage(pkgPath) {
|
|
|
1693
1693
|
return;
|
|
1694
1694
|
}
|
|
1695
1695
|
}
|
|
1696
|
+
function isControlChar(char) {
|
|
1697
|
+
const code = char.charCodeAt(0);
|
|
1698
|
+
return code < 32 || code === 127 || code >= 128 && code <= 159;
|
|
1699
|
+
}
|
|
1696
1700
|
var taskParameters = Type.Object({
|
|
1697
1701
|
description: Type.String({ description: "Short task label (3-5 words)" }),
|
|
1698
1702
|
prompt: Type.String({ description: "Full instructions for the subagent" }),
|
|
@@ -2406,10 +2410,11 @@ ${this.primaryAgent.prompt}` };
|
|
|
2406
2410
|
return;
|
|
2407
2411
|
}
|
|
2408
2412
|
let selectedSetting = 0;
|
|
2409
|
-
|
|
2413
|
+
let settingEditor;
|
|
2410
2414
|
let saving = false;
|
|
2411
|
-
let editing = false;
|
|
2412
2415
|
let confirmingDeleteAgent;
|
|
2416
|
+
let pendingTaskAction;
|
|
2417
|
+
const selectedTaskIds = new Set;
|
|
2413
2418
|
let follow = requested.length > 0;
|
|
2414
2419
|
let scroll = 0;
|
|
2415
2420
|
const reloadAgents = () => {
|
|
@@ -2429,9 +2434,21 @@ ${this.primaryAgent.prompt}` };
|
|
|
2429
2434
|
const refreshTasks = () => {
|
|
2430
2435
|
const selectedId = tasks[selectedTask]?.id;
|
|
2431
2436
|
tasks = [...this.tasks.values()];
|
|
2437
|
+
const visibleTaskIds = new Set(tasks.map((task) => task.id));
|
|
2438
|
+
for (const taskId of selectedTaskIds) {
|
|
2439
|
+
if (!visibleTaskIds.has(taskId))
|
|
2440
|
+
selectedTaskIds.delete(taskId);
|
|
2441
|
+
}
|
|
2432
2442
|
const nextSelected = selectedId ? tasks.findIndex((task) => task.id === selectedId) : selectedTask;
|
|
2433
2443
|
selectedTask = Math.max(0, Math.min(nextSelected < 0 ? 0 : nextSelected, tasks.length - 1));
|
|
2434
2444
|
};
|
|
2445
|
+
const taskTargets = () => {
|
|
2446
|
+
const selected = tasks.filter((task2) => selectedTaskIds.has(task2.id));
|
|
2447
|
+
if (selected.length > 0)
|
|
2448
|
+
return selected;
|
|
2449
|
+
const task = tasks[selectedTask];
|
|
2450
|
+
return task ? [task] : [];
|
|
2451
|
+
};
|
|
2435
2452
|
const refreshAgentRuntime = async (name) => {
|
|
2436
2453
|
reloadAgents();
|
|
2437
2454
|
if (this.primaryAgent?.name === name) {
|
|
@@ -2442,15 +2459,9 @@ ${this.primaryAgent.prompt}` };
|
|
|
2442
2459
|
};
|
|
2443
2460
|
const scopedAgent = (agent) => scope === "global" ? globalCatalog.agents.get(agent.name) : agent;
|
|
2444
2461
|
const selectedMaxSubagents = () => scope === "global" ? maxSubagentsSettings.global : maxSubagentsSettings.project ?? maxSubagentsSettings.global;
|
|
2445
|
-
const
|
|
2446
|
-
|
|
2447
|
-
dirtySettings.add(0);
|
|
2448
|
-
};
|
|
2462
|
+
const settingField = (setting) => setting === 0 ? "maxSubagents" : "sandboxEnabled";
|
|
2463
|
+
const settingLabel = (settingScope, field) => `${settingScope === "global" ? "Global" : "Project"} ${field}`;
|
|
2449
2464
|
const selectedSandboxEnabled = () => scope === "global" ? sandboxSettings.global : sandboxSettings.project ?? sandboxSettings.global;
|
|
2450
|
-
const updateSelectedSandboxEnabled = (value) => {
|
|
2451
|
-
sandboxSettings = scope === "global" ? { ...sandboxSettings, global: value } : { ...sandboxSettings, project: value };
|
|
2452
|
-
dirtySettings.add(1);
|
|
2453
|
-
};
|
|
2454
2465
|
await ctx.ui.custom((tui, theme, _keybindings, done) => ({
|
|
2455
2466
|
render: (width) => {
|
|
2456
2467
|
const contentWidth = Math.max(1, width - 4);
|
|
@@ -2548,27 +2559,33 @@ ${this.primaryAgent.prompt}` };
|
|
|
2548
2559
|
const sandboxInherited = scope === "project" && sandboxSettings.project === undefined;
|
|
2549
2560
|
const rows = [
|
|
2550
2561
|
{
|
|
2551
|
-
label: "
|
|
2562
|
+
label: "maxSubagents",
|
|
2552
2563
|
value: String(selectedMaxSubagents()),
|
|
2553
2564
|
inherited: maxSubagentsInherited,
|
|
2554
2565
|
unavailable: false
|
|
2555
2566
|
},
|
|
2556
2567
|
{
|
|
2557
|
-
label: "
|
|
2568
|
+
label: "sandboxEnabled",
|
|
2558
2569
|
value: selectedSandboxEnabled() ? "on" : "off",
|
|
2559
2570
|
inherited: sandboxInherited,
|
|
2560
2571
|
unavailable: sandboxCallbacks === undefined
|
|
2561
2572
|
}
|
|
2562
2573
|
];
|
|
2563
2574
|
const lines2 = [tabs, ""];
|
|
2575
|
+
if (settingEditor) {
|
|
2576
|
+
const current = settingEditor.setting === 0 ? String(selectedMaxSubagents()) : selectedSandboxEnabled() ? "on" : "off";
|
|
2577
|
+
lines2.push(theme.fg("dim", ` ${settingLabel(settingEditor.scope, settingEditor.field)} · current ${current}`), "", ` ${theme.fg("accent", "›")} [ ${settingEditor.value}${theme.fg("accent", "█")} ]`, "", theme.fg("dim", settingEditor.scope === "project" ? " empty inherit · enter submit · esc cancel" : " enter submit · esc cancel"));
|
|
2578
|
+
if (saving)
|
|
2579
|
+
lines2.push("", theme.fg("dim", "Saving…"));
|
|
2580
|
+
return box(lines2);
|
|
2581
|
+
}
|
|
2564
2582
|
for (const [index, row] of rows.entries()) {
|
|
2565
2583
|
const selected = index === selectedSetting;
|
|
2566
2584
|
const cursor = selected ? theme.fg("accent", "›") : " ";
|
|
2567
2585
|
const text = `[ ${row.value} ]`;
|
|
2568
2586
|
const value = row.inherited ? theme.fg("dim", text) : selected ? theme.fg("accent", text) : theme.fg(row.unavailable ? "muted" : "text", text);
|
|
2569
2587
|
const label = theme.fg(row.unavailable ? "muted" : "text", row.label);
|
|
2570
|
-
|
|
2571
|
-
lines2.push(`${cursor} ${value} ${label}${dirty}`);
|
|
2588
|
+
lines2.push(`${cursor} ${value} ${label}`);
|
|
2572
2589
|
}
|
|
2573
2590
|
if (selectedSetting === 1) {
|
|
2574
2591
|
lines2.push("", theme.fg("dim", rows[1]?.inherited ? "Controls OS sandboxing. Use /sandbox to inspect its policy. Using the Global value." : "Controls OS sandboxing. Use /sandbox to inspect its policy."));
|
|
@@ -2598,10 +2615,23 @@ ${this.primaryAgent.prompt}` };
|
|
|
2598
2615
|
for (const [offset, task2] of shown2.entries()) {
|
|
2599
2616
|
const index = start + offset;
|
|
2600
2617
|
const cursor = index === selectedTask ? theme.fg("accent", "›") : " ";
|
|
2618
|
+
const selected = selectedTaskIds.has(task2.id) ? theme.fg("accent", "✓") : " ";
|
|
2601
2619
|
const indent = " ".repeat(Math.max(0, task2.depth - 1));
|
|
2602
|
-
listLines.push(`${cursor} ${indent}${taskState(theme, task2)} ${theme.fg("accent", `@${task2.agent}`)} ${theme.fg("text", task2.description)} ${theme.fg("dim", task2.id.slice(0, 8))}`);
|
|
2620
|
+
listLines.push(`${cursor} ${selected} ${indent}${taskState(theme, task2)} ${theme.fg("accent", `@${task2.agent}`)} ${theme.fg("text", task2.description)} ${theme.fg("dim", task2.id.slice(0, 8))}`);
|
|
2603
2621
|
}
|
|
2604
2622
|
}
|
|
2623
|
+
const selectedCount = tasks.filter((task2) => selectedTaskIds.has(task2.id)).length;
|
|
2624
|
+
if (selectedCount > 0) {
|
|
2625
|
+
listLines.push("", theme.fg("dim", `${selectedCount} selected`));
|
|
2626
|
+
}
|
|
2627
|
+
listLines.push("");
|
|
2628
|
+
if (pendingTaskAction) {
|
|
2629
|
+
const count = pendingTaskAction.taskIds.length;
|
|
2630
|
+
const label = count === 1 ? `Delete ${pendingTaskAction.taskIds[0]?.slice(0, 8) ?? "task"}?` : `Delete ${count} selected task sessions?`;
|
|
2631
|
+
listLines.push(`${theme.fg("warning", label)} ${theme.fg("dim", "enter confirm · esc cancel")}`);
|
|
2632
|
+
} else {
|
|
2633
|
+
listLines.push(theme.fg("dim", "↑↓ move · space select · enter inspect · ctrl+d delete · esc close"));
|
|
2634
|
+
}
|
|
2605
2635
|
return box([tabs, "", ...listLines]);
|
|
2606
2636
|
}
|
|
2607
2637
|
const task = tasks[selectedTask];
|
|
@@ -2663,29 +2693,22 @@ ${this.primaryAgent.prompt}` };
|
|
|
2663
2693
|
}
|
|
2664
2694
|
return;
|
|
2665
2695
|
}
|
|
2666
|
-
if ((matchesKey(data, "shift+tab") || data.toLowerCase() === "s") && (tab === "primary" || tab === "subagent" || tab === "settings")) {
|
|
2696
|
+
if ((matchesKey(data, "shift+tab") || data.toLowerCase() === "s") && (tab === "primary" || tab === "subagent" || tab === "settings") && settingEditor === undefined) {
|
|
2667
2697
|
if (saving)
|
|
2668
2698
|
return;
|
|
2669
|
-
if (dirtySettings.size > 0) {
|
|
2670
|
-
ctx.ui.notify("Save or discard settings changes before changing scope", "warning");
|
|
2671
|
-
return;
|
|
2672
|
-
}
|
|
2673
2699
|
if (!projectTrusted && scope === "global") {
|
|
2674
2700
|
ctx.ui.notify("Project settings require a trusted project", "warning");
|
|
2675
2701
|
return;
|
|
2676
2702
|
}
|
|
2677
2703
|
scope = scope === "project" ? "global" : "project";
|
|
2678
|
-
editing = false;
|
|
2679
2704
|
reloadAgents();
|
|
2680
2705
|
reloadSettings();
|
|
2681
2706
|
tui.requestRender();
|
|
2682
2707
|
return;
|
|
2683
2708
|
}
|
|
2684
2709
|
if (matchesKey(data, "tab")) {
|
|
2685
|
-
if (
|
|
2686
|
-
ctx.ui.notify("Save changes with Enter or discard them with R before leaving", "warning");
|
|
2710
|
+
if (settingEditor !== undefined)
|
|
2687
2711
|
return;
|
|
2688
|
-
}
|
|
2689
2712
|
const selectedName = tab === "primary" || tab === "subagent" ? agentsForTab()[selectedAgent]?.name : undefined;
|
|
2690
2713
|
const tabs = ["primary", "subagent", "tasks", "log", "settings", "help"];
|
|
2691
2714
|
tab = tabs[(tabs.indexOf(tab) + 1) % tabs.length] ?? "primary";
|
|
@@ -2699,7 +2722,6 @@ ${this.primaryAgent.prompt}` };
|
|
|
2699
2722
|
follow = true;
|
|
2700
2723
|
else
|
|
2701
2724
|
follow = false;
|
|
2702
|
-
editing = false;
|
|
2703
2725
|
scroll = 0;
|
|
2704
2726
|
tui.requestRender();
|
|
2705
2727
|
return;
|
|
@@ -2784,82 +2806,109 @@ ${this.primaryAgent.prompt}` };
|
|
|
2784
2806
|
if (tab === "settings") {
|
|
2785
2807
|
if (saving)
|
|
2786
2808
|
return;
|
|
2787
|
-
if (matchesKey(data, "
|
|
2788
|
-
if (dirtySettings.size > 0) {
|
|
2789
|
-
ctx.ui.notify("Save changes with Enter or discard them with R before closing", "warning");
|
|
2790
|
-
return;
|
|
2791
|
-
}
|
|
2809
|
+
if (matchesKey(data, "ctrl+c")) {
|
|
2792
2810
|
done();
|
|
2793
2811
|
return;
|
|
2794
2812
|
}
|
|
2795
|
-
if (
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2813
|
+
if (settingEditor) {
|
|
2814
|
+
if (matchesKey(data, "escape")) {
|
|
2815
|
+
settingEditor = undefined;
|
|
2816
|
+
tui.requestRender();
|
|
2817
|
+
return;
|
|
2818
|
+
}
|
|
2819
|
+
if (matchesKey(data, "backspace")) {
|
|
2820
|
+
settingEditor.value = settingEditor.value.slice(0, -1);
|
|
2821
|
+
tui.requestRender();
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
if (matchesKey(data, "return")) {
|
|
2825
|
+
const editor = settingEditor;
|
|
2826
|
+
const input = editor.value.trim();
|
|
2827
|
+
let save;
|
|
2828
|
+
let notifyMessage;
|
|
2829
|
+
if (input === "") {
|
|
2830
|
+
if (editor.scope !== "project") {
|
|
2831
|
+
settingEditor = undefined;
|
|
2832
|
+
tui.requestRender();
|
|
2833
|
+
return;
|
|
2834
|
+
}
|
|
2835
|
+
save = editor.setting === 0 ? clearMaxSubagentsConfigForScope(ctx.cwd, "project") : sandboxCallbacks?.clearProject(ctx);
|
|
2836
|
+
notifyMessage = `${settingLabel(editor.scope, editor.field)} inherits Global`;
|
|
2837
|
+
} else if (editor.setting === 0) {
|
|
2838
|
+
if (!/^\d+$/.test(input)) {
|
|
2839
|
+
ctx.ui.notify(`Enter a whole number between 0 and ${MAX_SUBAGENTS}`, "error");
|
|
2840
|
+
return;
|
|
2841
|
+
}
|
|
2842
|
+
const parsed = Number(input);
|
|
2843
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > MAX_SUBAGENTS) {
|
|
2844
|
+
ctx.ui.notify(`Enter a whole number between 0 and ${MAX_SUBAGENTS}`, "error");
|
|
2845
|
+
return;
|
|
2846
|
+
}
|
|
2847
|
+
save = setMaxSubagentsConfigForScope(ctx.cwd, parsed, editor.scope);
|
|
2848
|
+
notifyMessage = `${settingLabel(editor.scope, editor.field)} = ${parsed}`;
|
|
2849
|
+
} else {
|
|
2850
|
+
const normalized = input.toLowerCase();
|
|
2851
|
+
const parsed = ["1", "on", "true", "yes"].includes(normalized) ? true : ["0", "off", "false", "no"].includes(normalized) ? false : undefined;
|
|
2852
|
+
if (parsed === undefined) {
|
|
2853
|
+
ctx.ui.notify("Enter on/off, true/false, or 1/0", "error");
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
save = sandboxCallbacks?.setEnabled(ctx, parsed, editor.scope);
|
|
2857
|
+
notifyMessage = `${settingLabel(editor.scope, editor.field)} = ${parsed ? "on" : "off"}`;
|
|
2858
|
+
}
|
|
2859
|
+
if (!save) {
|
|
2860
|
+
ctx.ui.notify("Sandbox settings are unavailable", "warning");
|
|
2861
|
+
return;
|
|
2862
|
+
}
|
|
2863
|
+
saving = true;
|
|
2864
|
+
settingEditor = undefined;
|
|
2865
|
+
tui.requestRender();
|
|
2866
|
+
save.then(() => {
|
|
2867
|
+
reloadSettings();
|
|
2868
|
+
const loadedMaxSubagents = loadMaxSubagentsSettings(ctx.cwd, projectTrusted);
|
|
2869
|
+
this.setMaxSubagents(loadedMaxSubagents.project ?? loadedMaxSubagents.global);
|
|
2870
|
+
maxSubagentsSettings = loadedMaxSubagents;
|
|
2871
|
+
sandboxSettings = sandboxCallbacks?.load(ctx.cwd, projectTrusted) ?? {
|
|
2872
|
+
global: true
|
|
2873
|
+
};
|
|
2874
|
+
ctx.ui.notify(notifyMessage ?? "Setting updated", "info");
|
|
2875
|
+
}).catch((error) => ctx.ui.notify(`Could not save setting: ${formatError(error)}`, "error")).finally(() => {
|
|
2876
|
+
saving = false;
|
|
2877
|
+
tui.requestRender();
|
|
2878
|
+
});
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2881
|
+
const kittyChar = decodeKittyPrintable(data);
|
|
2882
|
+
const printable = kittyChar ?? (data.length === 1 && !isControlChar(data) ? data : undefined);
|
|
2883
|
+
if (printable === undefined)
|
|
2884
|
+
return;
|
|
2885
|
+
if (settingEditor.setting === 0 && !/^\d$/.test(printable))
|
|
2886
|
+
return;
|
|
2887
|
+
if (settingEditor.setting === 1 && !/^[a-zA-Z0-9]$/.test(printable))
|
|
2888
|
+
return;
|
|
2889
|
+
settingEditor.value += printable;
|
|
2799
2890
|
tui.requestRender();
|
|
2800
2891
|
return;
|
|
2801
2892
|
}
|
|
2802
|
-
if (matchesKey(data, "
|
|
2893
|
+
if (matchesKey(data, "escape")) {
|
|
2894
|
+
done();
|
|
2895
|
+
return;
|
|
2896
|
+
}
|
|
2897
|
+
if (matchesKey(data, "up"))
|
|
2803
2898
|
selectedSetting = Math.max(0, selectedSetting - 1);
|
|
2804
|
-
|
|
2805
|
-
} else if (matchesKey(data, "down")) {
|
|
2899
|
+
else if (matchesKey(data, "down"))
|
|
2806
2900
|
selectedSetting = Math.min(1, selectedSetting + 1);
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
const value = Number(editing ? `${selectedMaxSubagents()}${data}` : data);
|
|
2810
|
-
if (value <= MAX_SUBAGENTS) {
|
|
2811
|
-
updateSelectedMaxSubagents(value);
|
|
2812
|
-
editing = true;
|
|
2813
|
-
}
|
|
2814
|
-
} else if (selectedSetting === 0 && (data === "+" || data === "-")) {
|
|
2815
|
-
updateSelectedMaxSubagents(Math.min(MAX_SUBAGENTS, Math.max(0, selectedMaxSubagents() + (data === "+" ? 1 : -1))));
|
|
2816
|
-
editing = false;
|
|
2817
|
-
} else if (selectedSetting === 1 && data === " " && sandboxCallbacks) {
|
|
2818
|
-
updateSelectedSandboxEnabled(!selectedSandboxEnabled());
|
|
2819
|
-
editing = false;
|
|
2820
|
-
} else if (data === "i" && scope === "project") {
|
|
2821
|
-
if (selectedSetting === 0) {
|
|
2822
|
-
maxSubagentsSettings = { ...maxSubagentsSettings, project: undefined };
|
|
2823
|
-
} else {
|
|
2824
|
-
sandboxSettings = { ...sandboxSettings, project: undefined };
|
|
2825
|
-
}
|
|
2826
|
-
dirtySettings.add(selectedSetting);
|
|
2827
|
-
editing = false;
|
|
2828
|
-
} else if (matchesKey(data, "return")) {
|
|
2829
|
-
const setting = selectedSetting;
|
|
2830
|
-
if (!dirtySettings.has(setting))
|
|
2831
|
-
return;
|
|
2832
|
-
const pendingMaxSubagents = maxSubagentsSettings;
|
|
2833
|
-
const pendingSandbox = sandboxSettings;
|
|
2834
|
-
const inherited = scope === "project" && (setting === 0 ? pendingMaxSubagents.project === undefined : pendingSandbox.project === undefined);
|
|
2835
|
-
const maxSubagents = selectedMaxSubagents();
|
|
2836
|
-
const sandboxEnabled = selectedSandboxEnabled();
|
|
2837
|
-
let save;
|
|
2838
|
-
if (setting === 0) {
|
|
2839
|
-
save = inherited ? clearMaxSubagentsConfigForScope(ctx.cwd, "project") : setMaxSubagentsConfigForScope(ctx.cwd, maxSubagents, scope);
|
|
2840
|
-
} else if (!sandboxCallbacks) {
|
|
2901
|
+
else if (matchesKey(data, "return")) {
|
|
2902
|
+
if (selectedSetting === 1 && !sandboxCallbacks) {
|
|
2841
2903
|
ctx.ui.notify("Sandbox settings are unavailable", "warning");
|
|
2842
2904
|
return;
|
|
2843
|
-
} else {
|
|
2844
|
-
save = inherited ? sandboxCallbacks.clearProject(ctx) : sandboxCallbacks.setEnabled(ctx, sandboxEnabled, scope);
|
|
2845
2905
|
}
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
};
|
|
2853
|
-
this.setMaxSubagents(loadedMaxSubagents.project ?? loadedMaxSubagents.global);
|
|
2854
|
-
maxSubagentsSettings = dirtySettings.has(0) ? pendingMaxSubagents : loadedMaxSubagents;
|
|
2855
|
-
sandboxSettings = dirtySettings.has(1) ? pendingSandbox : loadedSandbox;
|
|
2856
|
-
editing = false;
|
|
2857
|
-
ctx.ui.notify(inherited ? `${setting === 0 ? "Maximum subagents" : "Sandbox"} now uses the global value` : `${setting === 0 ? "Maximum subagents" : "Sandbox"} updated in ${scope} settings`, "info");
|
|
2858
|
-
}).catch((error) => ctx.ui.notify(`Could not save setting: ${formatError(error)}`, "error")).finally(() => {
|
|
2859
|
-
saving = false;
|
|
2860
|
-
tui.requestRender();
|
|
2861
|
-
});
|
|
2862
|
-
return;
|
|
2906
|
+
settingEditor = {
|
|
2907
|
+
setting: selectedSetting,
|
|
2908
|
+
scope,
|
|
2909
|
+
field: settingField(selectedSetting),
|
|
2910
|
+
value: ""
|
|
2911
|
+
};
|
|
2863
2912
|
} else
|
|
2864
2913
|
return;
|
|
2865
2914
|
tui.requestRender();
|
|
@@ -2871,12 +2920,46 @@ ${this.primaryAgent.prompt}` };
|
|
|
2871
2920
|
return;
|
|
2872
2921
|
}
|
|
2873
2922
|
if (tab === "tasks") {
|
|
2923
|
+
if (pendingTaskAction) {
|
|
2924
|
+
if (matchesKey(data, "return")) {
|
|
2925
|
+
const taskIds = pendingTaskAction.taskIds;
|
|
2926
|
+
pendingTaskAction = undefined;
|
|
2927
|
+
const deleted = this.deleteTasks(taskIds, ctx);
|
|
2928
|
+
for (const taskId of taskIds)
|
|
2929
|
+
selectedTaskIds.delete(taskId);
|
|
2930
|
+
refreshTasks();
|
|
2931
|
+
if (deleted > 0) {
|
|
2932
|
+
ctx.ui.notify(`Deleted ${deleted} task session${deleted === 1 ? "" : "s"}`, "info");
|
|
2933
|
+
}
|
|
2934
|
+
tui.requestRender();
|
|
2935
|
+
return;
|
|
2936
|
+
}
|
|
2937
|
+
if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
|
|
2938
|
+
pendingTaskAction = undefined;
|
|
2939
|
+
tui.requestRender();
|
|
2940
|
+
}
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2874
2943
|
if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c"))
|
|
2875
2944
|
done();
|
|
2876
2945
|
else if (matchesKey(data, "up"))
|
|
2877
2946
|
selectedTask = Math.max(0, selectedTask - 1);
|
|
2878
2947
|
else if (matchesKey(data, "down") && tasks.length > 0) {
|
|
2879
2948
|
selectedTask = Math.min(tasks.length - 1, selectedTask + 1);
|
|
2949
|
+
} else if (data === " ") {
|
|
2950
|
+
const task2 = tasks[selectedTask];
|
|
2951
|
+
if (!task2)
|
|
2952
|
+
return;
|
|
2953
|
+
if (!selectedTaskIds.delete(task2.id))
|
|
2954
|
+
selectedTaskIds.add(task2.id);
|
|
2955
|
+
} else if (matchesKey(data, "ctrl+d")) {
|
|
2956
|
+
const targets = taskTargets();
|
|
2957
|
+
if (targets.length === 0)
|
|
2958
|
+
return;
|
|
2959
|
+
pendingTaskAction = {
|
|
2960
|
+
type: "delete",
|
|
2961
|
+
taskIds: targets.map((task2) => task2.id)
|
|
2962
|
+
};
|
|
2880
2963
|
} else if (matchesKey(data, "return") && tasks.length > 0) {
|
|
2881
2964
|
tab = "log";
|
|
2882
2965
|
follow = true;
|
|
@@ -3735,6 +3818,25 @@ ${renderTaskResult(task.id, "error", message)}`);
|
|
|
3735
3818
|
invalidate() {}
|
|
3736
3819
|
}));
|
|
3737
3820
|
}
|
|
3821
|
+
deleteTasks(taskIds, ctx) {
|
|
3822
|
+
let deleted = 0;
|
|
3823
|
+
for (const taskId of taskIds) {
|
|
3824
|
+
const task = this.tasks.get(taskId);
|
|
3825
|
+
if (!task)
|
|
3826
|
+
continue;
|
|
3827
|
+
task.deleted = true;
|
|
3828
|
+
task.delivered = true;
|
|
3829
|
+
this.controllers.get(taskId)?.abort();
|
|
3830
|
+
this.tasks.delete(taskId);
|
|
3831
|
+
this.pendingPrompts.delete(taskId);
|
|
3832
|
+
this.foregroundClaims.delete(taskId);
|
|
3833
|
+
this.persist(task);
|
|
3834
|
+
deleted += 1;
|
|
3835
|
+
}
|
|
3836
|
+
if (deleted > 0)
|
|
3837
|
+
this.updateTaskWidget(ctx);
|
|
3838
|
+
return deleted;
|
|
3839
|
+
}
|
|
3738
3840
|
restore(ctx) {
|
|
3739
3841
|
this.tasks.clear();
|
|
3740
3842
|
for (const entry of ctx.sessionManager.getBranch()) {
|
|
@@ -3743,6 +3845,10 @@ ${renderTaskResult(task.id, "error", message)}`);
|
|
|
3743
3845
|
const task = entry.data;
|
|
3744
3846
|
if (!task?.id || task.parentSessionId !== ctx.sessionManager.getSessionId())
|
|
3745
3847
|
continue;
|
|
3848
|
+
if (task.deleted) {
|
|
3849
|
+
this.tasks.delete(task.id);
|
|
3850
|
+
continue;
|
|
3851
|
+
}
|
|
3746
3852
|
this.tasks.set(task.id, {
|
|
3747
3853
|
...task,
|
|
3748
3854
|
usage: isTaskUsage(task.usage) ? { ...task.usage } : undefined,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-landstrip",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.22",
|
|
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.22",
|
|
43
43
|
"jsonc-parser": "^3.3.1",
|
|
44
44
|
"minimatch": "^10.2.5",
|
|
45
45
|
"yaml": "^2.9.0"
|