pi-landstrip 0.18.17 → 0.18.18

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 +43 -33
  2. package/package.json +2 -2
package/dist/index.ts CHANGED
@@ -1604,12 +1604,12 @@ var INSPECTOR_BODY_LINES = 16;
1604
1604
  var PI_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
1605
1605
  var AGENTS_HELP_ROWS = [
1606
1606
  ["Tab", "Next tab"],
1607
- ["Shift+Tab / S", "Switch scope in Agents or Settings"],
1607
+ ["Shift+Tab / S", "Switch scope in Primary, Subagent, or Settings"],
1608
1608
  ["↑ / ↓", "Select item or scroll when follow is off"],
1609
1609
  ["F", "Toggle task log follow"],
1610
1610
  ["Page Up / Down", "Scroll task output by page"],
1611
1611
  ["Home / End", "Jump to task output boundary"],
1612
- ["Enter", "Open logs, set primary, or save"],
1612
+ ["Enter", "Open log, set primary, or save"],
1613
1613
  ["Esc", "Back or close"],
1614
1614
  ["Ctrl+C", "Close"],
1615
1615
  ["Space", "Enable agent or toggle sandbox"],
@@ -2397,8 +2397,9 @@ ${this.primaryAgent.prompt}` };
2397
2397
  let maxSubagentsSettings = loadMaxSubagentsSettings(ctx.cwd, projectTrusted);
2398
2398
  const sandboxCallbacks = this.integration.sandboxCallbacks;
2399
2399
  let sandboxSettings = sandboxCallbacks?.load(ctx.cwd, projectTrusted) ?? { global: true };
2400
- let tab = requested ? "logs" : "agents";
2401
- let selectedAgent = Math.max(0, agents.findIndex((agent) => agent.name === this.primaryAgent?.name));
2400
+ let tab = requested ? "log" : "primary";
2401
+ const agentsForTab = () => agents.filter((agent) => agentSupportsMode(agent, tab === "subagent" ? "subagent" : "primary"));
2402
+ let selectedAgent = Math.max(0, agentsForTab().findIndex((agent) => agent.name === this.primaryAgent?.name));
2402
2403
  let selectedTask = requested ? tasks.findIndex((task) => task.id === requested || task.id.startsWith(requested)) : 0;
2403
2404
  if (selectedTask < 0) {
2404
2405
  ctx.ui.notify(`Unknown task session: ${requested}`, "error");
@@ -2412,13 +2413,14 @@ ${this.primaryAgent.prompt}` };
2412
2413
  let follow = requested.length > 0;
2413
2414
  let scroll = 0;
2414
2415
  const reloadAgents = () => {
2415
- const selectedName = agents[selectedAgent]?.name;
2416
+ const selectedName = agentsForTab()[selectedAgent]?.name;
2416
2417
  catalog = this.getAgentCatalog(ctx);
2417
2418
  globalCatalog = this.loadCatalog(ctx.cwd, getAgentDir4(), false);
2418
2419
  agents = [...catalog.agents.values()].filter((agent) => !agent.hidden).sort((left, right) => left.name.localeCompare(right.name));
2419
2420
  disabledOverrides = loadAgentDisabledOverrides(ctx.cwd, projectTrusted);
2420
- const nextSelected = selectedName ? agents.findIndex((agent) => agent.name === selectedName) : selectedAgent;
2421
- selectedAgent = Math.max(0, Math.min(nextSelected < 0 ? 0 : nextSelected, agents.length - 1));
2421
+ const listedAgents = agentsForTab();
2422
+ const nextSelected = selectedName ? listedAgents.findIndex((agent) => agent.name === selectedName) : selectedAgent;
2423
+ selectedAgent = Math.max(0, Math.min(nextSelected < 0 ? 0 : nextSelected, listedAgents.length - 1));
2422
2424
  };
