refactor(web): move Configuration Chat Agent to utility agents page (#809)
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user