mirror of
https://github.com/grp06/openclaw-studio.git
synced 2026-08-14 08:52:03 +00:00
Merge codex/approvals-tab-tooltip-fix into big-one
This commit is contained in:
@@ -963,6 +963,7 @@ const AgentChatComposer = memo(function AgentChatComposer({
|
||||
onChange={(event) => {
|
||||
const nextValue = event.target.value.trim();
|
||||
onModelChange(nextValue ? nextValue : null);
|
||||
event.currentTarget.blur();
|
||||
}}
|
||||
>
|
||||
{modelOptions.length === 0 ? (
|
||||
|
||||
@@ -22,7 +22,7 @@ type FleetSidebarProps = {
|
||||
const FILTER_OPTIONS: Array<{ value: FocusFilter; label: string; testId: string }> = [
|
||||
{ value: "all", label: "All", testId: "fleet-filter-all" },
|
||||
{ value: "running", label: "Running", testId: "fleet-filter-running" },
|
||||
{ value: "idle", label: "Idle", testId: "fleet-filter-idle" },
|
||||
{ value: "approvals", label: "Approvals", testId: "fleet-filter-approvals" },
|
||||
];
|
||||
|
||||
export const FleetSidebar = ({
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
} from "@/features/agents/state/transcript";
|
||||
|
||||
export type AgentStatus = "idle" | "running" | "error";
|
||||
export type FocusFilter = "all" | "running" | "idle";
|
||||
export type FocusFilter = "all" | "running" | "approvals";
|
||||
|
||||
export type AgentStoreSeed = {
|
||||
agentId: string;
|
||||
@@ -526,8 +526,8 @@ export const getFilteredAgents = (state: AgentStoreState, filter: FocusFilter):
|
||||
return sortAgents(state.agents, true);
|
||||
case "running":
|
||||
return sortAgents(state.agents.filter((agent) => agent.status === "running"), false);
|
||||
case "idle":
|
||||
return sortAgents(state.agents.filter((agent) => agent.status === "idle"), false);
|
||||
case "approvals":
|
||||
return sortAgents(state.agents.filter((agent) => agent.awaitingUserInput), false);
|
||||
default: {
|
||||
const _exhaustive: never = filter;
|
||||
void _exhaustive;
|
||||
|
||||
@@ -3,7 +3,7 @@ export type StudioGatewaySettings = {
|
||||
token: string;
|
||||
};
|
||||
|
||||
export type FocusFilter = "all" | "running" | "idle";
|
||||
export type FocusFilter = "all" | "running" | "approvals";
|
||||
export type StudioViewMode = "focused";
|
||||
|
||||
export type StudioFocusedPreference = {
|
||||
@@ -66,10 +66,11 @@ const normalizeFocusFilter = (
|
||||
): FocusFilter => {
|
||||
const filter = coerceString(value);
|
||||
if (filter === "needs-attention") return "all";
|
||||
if (filter === "idle") return "approvals";
|
||||
if (
|
||||
filter === "all" ||
|
||||
filter === "running" ||
|
||||
filter === "idle"
|
||||
filter === "approvals"
|
||||
) {
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ describe("AgentChatPanel controls", () => {
|
||||
expect(runningBadge).toBeNull();
|
||||
});
|
||||
|
||||
it("invokes_on_model_change_when_model_select_changes", () => {
|
||||
it("invokes_on_model_change_when_model_select_changes_and_blurs_select", () => {
|
||||
const onModelChange = vi.fn();
|
||||
render(
|
||||
createElement(AgentChatPanel, {
|
||||
@@ -242,10 +242,15 @@ describe("AgentChatPanel controls", () => {
|
||||
})
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText("Model"), {
|
||||
const modelSelect = screen.getByLabelText("Model") as HTMLSelectElement;
|
||||
modelSelect.focus();
|
||||
expect(modelSelect).toHaveFocus();
|
||||
|
||||
fireEvent.change(modelSelect, {
|
||||
target: { value: "openai/gpt-5-mini" },
|
||||
});
|
||||
expect(onModelChange).toHaveBeenCalledWith("openai/gpt-5-mini");
|
||||
expect(modelSelect).not.toHaveFocus();
|
||||
});
|
||||
|
||||
it("invokes_on_thinking_change_when_thinking_select_changes", () => {
|
||||
|
||||
@@ -261,7 +261,7 @@ describe("agent store", () => {
|
||||
expect(cleared?.hasUnseenActivity).toBe(false);
|
||||
});
|
||||
|
||||
it("filters_agents_by_status", () => {
|
||||
it("filters_agents_by_status_and_approvals", () => {
|
||||
const seeds: AgentStoreSeed[] = [
|
||||
{
|
||||
agentId: "agent-1",
|
||||
@@ -286,7 +286,7 @@ describe("agent store", () => {
|
||||
state = agentStoreReducer(state, {
|
||||
type: "updateAgent",
|
||||
agentId: "agent-1",
|
||||
patch: { status: "idle" },
|
||||
patch: { status: "idle", awaitingUserInput: true },
|
||||
});
|
||||
state = agentStoreReducer(state, {
|
||||
type: "updateAgent",
|
||||
@@ -307,7 +307,7 @@ describe("agent store", () => {
|
||||
expect(getFilteredAgents(state, "running").map((agent) => agent.agentId)).toEqual([
|
||||
"agent-2",
|
||||
]);
|
||||
expect(getFilteredAgents(state, "idle").map((agent) => agent.agentId)).toEqual([
|
||||
expect(getFilteredAgents(state, "approvals").map((agent) => agent.agentId)).toEqual([
|
||||
"agent-1",
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -93,6 +93,22 @@ describe("FleetSidebar new agent action", () => {
|
||||
expect(screen.getByTestId("fleet-new-agent-button")).toBeDisabled();
|
||||
});
|
||||
|
||||
it("shows approvals tab instead of idle tab", () => {
|
||||
render(
|
||||
createElement(FleetSidebar, {
|
||||
agents: [createAgent()],
|
||||
selectedAgentId: "agent-1",
|
||||
filter: "all",
|
||||
onFilterChange: vi.fn(),
|
||||
onSelectAgent: vi.fn(),
|
||||
onCreateAgent: vi.fn(),
|
||||
})
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("fleet-filter-approvals")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("fleet-filter-idle")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows needs approval badge for awaiting agents", () => {
|
||||
render(
|
||||
createElement(FleetSidebar, {
|
||||
|
||||
@@ -238,7 +238,7 @@ describe("studioBootstrapOperation", () => {
|
||||
commands: [
|
||||
{ kind: "set-focused-preferences-loaded", value: false },
|
||||
{ kind: "set-preferred-selected-agent-id", agentId: "agent-1" },
|
||||
{ kind: "set-focus-filter", filter: "idle" },
|
||||
{ kind: "set-focus-filter", filter: "approvals" },
|
||||
{ kind: "log-error", message: "failed", error: new Error("boom") },
|
||||
],
|
||||
setFocusedPreferencesLoaded,
|
||||
@@ -249,7 +249,7 @@ describe("studioBootstrapOperation", () => {
|
||||
|
||||
expect(setFocusedPreferencesLoaded).toHaveBeenCalledWith(false);
|
||||
expect(setPreferredSelectedAgentId).toHaveBeenCalledWith("agent-1");
|
||||
expect(setFocusFilter).toHaveBeenCalledWith("idle");
|
||||
expect(setFocusFilter).toHaveBeenCalledWith("approvals");
|
||||
expect(logError).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ describe("studioBootstrapWorkflow", () => {
|
||||
"https://gateway.test": {
|
||||
mode: "focused",
|
||||
selectedAgentId: "agent-3",
|
||||
filter: "idle",
|
||||
filter: "approvals",
|
||||
},
|
||||
},
|
||||
avatars: {},
|
||||
@@ -164,7 +164,7 @@ describe("studioBootstrapWorkflow", () => {
|
||||
})
|
||||
).toEqual({
|
||||
preferredSelectedAgentId: "agent-3",
|
||||
focusFilter: "idle",
|
||||
focusFilter: "approvals",
|
||||
});
|
||||
|
||||
expect(
|
||||
|
||||
@@ -59,6 +59,24 @@ describe("studio settings normalization", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes_legacy_idle_filter_to_approvals", () => {
|
||||
const normalized = normalizeStudioSettings({
|
||||
focused: {
|
||||
"ws://localhost:18789": {
|
||||
mode: "focused",
|
||||
selectedAgentId: "agent-1",
|
||||
filter: "idle",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(normalized.focused["ws://localhost:18789"]).toEqual({
|
||||
mode: "focused",
|
||||
selectedAgentId: "agent-1",
|
||||
filter: "approvals",
|
||||
});
|
||||
});
|
||||
|
||||
it("merges_dual_mode_preferences", () => {
|
||||
const current = normalizeStudioSettings({
|
||||
focused: {
|
||||
@@ -73,7 +91,7 @@ describe("studio settings normalization", () => {
|
||||
const merged = mergeStudioSettings(current, {
|
||||
focused: {
|
||||
"ws://localhost:18789": {
|
||||
filter: "idle",
|
||||
filter: "approvals",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -81,7 +99,7 @@ describe("studio settings normalization", () => {
|
||||
expect(merged.focused["ws://localhost:18789"]).toEqual({
|
||||
mode: "focused",
|
||||
selectedAgentId: "main",
|
||||
filter: "idle",
|
||||
filter: "approvals",
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ describe("StudioSettingsCoordinator", () => {
|
||||
focused: {
|
||||
"ws://localhost:18789": {
|
||||
mode: "focused",
|
||||
filter: "idle",
|
||||
filter: "approvals",
|
||||
selectedAgentId: null,
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user