2423
2425
  const reloadSettings = () => {
2424
2426
  maxSubagentsSettings = loadMaxSubagentsSettings(ctx.cwd, projectTrusted);
@@ -2462,27 +2464,25 @@ ${this.primaryAgent.prompt}` };
2462
2464
  return `${clipped}${" ".repeat(Math.max(0, cellWidth - visibleWidth2(clipped)))}`;
2463
2465
  };
2464
2466
  refreshTasks();
2465
- const tabs = `${dialogTabs(theme, ["Agents", "Tasks", "Logs", "Settings", "Help"], `${tab[0]?.toUpperCase()}${tab.slice(1)}`)}${tab === "tasks" || tab === "logs" ? "" : theme.fg("dim", ` · Scope: ${scope === "project" ? "Project" : "Global"}`)}`;
2466
- if (tab === "agents") {
2467
- const start = Math.max(0, Math.min(selectedAgent - 3, agents.length - 7));
2468
- const shown2 = agents.slice(start, start + 7);
2469
- const nameWidth = Math.min(20, Math.max(5, ...agents.map((agent2) => visibleWidth2(`@${agent2.name}`))));
2470
- const primaryWidth = 7;
2471
- const modeWidth = 8;
2467
+ const tabs = `${dialogTabs(theme, ["Primary", "Subagent", "Tasks", "Log", "Settings", "Help"], `${tab[0]?.toUpperCase()}${tab.slice(1)}`)}${tab === "tasks" || tab === "log" ? "" : theme.fg("dim", ` · Scope: ${scope === "project" ? "Project" : "Global"}`)}`;
2468
+ if (tab === "primary" || tab === "subagent") {
2469
+ const listedAgents = agentsForTab();
2470
+ const start = Math.max(0, Math.min(selectedAgent - 3, listedAgents.length - 7));
2471
+ const shown2 = listedAgents.slice(start, start + 7);
2472
+ const nameWidth = Math.min(20, Math.max(5, ...listedAgents.map((agent2) => visibleWidth2(`@${agent2.name}`))));
2472
2473
  const sourceWidth = 8;
2473
2474
  const stateWidth = 13;
2474
- const fixedWidth = 2 + primaryWidth + 1 + nameWidth + 1 + modeWidth + 1 + sourceWidth + 1 + stateWidth;
2475
+ const fixedWidth = 2 + nameWidth + 1 + sourceWidth + 1 + stateWidth;
2475
2476
  const modelWidth = Math.max(10, Math.min(30, contentWidth - fixedWidth - 1));
2476
2477
  const lines2 = [
2477
2478
  tabs,
2478
2479
  "",
2479
- theme.fg("dim", ` ${pad("Primary", primaryWidth)} ${pad("Agent", nameWidth)} ${pad("Mode", modeWidth)} ${pad("Source", sourceWidth)} ${pad("Model", modelWidth)} ${pad("State", stateWidth)}`)
2480
+ theme.fg("dim", ` ${pad("Agent", nameWidth)} ${pad("Source", sourceWidth)} ${pad("Model", modelWidth)} ${pad("State", stateWidth)}`)
2480
2481
  ];
2481
2482
  for (const [offset, agent2] of shown2.entries()) {
2482
2483
  const index = start + offset;
2483
2484
  const selected = index === selectedAgent;
2484
2485
  const cursor = selected ? theme.fg("accent", "›") : " ";
2485
- const primary = agent2.name === this.primaryAgent?.name ? "yes" : "";
2486
2486
  const current = scopedAgent(agent2);
2487
2487
  const unavailable = current === undefined;
2488
2488
  const scopedDisabled = current?.disabled ?? false;
@@ -2493,11 +2493,13 @@ ${this.primaryAgent.prompt}` };
2493
2493
  const color = deleting ? "error" : disabled ? "muted" : "text";
2494
2494
  const plainName = pad(`@${agent2.name}`, nameWidth);
2495
2495
  const name = deleting ? theme.fg("error", plainName) : disabled ? theme.fg("muted", plainName) : colorizeAgentText(agent2.color, plainName, (agentColor, text) => theme.fg(agentColor, text));
2496
- lines2.push(`${cursor} ${theme.fg(primary ? "success" : "dim", pad(primary, primaryWidth))} ${name} ${theme.fg(color, pad(agent2.mode, modeWidth))} ${theme.fg(color, pad(agent2.source, sourceWidth))} ${theme.fg(color, pad(agent2.model ?? "current model", modelWidth))} ${theme.fg(deleting ? "error" : unavailable ? "muted" : scopedDisabled ? "warning" : color, pad(state, stateWidth))}`);
2496
+ const line = `${cursor} ${name} ${theme.fg(color, pad(agent2.source, sourceWidth))} ${theme.fg(color, pad(agent2.model ?? "current model", modelWidth))} ${theme.fg(deleting ? "error" : unavailable ? "muted" : scopedDisabled ? "warning" : color, pad(state, stateWidth))}`;
2497
+ lines2.push(agent2.name === this.primaryAgent?.name ? theme.bold(line) : line);
2497
2498
  }
2498
- if (agents.length === 0)
2499
- lines2.push(theme.fg("muted", " No agents configured."));
2500
- const agent = agents[selectedAgent];
2499
+ if (listedAgents.length === 0) {
2500
+ lines2.push(theme.fg("muted", ` No ${tab} agents configured.`));
2501
+ }
2502
+ const agent = listedAgents[selectedAgent];
2501
2503
  if (agent) {
2502
2504
  lines2.push("", theme.fg(agent.disabled ? "muted" : "text", agent.description ?? "No description"));
2503
2505
  const details = [
@@ -2661,7 +2663,7 @@ ${this.primaryAgent.prompt}` };
2661
2663
  }
2662
2664
  return;
2663
2665
  }
2664
- if ((matchesKey(data, "shift+tab") || data.toLowerCase() === "s") && (tab === "agents" || tab === "settings")) {
2666
+ if ((matchesKey(data, "shift+tab") || data.toLowerCase() === "s") && (tab === "primary" || tab === "subagent" || tab === "settings")) {
2665
2667
  if (saving)
2666
2668
  return;
2667
2669
  if (dirtySettings.size > 0) {
@@ -2684,9 +2686,16 @@ ${this.primaryAgent.prompt}` };
2684
2686
  ctx.ui.notify("Save changes with Enter or discard them with R before leaving", "warning");
2685
2687
  return;
2686
2688
  }
