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.
Files changed (2) hide show
  1. package/dist/index.ts +203 -97
  2. 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 save"],
1613
- ["Esc", "Back or close"],
1613
+ ["Enter", "Open log, set primary, or edit setting"],
1614
+ ["Esc", "Cancel edit, go back, or close"],
1614
1615
  ["Ctrl+C", "Close"],
1615
- ["Space", "Enable agent or toggle sandbox"],
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
- ["I", "Use global value"],
1620
- ["R", "Discard setting changes"],
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
- const dirtySettings = new Set;
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 updateSelectedMaxSubagents = (value) => {
2446
- maxSubagentsSettings = scope === "global" ? { ...maxSubagentsSettings, global: value } : { ...maxSubagentsSettings, project: value };
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: "Maximum subagents",
2562
+ label: "maxSubagents",
2552
2563
  value: String(selectedMaxSubagents()),
2553
2564
  inherited: maxSubagentsInherited,
2554
2565
  unavailable: false
2555
2566
  },
2556
2567
  {
2557
- label: "Sandbox enabled",
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
- const dirty = dirtySettings.has(index) ? theme.fg("warning", " *") : "";
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 (tab === "settings" && dirtySettings.size > 0) {
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, "escape") || matchesKey(data, "ctrl+c")) {
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 (data.toLowerCase() === "r") {
2796
- reloadSettings();
2797
- dirtySettings.clear();
2798
- editing = false;
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, "up")) {
2893
+ if (matchesKey(data, "escape")) {
2894
+ done();
2895
+ return;
2896
+ }
2897
+ if (matchesKey(data, "up"))
2803
2898
  selectedSetting = Math.max(0, selectedSetting - 1);
2804
- editing = false;
2805
- } else if (matchesKey(data, "down")) {
2899
+ else if (matchesKey(data, "down"))
2806
2900
  selectedSetting = Math.min(1, selectedSetting + 1);
2807
- editing = false;
2808
- } else if (selectedSetting === 0 && /^[0-9]$/.test(data)) {
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
- saving = true;
2847
- save.then(() => {
2848
- dirtySettings.delete(setting);
2849
- const loadedMaxSubagents = loadMaxSubagentsSettings(ctx.cwd, projectTrusted);
2850
- const loadedSandbox = sandboxCallbacks?.load(ctx.cwd, projectTrusted) ?? {
2851
- global: true
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.21",
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.21",
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"