refactor(web): move Configuration Chat Agent to utility agents page (#809)

This commit is contained in:
Carlos Florêncio
2026-05-04 07:47:35 +01:00
committed by GitHub
parent 7ce2e24150
commit d4f6d89e3f
4 changed files with 108 additions and 73 deletions
+1 -72
View File
@@ -14,11 +14,8 @@ import {
import { Badge } from "@kandev/ui/badge";
import { Button } from "@kandev/ui/button";
import { Card, CardContent } from "@kandev/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@kandev/ui/select";
import { Separator } from "@kandev/ui/separator";
import { useAppStore, useAppStoreApi } from "@/components/state-provider";
import { useToast } from "@/components/toast-provider";
import { updateWorkspaceAction } from "@/app/actions/workspaces";
import { useAppStore } from "@/components/state-provider";
import {
createCustomTUIAgent,
listAgentDiscovery,
@@ -372,72 +369,6 @@ function AgentProfilesSection({ savedAgents }: AgentProfilesSectionProps) {
);
}
function ConfigChatAgentSection() {
const workspace = useAppStore(
(s) => s.workspaces.items.find((w) => w.id === s.workspaces.activeId) ?? null,
);
const profiles = useAppStore((s) => s.agentProfiles.items ?? []);
const currentProfileId = workspace?.default_config_agent_profile_id ?? "";
const [saving, setSaving] = useState(false);
const { toast } = useToast();
const storeApi = useAppStoreApi();
const handleChange = async (value: string) => {
const effectiveValue = value === "none" ? "" : value;
if (!workspace) return;
setSaving(true);
try {
await updateWorkspaceAction(workspace.id, {
default_config_agent_profile_id: effectiveValue,
});
const { workspaces, setWorkspaces } = storeApi.getState();
setWorkspaces(
workspaces.items.map((w) =>
w.id === workspace.id ? { ...w, default_config_agent_profile_id: effectiveValue } : w,
),
);
toast({ title: "Configuration agent updated", variant: "success" });
} catch (error) {
toast({
title: "Failed to update",
description: error instanceof Error ? error.message : "Unknown error",
variant: "error",
});
} finally {
setSaving(false);
}
};
if (!workspace) return null;
return (
<div className="space-y-4">
<Separator />
<div>
<h3 className="text-lg font-semibold">Configuration Chat Agent</h3>
<p className="text-sm text-muted-foreground">
Choose which agent profile to use for the Configuration Chat. This agent can manage your
workflows, agent profiles, and MCP configuration.
</p>
</div>
<Select value={currentProfileId || "none"} onValueChange={handleChange} disabled={saving}>
<SelectTrigger className="w-full max-w-sm cursor-pointer">
<SelectValue placeholder="Choose an agent profile..." />
</SelectTrigger>
<SelectContent>
<SelectItem value="none">No default</SelectItem>
{profiles.map((p) => (
<SelectItem key={p.id} value={p.id} className="cursor-pointer">
{p.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
);
}
function useAgentPageState() {
const { items: discoveryAgents, loading: discoveryLoading } = useAgentDiscovery();
const savedAgents = useAppStore((state) => state.settingsAgents.items);
@@ -563,8 +494,6 @@ export default function AgentsSettingsPage() {
<AgentProfilesSection savedAgents={savedAgents} />
<ConfigChatAgentSection />
<AddTUIAgentDialog
open={tuiDialogOpen}
onOpenChange={setTuiDialogOpen}
@@ -1,5 +1,11 @@
import { ConfigChatAgentSection } from "@/components/settings/config-chat-agent-section";
import { UtilityAgentsSection } from "@/components/settings/utility-agents-section";
export default function UtilityAgentsSettingsPage() {
return <UtilityAgentsSection />;
return (
<div className="space-y-8">
<UtilityAgentsSection />
<ConfigChatAgentSection />
</div>
);
}
@@ -0,0 +1,74 @@
"use client";
import { useState } from "react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@kandev/ui/select";
import { Separator } from "@kandev/ui/separator";
import { useAppStore, useAppStoreApi } from "@/components/state-provider";
import { useToast } from "@/components/toast-provider";
import { updateWorkspaceAction } from "@/app/actions/workspaces";
export function ConfigChatAgentSection() {
const workspace = useAppStore(
(s) => s.workspaces.items.find((w) => w.id === s.workspaces.activeId) ?? null,
);
const profiles = useAppStore((s) => s.agentProfiles.items ?? []);
const currentProfileId = workspace?.default_config_agent_profile_id ?? "";
const [saving, setSaving] = useState(false);
const { toast } = useToast();
const storeApi = useAppStoreApi();
const handleChange = async (value: string) => {
const effectiveValue = value === "none" ? "" : value;
if (!workspace) return;
setSaving(true);
try {
await updateWorkspaceAction(workspace.id, {
default_config_agent_profile_id: effectiveValue,
});
const { workspaces, setWorkspaces } = storeApi.getState();
setWorkspaces(
workspaces.items.map((w) =>
w.id === workspace.id ? { ...w, default_config_agent_profile_id: effectiveValue } : w,
),
);
toast({ title: "Configuration agent updated", variant: "success" });
} catch (error) {
toast({
title: "Failed to update",
description: error instanceof Error ? error.message : "Unknown error",
variant: "error",
});
} finally {
setSaving(false);
}
};
if (!workspace) return null;
return (
<div className="space-y-4">
<Separator />
<div>
<h3 className="text-lg font-semibold">Configuration Chat Agent</h3>
<p className="text-sm text-muted-foreground">
Choose which agent profile to use for the Configuration Chat. This agent can manage your
workflows, agent profiles, and MCP configuration.
</p>
</div>
<Select value={currentProfileId || "none"} onValueChange={handleChange} disabled={saving}>
<SelectTrigger className="w-full max-w-sm cursor-pointer">
<SelectValue placeholder="Choose an agent profile..." />
</SelectTrigger>
<SelectContent>
<SelectItem value="none">No default</SelectItem>
{profiles.map((p) => (
<SelectItem key={p.id} value={p.id} className="cursor-pointer">
{p.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
);
}
@@ -192,4 +192,30 @@ test.describe("Utility Agents settings page", () => {
[],
);
});
test("Configuration Chat Agent section lives here, not on the agents page", async ({
testPage,
}) => {
// Regression guard for the move from /settings/agents to /settings/utility-agents.
await testPage.goto("/settings/utility-agents");
await expect(
testPage.getByRole("heading", { name: "Utility Agents", exact: true }),
).toBeVisible({ timeout: 15_000 });
await expect(
testPage.getByRole("heading", { name: "Configuration Chat Agent", exact: true }),
).toBeVisible();
await expect(
testPage.getByText(
"Choose which agent profile to use for the Configuration Chat. This agent can manage your workflows, agent profiles, and MCP configuration.",
),
).toBeVisible();
await testPage.goto("/settings/agents");
await expect(testPage.getByRole("heading", { name: "Agents", exact: true })).toBeVisible({
timeout: 15_000,
});
await expect(
testPage.getByRole("heading", { name: "Configuration Chat Agent", exact: true }),
).toHaveCount(0);
});
});