2687
- const tabs = ["agents", "tasks", "logs", "settings", "help"];
2688
- tab = tabs[(tabs.indexOf(tab) + 1) % tabs.length] ?? "agents";
2689
- if (tab === "logs" && tasks.length > 0)
2689
+ const selectedName = tab === "primary" || tab === "subagent" ? agentsForTab()[selectedAgent]?.name : undefined;
2690
+ const tabs = ["primary", "subagent", "tasks", "log", "settings", "help"];
2691
+ tab = tabs[(tabs.indexOf(tab) + 1) % tabs.length] ?? "primary";
2692
+ if (tab === "primary" || tab === "subagent") {
2693
+ const listedAgents = agentsForTab();
2694
+ const preferredName = selectedName ?? (tab === "primary" ? this.primaryAgent?.name : undefined);
2695
+ const nextSelected = preferredName ? listedAgents.findIndex((agent) => agent.name === preferredName) : 0;
2696
+ selectedAgent = Math.max(0, Math.min(nextSelected < 0 ? 0 : nextSelected, listedAgents.length - 1));
2697
+ }
2698
+ if (tab === "log" && tasks.length > 0)
2690
2699
  follow = true;
2691
2700
  else
2692
2701
  follow = false;
@@ -2695,16 +2704,17 @@ ${this.primaryAgent.prompt}` };
2695
2704
  tui.requestRender();
2696
2705
  return;
2697
2706
  }
2698
- if (tab === "agents") {
2699
- const agent = agents[selectedAgent];
2707
+ if (tab === "primary" || tab === "subagent") {
2708
+ const listedAgents = agentsForTab();
2709
+ const agent = listedAgents[selectedAgent];
2700
2710
  if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
2701
2711
  done();
2702
2712
  return;
2703
2713
  }
2704
2714
  if (matchesKey(data, "up"))
2705
2715
  selectedAgent = Math.max(0, selectedAgent - 1);
2706
- else if (matchesKey(data, "down") && agents.length > 0) {
2707
- selectedAgent = Math.min(agents.length - 1, selectedAgent + 1);
2716
+ else if (matchesKey(data, "down") && listedAgents.length > 0) {
2717
+ selectedAgent = Math.min(listedAgents.length - 1, selectedAgent + 1);
2708
2718
  } else if (data.toLowerCase() === "x" && agent && !saving) {
2709
2719
  if (!projectTrusted || !canDeleteProjectAgent(ctx.cwd, agent)) {
2710
2720
  ctx.ui.notify("Only project agent files can be deleted here", "warning");
@@ -2760,10 +2770,10 @@ ${this.primaryAgent.prompt}` };
2760
2770
  tui.requestRender();
2761
2771
  });
2762
2772
  return;
2763
- } else if (matchesKey(data, "return") && agent && !agent.disabled && agentSupportsMode(agent, "primary")) {
2773
+ } else if (tab === "primary" && matchesKey(data, "return") && agent && !agent.disabled && agentSupportsMode(agent, "primary")) {
2764
2774
  this.selectPrimaryAgent(agent.name, ctx).then(() => tui.requestRender()).catch((error) => ctx.ui.notify(`Could not select primary agent: ${formatError(error)}`, "error"));
2765
2775
  return;
2766
- } else if (matchesKey(data, "return") && agent) {
2776
+ } else if (tab === "primary" && matchesKey(data, "return") && agent) {
2767
2777
  ctx.ui.notify(agent.disabled ? "Enable this agent before setting it as primary" : "This agent cannot be used as the primary agent", "warning");
2768
2778
  return;
2769
2779
  } else
@@ -2868,7 +2878,7 @@ ${this.primaryAgent.prompt}` };
2868
2878
  else if (matchesKey(data, "down") && tasks.length > 0) {
2869
2879
  selectedTask = Math.min(tasks.length - 1, selectedTask + 1);
2870
2880
  } else if (matchesKey(data, "return") && tasks.length > 0) {
2871
- tab = "logs";
2881
+ tab = "log";
2872
2882
  follow = true;
2873
2883
  scroll = 0;
2874
2884
  } else
@@ -2876,7 +2886,7 @@ ${this.primaryAgent.prompt}` };
2876
2886
  tui.requestRender();
2877
2887
  return;
2878
2888
  }
2879
- if (tab !== "logs")
2889
+ if (tab !== "log")
2880
2890
  return;
2881
2891
  const task = tasks[selectedTask];
2882
2892
  if (!task) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-landstrip",
3
- "version": "0.18.17",
3
+ "version": "0.18.18",
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.17",
42
+ "@landstrip/landstrip": "^0.18.18",
43
43
  "jsonc-parser": "^3.3.1",
44
44
  "minimatch": "^10.2.5",
45
45
  "yaml": "^2.9.0"