mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
🐛 fix: group builder not set true edit data (#11858)
* feat: add the setAgentBuilderContent tools into agent group builder to slove setEditor not work * feat: update the system prompt
This commit is contained in:
@@ -6,6 +6,7 @@ import { type GroupMemberConfig, chatGroupService } from '@/services/chatGroup';
|
||||
import { useAgentStore } from '@/store/agent';
|
||||
import { getChatGroupStoreState } from '@/store/agentGroup';
|
||||
import { agentGroupSelectors } from '@/store/agentGroup/selectors';
|
||||
import { useGroupProfileStore } from '@/store/groupProfile';
|
||||
|
||||
import type {
|
||||
BatchCreateAgentsParams,
|
||||
@@ -410,6 +411,11 @@ export class GroupAgentBuilderExecutionRuntime {
|
||||
// Refresh the group detail in the store to sync agent data
|
||||
await state.refreshGroupDetail(groupId);
|
||||
|
||||
// IMPORTANT: Directly update the editor content instead of manipulating store data.
|
||||
// This bypasses the priority issue between editorData (JSON) and systemRole (markdown).
|
||||
// The editor will auto-save and sync both fields properly after the update.
|
||||
useGroupProfileStore.getState().setAgentBuilderContent(agentId, prompt);
|
||||
|
||||
const content = prompt
|
||||
? `Successfully updated agent ${agentId} system prompt (${prompt.length} characters)`
|
||||
: `Successfully cleared agent ${agentId} system prompt`;
|
||||
@@ -563,6 +569,11 @@ export class GroupAgentBuilderExecutionRuntime {
|
||||
// Refresh the group detail in the store to ensure data sync
|
||||
await state.refreshGroupDetail(group.id);
|
||||
|
||||
// IMPORTANT: Directly update the editor content instead of manipulating store data.
|
||||
// This bypasses the priority issue between editorData (JSON) and content (markdown).
|
||||
// The editor will auto-save and sync both fields properly after the update.
|
||||
useGroupProfileStore.getState().setAgentBuilderContent(group.id, args.prompt);
|
||||
|
||||
const content = args.prompt
|
||||
? `Successfully updated group shared prompt (${args.prompt.length} characters)`
|
||||
: 'Successfully cleared group shared prompt';
|
||||
|
||||
@@ -63,6 +63,13 @@ You have access to tools that can modify group configurations:
|
||||
- User wants to change how a specific agent behaves → use \`updateAgentPrompt\` with that agent's ID
|
||||
- User mentions "group prompt", "shared content", "background info" → use \`updateGroupPrompt\`
|
||||
- User mentions "agent behavior", "agent prompt", specific agent name → use \`updateAgentPrompt\`
|
||||
|
||||
**CRITICAL - Individual Updates Only:**
|
||||
- **NEVER batch update multiple agents with the same prompt** - each agent should have its own unique configuration
|
||||
- **ALWAYS update agents individually** - use \`updateAgentPrompt\` with a specific agentId for each agent
|
||||
- **ALWAYS update group prompt separately** - use \`updateGroupPrompt\` for shared content, never mix with agent prompts
|
||||
- When modifying multiple agents, call \`updateAgentPrompt\` once for each agent with their specific agentId
|
||||
- When modifying group content, call \`updateGroupPrompt\` separately - it applies to ALL members
|
||||
</prompt_architecture>
|
||||
|
||||
<supervisor_prompt_generation>
|
||||
@@ -176,13 +183,18 @@ When creating agents (via \`createAgent\` or \`batchCreateAgents\`), you MUST an
|
||||
4. **Distinguish group vs agent operations**:
|
||||
- Group-level: updateGroupPrompt, updateGroup, inviteAgent, removeAgent, batchCreateAgents
|
||||
- Agent-level: updateAgentPrompt (requires agentId), updateConfig (agentId optional, defaults to supervisor), installPlugin
|
||||
5. **CRITICAL - Auto-update supervisor after member changes**: After ANY member change (create, invite, remove), you MUST automatically call \`updateAgentPrompt\` with supervisor's agentId to regenerate the orchestration prompt. This is NOT optional - the supervisor needs updated delegation rules to coordinate the team effectively.
|
||||
6. **CRITICAL - Assign tools when creating agents**: When using \`createAgent\` or \`batchCreateAgents\`, ALWAYS include appropriate \`tools\` based on the agent's role. Reference \`official_tools\` in the context for available tool identifiers. An agent without proper tools cannot perform specialized tasks.
|
||||
7. **Explain your changes**: When modifying configurations, explain what you're changing and why it might benefit the group collaboration.
|
||||
8. **Validate user intent**: For significant changes (like removing an agent), confirm with the user before proceeding.
|
||||
9. **Provide recommendations**: When users ask for advice, consider how changes affect multi-agent collaboration.
|
||||
10. **Use user's language**: Always respond in the same language the user is using.
|
||||
11. **Cannot remove supervisor**: The supervisor agent cannot be removed from the group - it's the orchestrator.
|
||||
5. **CRITICAL - Individual updates only**:
|
||||
- When updating agent prompts, ALWAYS call \`updateAgentPrompt\` individually for each agent with their specific agentId
|
||||
- When updating group prompt, ALWAYS call \`updateGroupPrompt\` separately - it affects ALL members
|
||||
- NEVER try to batch update multiple agents with the same prompt - each agent needs individual configuration
|
||||
- NEVER mix group prompt updates with agent prompt updates - they serve different purposes
|
||||
6. **CRITICAL - Auto-update supervisor after member changes**: After ANY member change (create, invite, remove), you MUST automatically call \`updateAgentPrompt\` with supervisor's agentId to regenerate the orchestration prompt. This is NOT optional - the supervisor needs updated delegation rules to coordinate the team effectively.
|
||||
7. **CRITICAL - Assign tools when creating agents**: When using \`createAgent\` or \`batchCreateAgents\`, ALWAYS include appropriate \`tools\` based on the agent's role. Reference \`official_tools\` in the context for available tool identifiers. An agent without proper tools cannot perform specialized tasks.
|
||||
8. **Explain your changes**: When modifying configurations, explain what you're changing and why it might benefit the group collaboration.
|
||||
9. **Validate user intent**: For significant changes (like removing an agent), confirm with the user before proceeding.
|
||||
10. **Provide recommendations**: When users ask for advice, consider how changes affect multi-agent collaboration.
|
||||
11. **Use user's language**: Always respond in the same language the user is using.
|
||||
12. **Cannot remove supervisor**: The supervisor agent cannot be removed from the group - it's the orchestrator.
|
||||
</guidelines>
|
||||
|
||||
<configuration_knowledge>
|
||||
@@ -256,6 +268,24 @@ When creating agents (via \`createAgent\` or \`batchCreateAgents\`), you MUST an
|
||||
- For member: Find agentId from \`<group_members>\`, then updateAgentPrompt with that agentId
|
||||
</example>
|
||||
|
||||
<example title="Update Multiple Agents (Individual Updates Required)">
|
||||
User: "Update the prompts for developer and designer agents"
|
||||
Action (MUST update individually):
|
||||
1. Find developer agentId from \`<group_members>\`
|
||||
2. Call updateAgentPrompt with developer's agentId and their specific prompt
|
||||
3. Find designer agentId from \`<group_members>\`
|
||||
4. Call updateAgentPrompt with designer's agentId and their specific prompt
|
||||
Note: Each agent gets a separate updateAgentPrompt call with unique content - NEVER use the same prompt for multiple agents
|
||||
</example>
|
||||
|
||||
<example title="Update Both Group and Agent Prompts (Separate Updates)">
|
||||
User: "Add project context and update supervisor's delegation rules"
|
||||
Action (MUST update separately):
|
||||
1. First - updateGroupPrompt: Add project background, domain knowledge (shared by ALL)
|
||||
2. Second - updateAgentPrompt with supervisor's agentId: Add delegation rules (supervisor only)
|
||||
Note: Group prompt and agent prompt are separate - NEVER combine them in one update
|
||||
</example>
|
||||
|
||||
<example title="Update Configuration">
|
||||
User: "Change model to Claude" / "Set welcome message"
|
||||
Action:
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Button, Flexbox } from '@lobehub/ui';
|
||||
import { Divider } from 'antd';
|
||||
import { useTheme } from 'antd-style';
|
||||
import { PlayIcon, Settings2Icon } from 'lucide-react';
|
||||
import { memo, useCallback, useMemo, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import urlJoin from 'url-join';
|
||||
|
||||
@@ -30,6 +30,8 @@ const GroupProfile = memo(() => {
|
||||
|
||||
const editor = useGroupProfileStore((s) => s.editor);
|
||||
const handleContentChange = useGroupProfileStore((s) => s.handleContentChange);
|
||||
const agentBuilderContentUpdate = useGroupProfileStore((s) => s.agentBuilderContentUpdate);
|
||||
const setAgentBuilderContent = useGroupProfileStore((s) => s.setAgentBuilderContent);
|
||||
|
||||
// Create save callback that captures latest groupId
|
||||
const saveContent = useCallback(
|
||||
@@ -56,6 +58,18 @@ const GroupProfile = memo(() => {
|
||||
[currentGroup?.content, currentGroup?.editorData],
|
||||
);
|
||||
|
||||
// Watch for agent builder content updates and apply them directly to the editor
|
||||
useEffect(() => {
|
||||
if (!editor || !agentBuilderContentUpdate || !groupId) return;
|
||||
if (agentBuilderContentUpdate.entityId !== groupId) return;
|
||||
|
||||
// Directly set the editor content
|
||||
editor.setDocument('markdown', agentBuilderContentUpdate.content);
|
||||
|
||||
// Clear the update after processing to prevent re-applying
|
||||
setAgentBuilderContent('', '');
|
||||
}, [editor, agentBuilderContentUpdate, groupId, setAgentBuilderContent]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flexbox
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Alert, Button, Flexbox, Icon } from '@lobehub/ui';
|
||||
import { Divider } from 'antd';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { InfoIcon, PlayIcon } from 'lucide-react';
|
||||
import React, { memo, useCallback, useMemo } from 'react';
|
||||
import React, { memo, useCallback, useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import urlJoin from 'url-join';
|
||||
|
||||
@@ -28,6 +28,8 @@ const MemberProfile = memo(() => {
|
||||
const agentId = useGroupProfileStore((s) => s.activeTabId);
|
||||
const editor = useGroupProfileStore((s) => s.editor);
|
||||
const handleContentChange = useGroupProfileStore((s) => s.handleContentChange);
|
||||
const agentBuilderContentUpdate = useGroupProfileStore((s) => s.agentBuilderContentUpdate);
|
||||
const setAgentBuilderContent = useGroupProfileStore((s) => s.setAgentBuilderContent);
|
||||
|
||||
// Get agent config by agentId
|
||||
const config = useAgentStore(agentByIdSelectors.getAgentConfigById(agentId), isEqual);
|
||||
@@ -80,6 +82,18 @@ const MemberProfile = memo(() => {
|
||||
[updateAgentConfigById, agentId],
|
||||
);
|
||||
|
||||
// Watch for agent builder content updates and apply them directly to the editor
|
||||
useEffect(() => {
|
||||
if (!editor || !agentBuilderContentUpdate) return;
|
||||
if (agentBuilderContentUpdate.entityId !== agentId) return;
|
||||
|
||||
// Directly set the editor content
|
||||
editor.setDocument('markdown', agentBuilderContentUpdate.content);
|
||||
|
||||
// Clear the update after processing to prevent re-applying
|
||||
setAgentBuilderContent('', '');
|
||||
}, [editor, agentBuilderContentUpdate, agentId, setAgentBuilderContent]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* External agent warning or AutoSaveHint */}
|
||||
|
||||
@@ -22,13 +22,19 @@ const loadEditorContent = (
|
||||
typeof editorData.editorData === 'object' &&
|
||||
Object.keys(editorData.editorData as object).length > 0;
|
||||
|
||||
if (hasValidEditorData) {
|
||||
editorInstance.setDocument('json', JSON.stringify(editorData.editorData));
|
||||
return true;
|
||||
} else if (editorData.content?.trim()) {
|
||||
editorInstance.setDocument('markdown', editorData.content, { keepId: true });
|
||||
return true;
|
||||
try {
|
||||
if (hasValidEditorData) {
|
||||
editorInstance.setDocument('json', JSON.stringify(editorData.editorData));
|
||||
return true;
|
||||
} else if (editorData.content?.trim()) {
|
||||
editorInstance.setDocument('markdown', editorData.content, { keepId: true });
|
||||
return true;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[loadEditorContent] Error loading content:', err);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -65,12 +71,12 @@ const EditorDataMode = memo<EditorDataModeProps>(
|
||||
[editorData, entityId, onInit],
|
||||
);
|
||||
|
||||
// Load content only when entityId changes (switching to a different entity)
|
||||
// Ignore editorData changes for the same entity to prevent focus loss during auto-save
|
||||
// Load content when entityId changes (switching to a different entity)
|
||||
// Ignore editorData changes when entityId hasn't changed to prevent focus loss during auto-save
|
||||
useEffect(() => {
|
||||
if (!editor || !isEditorReadyRef.current) return;
|
||||
|
||||
// Only reload if entityId changed (switching entities)
|
||||
// Only reload if entityId changed
|
||||
if (!isEntityChanged) {
|
||||
// Same entity - don't reload, user is still editing
|
||||
return;
|
||||
@@ -84,7 +90,7 @@ const EditorDataMode = memo<EditorDataModeProps>(
|
||||
} catch (err) {
|
||||
console.error('[EditorCanvas] Failed to load content:', err);
|
||||
}
|
||||
}, [editor, entityId, isEntityChanged, editorData]);
|
||||
}, [editor, entityId, editorData, isEntityChanged]);
|
||||
|
||||
if (!editor) return null;
|
||||
|
||||
|
||||
@@ -115,8 +115,15 @@ const getAgentBuilderContextById =
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get full agent data by agentId
|
||||
* Returns the complete agent object including metadata fields like updatedAt
|
||||
*/
|
||||
const getAgentById = (agentId: string) => (s: AgentStoreState) => s.agentMap[agentId];
|
||||
|
||||
export const agentByIdSelectors = {
|
||||
getAgentBuilderContextById,
|
||||
getAgentById,
|
||||
getAgentConfigById: agentSelectors.getAgentConfigById,
|
||||
getAgentEnableModeById,
|
||||
getAgentFilesById,
|
||||
|
||||
@@ -16,6 +16,11 @@ export interface Action {
|
||||
flushSave: () => void;
|
||||
handleContentChange: (saveCallback: (payload: SaveContentPayload) => Promise<void>) => void;
|
||||
setActiveTabId: (tabId: string) => void;
|
||||
/**
|
||||
* Set content from agent builder - triggers editor to update
|
||||
* @param entityId - groupId for group editor, agentId for member editor
|
||||
*/
|
||||
setAgentBuilderContent: (entityId: string, content: string) => void;
|
||||
setChatPanelExpanded: (expanded: boolean | ((prev: boolean) => boolean)) => void;
|
||||
updateSaveStatus: (tabId: string, status: SaveStatus) => void;
|
||||
}
|
||||
@@ -153,6 +158,16 @@ export const store: StateCreator<Store> = (set, get) => {
|
||||
set({ activeTabId: tabId });
|
||||
},
|
||||
|
||||
setAgentBuilderContent: (entityId, content) => {
|
||||
set({
|
||||
agentBuilderContentUpdate: {
|
||||
content,
|
||||
entityId,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
setChatPanelExpanded: (expanded) => {
|
||||
if (typeof expanded === 'function') {
|
||||
set((state) => ({ chatPanelExpanded: expanded(state.chatPanelExpanded) }));
|
||||
|
||||
@@ -15,6 +15,15 @@ export interface State extends PublicState {
|
||||
* Active tab ID - 'group' for group settings, or agent ID for member editor
|
||||
*/
|
||||
activeTabId: string;
|
||||
/**
|
||||
* Agent builder content update - when set, triggers editor to load new content
|
||||
* Format: { entityId: string (groupId or agentId), content: string, timestamp: number }
|
||||
*/
|
||||
agentBuilderContentUpdate?: {
|
||||
content: string;
|
||||
entityId: string;
|
||||
timestamp: number;
|
||||
};
|
||||
chatPanelExpanded: boolean;
|
||||
editor?: IEditor;
|
||||
editorState?: any; // EditorState from useEditorState hook
|
||||
|
||||
Reference in New Issue
Block a user