智能体分权

This commit is contained in:
吉鑫升 committed 2026-05-13 11:36:17 +08:00
1 parent e7a455f22e
commit cf2e4bdd9c
31 files changed
+1237 -436

No files matched your search

+11 -10
View File
@@ -37,11 +37,11 @@ export default function AgentChatPage() {
const [hasStartedConversation, setHasStartedConversation] = useState(false);
const router = useRouter();
const { agent_name } = useParams<{
agent_name: string;
const { agent_id } = useParams<{
agent_id: string;
}>();
const { agent } = useAgent(agent_name);
const { agent } = useAgent(agent_id);
const { threadId, setThreadId, isNewThread, setIsNewThread } =
useThreadChat();
@@ -57,7 +57,8 @@ export default function AgentChatPage() {
const { showNotification } = useNotification();
const [thread, sendMessage] = useThreadStream({
threadId: isNewThread ? undefined : threadId,
context: { ...settings.context, agent_name: agent_name },
assistantId: agent_id,
context: { ...settings.context, agent_id },
onStart: (createdThreadId) => {
setThreadId(createdThreadId);
setIsNewThread(false);
@@ -65,7 +66,7 @@ export default function AgentChatPage() {
history.replaceState(
null,
"",
`${window.location.pathname}${window.location.search}#/workspace/agents/${agent_name}/chats/${createdThreadId}`,
`${window.location.pathname}${window.location.search}#/workspace/agents/${agent_id}/chats/${createdThreadId}`,
);
},
onFinish: (state) => {
@@ -92,9 +93,9 @@ export default function AgentChatPage() {
window.dispatchEvent(
new CustomEvent("workspace:sandbox-resume-autoscroll"),
);
void sendMessage(threadId, message, { agent_name });
void sendMessage(threadId, message, { agent_id });
},
[sendMessage, threadId, agent_name],
[sendMessage, threadId, agent_id],
);
const handleStop = useCallback(async () => {
@@ -123,7 +124,7 @@ export default function AgentChatPage() {
<div className="flex shrink-0 items-center gap-1.5 rounded-md border px-2 py-1">
<BotIcon className="text-primary h-3.5 w-3.5" />
<span className="text-xs font-medium">
{agent?.name ?? agent_name}
{agent?.name ?? agent_id}
</span>
</div>
@@ -136,7 +137,7 @@ export default function AgentChatPage() {
size="sm"
variant="secondary"
onClick={() => {
router.push(`/workspace/agents/${agent_name}/chats/new`);
router.push(`/workspace/agents/${agent_id}/chats/new`);
}}
>
<PlusSquare /> {t.agents.newChat}
@@ -199,7 +200,7 @@ export default function AgentChatPage() {
context={settings.context}
extraHeader={
isLandingState && (
<AgentWelcome agent={agent} agentName={agent_name} />
<AgentWelcome agent={agent} agentName={agent?.name ?? agent_id} />
)
}
disabled={env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true"}
+21 -23
View File
@@ -49,7 +49,6 @@ import { cn } from "@/lib/utils";
type Step = "name" | "chat";
type SetupAgentStatus = "idle" | "requested" | "completed";
const NAME_RE = /^[A-Za-z0-9-]+$/;
const SAVE_HINT_STORAGE_KEY = "deerflow.agent-create.save-hint-seen";
const AGENT_READ_RETRY_DELAYS_MS = [200, 500, 1_000, 2_000];
const DEFAULT_SELECTED_SKILL_COUNT = 3;
@@ -58,14 +57,14 @@ function wait(ms: number) {
return new Promise((resolve) => window.setTimeout(resolve, ms));
}
async function getAgentWithRetry(agentName: string) {
async function getAgentWithRetry(agentId: string) {
for (const delay of [0, ...AGENT_READ_RETRY_DELAYS_MS]) {
if (delay > 0) {
await wait(delay);
}
try {
return await getAgent(agentName);
return await getAgent(agentId);
} catch {
// Retry until the write settles or the attempts are exhausted.
}
@@ -97,7 +96,7 @@ export default function NewAgentPage() {
const [nameError, setNameError] = useState("");
const [isCheckingName, setIsCheckingName] = useState(false);
const [isCreatingAgent, setIsCreatingAgent] = useState(false);
const [agentName, setAgentName] = useState("");
const [agentId, setAgentId] = useState("");
const [agent, setAgent] = useState<Agent | null>(null);
const [showSaveHint, setShowSaveHint] = useState(false);
const [setupAgentStatus, setSetupAgentStatus] =
@@ -125,6 +124,7 @@ export default function NewAgentPage() {
const [thread, sendMessage] = useThreadStream({
threadId: step === "chat" ? threadId : undefined,
assistantId: agentId || undefined,
context: {
mode: "flash",
is_bootstrap: true,
@@ -135,9 +135,9 @@ export default function NewAgentPage() {
}
},
onToolEnd({ name }) {
if (name !== "setup_agent" || !agentName) return;
if (name !== "setup_agent" || !agentId) return;
setSetupAgentStatus("completed");
void getAgentWithRetry(agentName).then((fetched) => {
void getAgentWithRetry(agentId).then((fetched) => {
if (fetched) {
setAgent(fetched);
return;
@@ -171,8 +171,7 @@ export default function NewAgentPage() {
const handleConfirmName = useCallback(async () => {
const trimmed = nameInput.trim();
if (!trimmed) return;
if (!NAME_RE.test(trimmed)) {
if (!trimmed) {
setNameError(t.agents.nameStepInvalidError);
return;
}
@@ -185,11 +184,7 @@ export default function NewAgentPage() {
setNameError("");
setIsCheckingName(true);
try {
const result = await checkAgentName(trimmed);
if (!result.available) {
setNameError(t.agents.nameStepAlreadyExistsError);
return;
}
await checkAgentName(trimmed);
} catch (err) {
if (
err instanceof AgentNameCheckError &&
@@ -204,14 +199,18 @@ export default function NewAgentPage() {
setIsCheckingName(false);
}
let createdId: string;
let createdName: string;
setIsCreatingAgent(true);
try {
await createAgent({
const created = await createAgent({
name: trimmed,
description: "",
skills: selectedSkills,
soul: "",
});
createdId = created.id;
createdName = created.name;
} catch (err) {
setNameError(
getCreateAgentErrorMessage(
@@ -225,17 +224,16 @@ export default function NewAgentPage() {
setIsCreatingAgent(false);
}
setAgentName(trimmed);
setAgentId(createdId);
setStep("chat");
await ensureThreadExists();
await sendMessage(threadId, {
text: t.agents.nameStepBootstrapMessage.replace("{name}", trimmed),
text: t.agents.nameStepBootstrapMessage.replace("{name}", createdName),
files: [],
});
}, [
nameInput,
sendMessage,
t.agents.nameStepAlreadyExistsError,
t.agents.nameStepNetworkError,
t.agents.nameStepBootstrapMessage,
t.agents.nameStepCheckError,
@@ -272,15 +270,15 @@ export default function NewAgentPage() {
await sendMessage(
threadId,
{ text: trimmed, files: [] },
{ agent_name: agentName },
{ agent_id: agentId },
);
},
[agentName, sendMessage, thread.isLoading, threadId, ensureThreadExists],
[agentId, sendMessage, thread.isLoading, threadId, ensureThreadExists],
);
const handleSaveAgent = useCallback(async () => {
if (
!agentName ||
!agentId ||
agent ||
thread.isLoading ||
setupAgentStatus !== "idle"
@@ -294,7 +292,7 @@ export default function NewAgentPage() {
await sendMessage(
threadId,
{ text: t.agents.saveCommandMessage, files: [] },
{ agent_name: agentName },
{ agent_id: agentId },
{ additionalKwargs: { hide_from_ui: true } },
);
toast.success(t.agents.saveRequested);
@@ -304,7 +302,7 @@ export default function NewAgentPage() {
}
}, [
agent,
agentName,
agentId,
sendMessage,
setupAgentStatus,
t.agents.saveCommandMessage,
@@ -480,7 +478,7 @@ export default function NewAgentPage() {
<Button
onClick={() =>
router.push(
`/workspace/agents/${agentName}/chats/new`,
`/workspace/agents/${agentId}/chats/new`,
)
}
>