diff --git a/example/parsar/src/Agents.tsx b/example/parsar/src/Agents.tsx
index f5324c0ae..21b3997ab 100644
--- a/example/parsar/src/Agents.tsx
+++ b/example/parsar/src/Agents.tsx
@@ -1,13 +1,18 @@
import { tr } from "./lib/i18n";
import { useState } from "react";
-import { Plus, Search, Send, Server } from "lucide-react";
+import { Blocks, Plug, Plus, Search, Send, Server } from "lucide-react";
import {
useAgents,
useFeishuBots,
+ useMCPs,
useModels,
useRuntimes,
type AgentProfile,
+ type FeishuBot,
+ type RuntimeProfile,
} from "./lib/product";
+import { useCapabilities } from "./Capabilities";
+import { useSkills } from "./Skills";
import { engineSummary } from "./ExecutionFields";
import { Button } from "./components/ui/button";
import { Input } from "./components/ui/input";
@@ -42,7 +47,12 @@ export function Agents() {
const agents = useAgents(),
models = useModels(),
runtimes = useRuntimes(),
- bots = useFeishuBots();
+ bots = useFeishuBots(),
+ skills = useSkills(),
+ mcps = useMCPs(),
+ capabilities = useCapabilities();
+ const names = (rows: { id: string; name: string }[] = [], ids: string[] = []) =>
+ ids.flatMap((id) => rows.find((row) => row.id === id)?.name || []);
const [search, setSearch] = useState("");
const rows = (agents.data || []).filter((agent) =>
`${agent.name} ${agent.description || ""}`
@@ -93,8 +103,18 @@ export function Agents() {
key={agent.id}
agent={agent}
engine={engineSummary(agent, models.data)}
- runtime={runtimes.data?.find((r) => r.id === agent.runtime_id)?.name}
- bot={bots.data?.find((b) => b.agent_id === agent.id)?.name}
+ runtime={runtimes.data?.find((r) => r.id === agent.runtime_id)}
+ bot={bots.data?.find((b) => b.agent_id === agent.id)}
+ skills={names(skills.data, agent.skill_ids)}
+ capabilities={[
+ ...(agent.web_search && agent.web_search !== "disabled" ? [tr("网页搜索")] : []),
+ ...(agent.ask_user ? [tr("向用户提问")] : []),
+ ...names(mcps.data, agent.mcp_ids),
+ ...names(
+ capabilities.data?.filter((row) => row.kind !== "prompt"),
+ agent.capability_ids,
+ ),
+ ]}
/>
))}
@@ -104,18 +124,46 @@ export function Agents() {
);
}
+// One line of the card: which bot, template, Skills or capabilities the Agent is assembled from.
+function Part({
+ icon: Icon,
+ label,
+ children,
+}: {
+ icon: typeof Server;
+ label: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+ {label}
+
+
{children}
+
+ );
+}
+
+const shownSkills = 8;
+
function AgentCard({
agent,
engine,
runtime,
bot,
+ skills,
+ capabilities,
}: {
agent: AgentProfile;
engine: string;
- runtime?: string;
- bot?: string;
+ runtime?: RuntimeProfile;
+ bot?: FeishuBot;
+ skills: string[];
+ capabilities: string[];
}) {
const disabled = agent.enabled === false;
+ const packages = [...(runtime?.packages?.npm || []), ...(runtime?.packages?.python || [])];
return (
@@ -135,14 +183,55 @@ function AgentCard({
{disabled && {tr("已停用")}}
-
+
{agent.description || agent.instructions || tr("暂无描述")}
-
-
- {runtime || tr("未选择环境")}
-
- {bot &&
{bot}}
+
+
+ {bot ? (
+
+ {bot.name}
+ {bot.health?.state === "connected" && (
+
+ )}
+
+ ) : (
+ {tr("未绑定")}
+ )}
+
+
+ {runtime ? (
+ <>
+ {runtime.name}
+ {packages.map((name) => (
+ {name}
+ ))}
+ >
+ ) : (
+ {tr("未选择环境")}
+ )}
+
+
+ {skills.length ? (
+ <>
+ {skills.slice(0, shownSkills).map((name) => (
+ {name}
+ ))}
+ {skills.length > shownSkills && (
+ +{skills.length - shownSkills}
+ )}
+ >
+ ) : (
+ {tr("无")}
+ )}
+
+
+ {capabilities.length ? (
+ capabilities.map((name) => {name})
+ ) : (
+ {tr("无")}
+ )}
+