feat(app): cycle agent modes with Shift+Tab

This commit is contained in:
Mohamed Boudra
2026-06-24 14:41:14 +07:00
parent 7a817774b7
commit 6fe320055d
20 changed files with 310 additions and 108 deletions
@@ -1,5 +1,14 @@
import { describe, expect, it } from "vitest";
import { resolveAgentControlsMode } from "./mode";
import type { AgentMode } from "@getpaseo/protocol/agent-types";
import { resolveAgentControlsMode, resolveNextAgentModeId } from "./mode";
const PLAN_MODE = { id: "plan", label: "Plan" } satisfies AgentMode;
const MODES = [
PLAN_MODE,
{ id: "build", label: "Build" },
{ id: "full-access", label: "Full Access" },
] satisfies AgentMode[];
describe("resolveAgentControlsMode", () => {
it("uses ready mode when no controlled agent controls are provided", () => {
@@ -29,3 +38,32 @@ describe("resolveAgentControlsMode", () => {
).toBe("draft");
});
});
describe("resolveNextAgentModeId", () => {
it("cycles from the selected mode to the next mode", () => {
expect(resolveNextAgentModeId({ modeOptions: MODES, selectedMode: "build" })).toBe(
"full-access",
);
});
it("wraps from the last mode to the first mode", () => {
expect(resolveNextAgentModeId({ modeOptions: MODES, selectedMode: "full-access" })).toBe(
"plan",
);
});
it("treats an empty selection as the visible first mode", () => {
expect(resolveNextAgentModeId({ modeOptions: MODES, selectedMode: "" })).toBe("build");
});
it("treats a stale selection as the visible first mode", () => {
expect(resolveNextAgentModeId({ modeOptions: MODES, selectedMode: "deleted-mode" })).toBe(
"build",
);
});
it("returns null when there are fewer than two modes", () => {
expect(resolveNextAgentModeId({ modeOptions: [], selectedMode: "" })).toBeNull();
expect(resolveNextAgentModeId({ modeOptions: [PLAN_MODE], selectedMode: "plan" })).toBeNull();
});
});