θΏ™ζ˜―indexlocζδΎ›ηš„ζœεŠ‘οΌŒδΈθ¦θΎ“ε…₯任何密码
Skip to content

Agent skills UI/UX improvements #3924

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 50 additions & 23 deletions frontend/src/pages/Admin/Agents/AgentFlows/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { CaretRight } from "@phosphor-icons/react";

export default function AgentFlowsList({
flows = [],
selectedFlow,
handleClick,
selectedFlow = null,
handleClick = null,
activeFlowIds = [],
toggleFlow = () => {},
}) {
if (flows.length === 0) {
return (
Expand All @@ -13,6 +15,7 @@ export default function AgentFlowsList({
<a
href="https://docs.anythingllm.com/agent-flows/getting-started"
target="_blank"
rel="noreferrer"
className="text-theme-text-secondary underline hover:text-cta-button"
>
Learn more about Agent Flows.
Expand All @@ -23,32 +26,56 @@ export default function AgentFlowsList({

return (
<div className="bg-theme-bg-secondary text-white rounded-xl w-full md:min-w-[360px]">
{flows.map((flow, index) => (
{flows.map((flow) => (
<div
key={flow.uuid}
className={`py-3 px-4 flex items-center justify-between ${
index === 0 ? "rounded-t-xl" : ""
} ${
index === flows.length - 1
? "rounded-b-xl"
: "border-b border-white/10"
} cursor-pointer transition-all duration-300 hover:bg-theme-bg-primary ${
selectedFlow?.uuid === flow.uuid
? "bg-white/10 light:bg-theme-bg-sidebar"
: ""
}`}
onClick={() => handleClick?.(flow)}
className={`
relative
cursor-pointer
transition-all duration-300
after:content-['']
after:absolute
after:bottom-0
after:left-4
after:right-4
after:h-[1px]
after:bg-theme-action-menu-bg
last:after:hidden
first:rounded-t-xl
last:rounded-b-xl
${selectedFlow?.uuid === flow.uuid ? "bg-white/10 light:bg-theme-bg-sidebar" : "hover:bg-theme-bg-primary"}
`}
>
<div className="text-sm font-light">{flow.name}</div>
<div className="flex items-center gap-x-2">
<div className="text-sm text-theme-text-secondary font-medium">
{flow.active ? "On" : "Off"}
<div className="flex items-center justify-between h-[36px] px-4">
<div className="text-sm font-medium">{flow.name}</div>
<div className="flex items-center gap-x-2">
<div
onClick={(e) => {
e.stopPropagation();
toggleFlow(flow.uuid);
}}
className="relative inline-flex h-4 w-7 items-center rounded-full transition-colors duration-300"
style={{
backgroundColor: activeFlowIds.includes(flow.uuid)
? "#32D583"
: "#CFCFD0",
}}
>
<span
className={`inline-block h-3 w-3 transform rounded-full bg-white transition-transform duration-300 ${
activeFlowIds.includes(flow.uuid)
? "translate-x-[14px]"
: "translate-x-[2px]"
}`}
/>
</div>
<CaretRight
size={14}
weight="bold"
className="text-theme-text-secondary"
/>
</div>
<CaretRight
size={14}
weight="bold"
className="text-theme-text-secondary"
/>
</div>
</div>
))}
Expand Down
68 changes: 46 additions & 22 deletions frontend/src/pages/Admin/Agents/Imported/SkillList/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default function ImportedSkillList({
skills = [],
selectedSkill = null,
handleClick = null,
toggleSkill = () => {},
}) {
if (skills.length === 0)
return (
Expand All @@ -15,6 +16,7 @@ export default function ImportedSkillList({
<a
href="https://docs.anythingllm.com/agent/custom/developer-guide"
target="_blank"
rel="noreferrer"
className="text-theme-text-secondary underline hover:text-cta-button"
>
AnythingLLM Agent Docs
Expand All @@ -25,33 +27,55 @@ export default function ImportedSkillList({
);

return (
<div
className={`bg-theme-bg-secondary text-white rounded-xl w-full md:min-w-[360px]`}
>
{skills.map((config, index) => (
<div className="bg-theme-bg-secondary text-white rounded-xl w-full md:min-w-[360px]">
{skills.map((config) => (
<div
key={config.hubId}
className={`py-3 px-4 flex items-center justify-between ${
index === 0 ? "rounded-t-xl" : ""
} ${
index === Object.keys(skills).length - 1
? "rounded-b-xl"
: "border-b border-white/10"
} cursor-pointer transition-all duration-300 hover:bg-theme-bg-primary ${
selectedSkill === config.hubId ? "bg-theme-bg-primary" : ""
}`}
onClick={() => handleClick?.({ ...config, imported: true })}
className={`
relative
cursor-pointer
transition-all duration-300
after:content-['']
after:absolute
after:bottom-0
after:left-4
after:right-4
after:h-[1px]
after:bg-theme-action-menu-bg
last:after:hidden
first:rounded-t-xl
last:rounded-b-xl
${selectedSkill?.hubId === config.hubId ? "bg-white/10 light:bg-theme-bg-sidebar" : "hover:bg-theme-bg-primary"}
`}
>
<div className="text-sm font-light">{sentenceCase(config.name)}</div>
<div className="flex items-center gap-x-2">
<div className="text-sm text-theme-text-secondary font-medium">
{config.active ? "On" : "Off"}
<div className="flex items-center justify-between h-[36px] px-4">
<div className="text-sm font-medium">
{sentenceCase(config.name)}
</div>
<div className="flex items-center gap-x-2">
<div
onClick={(e) => {
e.stopPropagation();
toggleSkill(config);
}}
className="relative inline-flex h-4 w-7 items-center rounded-full transition-colors duration-300"
style={{
backgroundColor: config.active ? "#32D583" : "#CFCFD0",
}}
>
<span
className={`inline-block h-3 w-3 transform rounded-full bg-white transition-transform duration-300 ${
config.active ? "translate-x-[14px]" : "translate-x-[2px]"
}`}
/>
</div>
<CaretRight
size={14}
weight="bold"
className="text-theme-text-secondary"
/>
</div>
<CaretRight
size={14}
weight="bold"
className="text-theme-text-secondary"
/>
</div>
</div>
))}
Expand Down
107 changes: 62 additions & 45 deletions frontend/src/pages/Admin/Agents/MCPServers/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useState, useEffect } from "react";
import { titleCase } from "text-case";
import { BookOpenText, ArrowClockwise } from "@phosphor-icons/react";
import {
BookOpenText,
ArrowsClockwise,
CaretRight,
} from "@phosphor-icons/react";
import MCPLogo from "@/media/agents/mcp-logo.svg";
import MCPServers from "@/models/mcpServers";
import showToast from "@/utils/toast";
Expand Down Expand Up @@ -48,31 +52,28 @@ export function MCPServerHeader({
<>
<div className="text-theme-text-primary flex items-center justify-between gap-x-2 mt-4">
<div className="flex items-center gap-x-2">
<img src={MCPLogo} className="w-6 h-6 light:invert" alt="MCP Logo" />
<p className="text-lg font-medium">MCP Servers</p>
<img src={MCPLogo} className="w-5 h-5 light:invert" alt="MCP Logo" />
<p className="text-sm font-semibold">MCP Servers</p>
</div>
<div className="flex items-center gap-x-3">
<a
href="https://docs.anythingllm.com/mcp-compatibility/overview"
target="_blank"
rel="noopener noreferrer"
className="border-none text-theme-text-secondary hover:text-cta-button"
className="border-none text-cta-button hover:text-theme-text-secondary"
>
<BookOpenText size={16} />
<BookOpenText size={16} weight="bold" />
</a>
<button
type="button"
onClick={refreshMCPServers}
disabled={loadingMcpServers}
className="border-none text-theme-text-secondary hover:text-cta-button flex items-center gap-x-1"
className="border-none text-cta-button hover:text-theme-text-secondary flex items-center gap-x-1"
>
<ArrowClockwise
<ArrowsClockwise
size={16}
className={loadingMcpServers ? "animate-spin" : ""}
/>
<p className="text-sm">
{loadingMcpServers ? "Loading..." : "Refresh"}
</p>
</button>
</div>
</div>
Expand All @@ -82,23 +83,16 @@ export function MCPServerHeader({
}

export function MCPServersList({
isLoading = false,
servers = [],
selectedServer,
handleClick,
selectedServer = null,
handleClick = null,
toggleServer = () => {},
isLoading = false,
}) {
if (isLoading) {
return (
<div className="text-theme-text-secondary text-center text-xs flex flex-col gap-y-2">
<p>Loading MCP Servers from configuration file...</p>
<a
href="https://docs.anythingllm.com/mcp-compatibility/overview"
target="_blank"
rel="noopener noreferrer"
className="text-theme-text-secondary underline hover:text-cta-button"
>
Learn more about MCP Servers.
</a>
<p>Loading MCP servers...</p>
</div>
);
}
Expand All @@ -108,43 +102,66 @@ export function MCPServersList({
<div className="text-theme-text-secondary text-center text-xs flex flex-col gap-y-2">
<p>No MCP servers found</p>
<a
href="https://docs.anythingllm.com/mcp-compatibility/overview"
href="https://docs.anythingllm.com/mcp/getting-started"
target="_blank"
rel="noopener noreferrer"
rel="noreferrer"
className="text-theme-text-secondary underline hover:text-cta-button"
>
Learn more about MCP Servers.
Learn more about MCP.
</a>
</div>
);
}

return (
<div className="bg-theme-bg-secondary text-white rounded-xl w-full md:min-w-[360px]">
{servers.map((server, index) => (
{servers.map((server) => (
<div
key={server.name}
className={`py-3 px-4 flex items-center justify-between ${
index === 0 ? "rounded-t-xl" : ""
} ${
index === servers.length - 1
? "rounded-b-xl"
: "border-b border-white/10"
} cursor-pointer transition-all duration-300 hover:bg-theme-bg-primary ${
selectedServer?.name === server.name
? "bg-white/10 light:bg-theme-bg-sidebar"
: ""
}`}
onClick={() => handleClick?.(server)}
className={`
relative
cursor-pointer
transition-all duration-300
after:content-['']
after:absolute
after:bottom-0
after:left-4
after:right-4
after:h-[1px]
after:bg-theme-action-menu-bg
last:after:hidden
first:rounded-t-xl
last:rounded-b-xl
${selectedServer?.name === server.name ? "bg-white/10 light:bg-theme-bg-sidebar" : "hover:bg-theme-bg-primary"}
`}
>
<div className="text-sm font-light">
{titleCase(server.name.replace(/[_-]/g, " "))}
</div>
<div className="flex items-center gap-x-2">
<div
className={`text-sm text-theme-text-secondary font-medium ${server.running ? "text-green-500" : "text-red-500"}`}
>
{server.running ? "On" : "Stopped"}
<div className="flex items-center justify-between h-[36px] px-4">
<div className="text-sm font-medium">
{titleCase(server.name.replace(/[_-]/g, " "))}
</div>
<div className="flex items-center gap-x-2">
<div
onClick={(e) => {
e.stopPropagation();
toggleServer(server.name);
}}
className="relative inline-flex h-4 w-7 items-center rounded-full transition-colors duration-300"
style={{
backgroundColor: server.running ? "#32D583" : "#CFCFD0",
}}
>
<span
className={`inline-block h-3 w-3 transform rounded-full bg-white transition-transform duration-300 ${
server.running ? "translate-x-[14px]" : "translate-x-[2px]"
}`}
/>
</div>
<CaretRight
size={14}
weight="bold"
className="text-theme-text-secondary"
/>
</div>
</div>
</div>
Expand Down
Loading