Compare commits
No commits in common. "631c61fea2e241e1eeedbe948c7417d1af63829a" and "8af7edfb3265133313da06a70e9e78a6bf5dd257" have entirely different histories.
631c61fea2
...
8af7edfb32
@ -221,8 +221,6 @@ pub struct TaskConfig {
|
|||||||
pub ttl_hours: u64,
|
pub ttl_hours: u64,
|
||||||
#[serde(default = "default_task_allowed_tools")]
|
#[serde(default = "default_task_allowed_tools")]
|
||||||
pub allowed_tools: Vec<String>,
|
pub allowed_tools: Vec<String>,
|
||||||
#[serde(default = "default_task_max_nesting_depth")]
|
|
||||||
pub max_nesting_depth: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_task_enabled() -> bool {
|
fn default_task_enabled() -> bool {
|
||||||
@ -241,10 +239,6 @@ fn default_task_ttl_hours() -> u64 {
|
|||||||
24
|
24
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_task_max_nesting_depth() -> u32 {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_task_allowed_tools() -> Vec<String> {
|
fn default_task_allowed_tools() -> Vec<String> {
|
||||||
vec![
|
vec![
|
||||||
"read".to_string(),
|
"read".to_string(),
|
||||||
@ -270,7 +264,6 @@ impl Default for TaskConfig {
|
|||||||
explore_max_execution_secs: default_task_explore_max_execution_secs(),
|
explore_max_execution_secs: default_task_explore_max_execution_secs(),
|
||||||
ttl_hours: default_task_ttl_hours(),
|
ttl_hours: default_task_ttl_hours(),
|
||||||
allowed_tools: default_task_allowed_tools(),
|
allowed_tools: default_task_allowed_tools(),
|
||||||
max_nesting_depth: default_task_max_nesting_depth(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,6 @@ impl AgentFactory {
|
|||||||
message_id: request.message_id.map(str::to_string),
|
message_id: request.message_id.map(str::to_string),
|
||||||
message_seq: None,
|
message_seq: None,
|
||||||
subagent_description: None,
|
subagent_description: None,
|
||||||
nesting_depth: 0,
|
|
||||||
});
|
});
|
||||||
// 如果有取消信号接收端,注入 Agent
|
// 如果有取消信号接收端,注入 Agent
|
||||||
if let Some(token) = request.cancel_token {
|
if let Some(token) = request.cancel_token {
|
||||||
|
|||||||
@ -193,7 +193,6 @@ pub(crate) fn build_session_manager_with_sender(
|
|||||||
explore_max_execution_secs: task_config.explore_max_execution_secs,
|
explore_max_execution_secs: task_config.explore_max_execution_secs,
|
||||||
ttl_hours: task_config.ttl_hours,
|
ttl_hours: task_config.ttl_hours,
|
||||||
skills_index: skills.system_index_prompt(),
|
skills_index: skills.system_index_prompt(),
|
||||||
max_nesting_depth: task_config.max_nesting_depth,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let subagent_runtime = Arc::new(DefaultSubAgentRuntime::new(
|
let subagent_runtime = Arc::new(DefaultSubAgentRuntime::new(
|
||||||
|
|||||||
@ -243,15 +243,7 @@ impl ToolRegistryFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册 task 工具,允许子代理创建孙代理(深度由 TaskTool 运行时控制)
|
// 注意:不注册 task 工具,防止递归创建子代理
|
||||||
if self.is_enabled("task") && self.task_config.enabled {
|
|
||||||
if let Some(runtime) = &self.subagent_runtime {
|
|
||||||
registry.register(TaskTool::new_with_depth(
|
|
||||||
runtime.clone(),
|
|
||||||
self.task_config.max_nesting_depth,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registry
|
registry
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,8 +34,6 @@ pub struct SubAgentRuntimeConfig {
|
|||||||
pub ttl_hours: u64,
|
pub ttl_hours: u64,
|
||||||
/// 技能索引(可选,预生成的技能列表字符串)
|
/// 技能索引(可选,预生成的技能列表字符串)
|
||||||
pub skills_index: Option<String>,
|
pub skills_index: Option<String>,
|
||||||
/// 子代理最大嵌套深度(0 = 禁止嵌套,1 = 允许 1 层孙代理)
|
|
||||||
pub max_nesting_depth: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SubAgentRuntimeConfig {
|
impl Default for SubAgentRuntimeConfig {
|
||||||
@ -59,7 +57,6 @@ impl Default for SubAgentRuntimeConfig {
|
|||||||
explore_max_execution_secs: 3600, // 60分钟
|
explore_max_execution_secs: 3600, // 60分钟
|
||||||
ttl_hours: 24,
|
ttl_hours: 24,
|
||||||
skills_index: None,
|
skills_index: None,
|
||||||
max_nesting_depth: 1,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +323,6 @@ impl DefaultSubAgentRuntime {
|
|||||||
&self,
|
&self,
|
||||||
session: &TaskSession,
|
session: &TaskSession,
|
||||||
system_prompt: String,
|
system_prompt: String,
|
||||||
parent_nesting_depth: u32,
|
|
||||||
) -> Result<AgentLoop, TaskError> {
|
) -> Result<AgentLoop, TaskError> {
|
||||||
let prompt_provider = Arc::new(StaticSystemPromptProvider::new(system_prompt));
|
let prompt_provider = Arc::new(StaticSystemPromptProvider::new(system_prompt));
|
||||||
|
|
||||||
@ -346,7 +342,6 @@ impl DefaultSubAgentRuntime {
|
|||||||
message_id: None,
|
message_id: None,
|
||||||
message_seq: None,
|
message_seq: None,
|
||||||
subagent_description: Some(session.description.clone()),
|
subagent_description: Some(session.description.clone()),
|
||||||
nesting_depth: parent_nesting_depth + 1,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果有 MessageBus,附加实时广播 emitter
|
// 如果有 MessageBus,附加实时广播 emitter
|
||||||
@ -566,7 +561,7 @@ impl SubAgentRuntime for DefaultSubAgentRuntime {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 7. 创建子代理
|
// 7. 创建子代理
|
||||||
let agent = self.create_subagent(&session, system_prompt, parent_context.nesting_depth)?;
|
let agent = self.create_subagent(&session, system_prompt)?;
|
||||||
|
|
||||||
// 8. 执行任务
|
// 8. 执行任务
|
||||||
let result = self
|
let result = self
|
||||||
@ -647,7 +642,7 @@ impl SubAgentRuntime for DefaultSubAgentRuntime {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 5. 创建子代理
|
// 5. 创建子代理
|
||||||
let agent = self.create_subagent(&session, system_prompt, parent_context.nesting_depth)?;
|
let agent = self.create_subagent(&session, system_prompt)?;
|
||||||
|
|
||||||
// 6. 使用历史继续执行
|
// 6. 使用历史继续执行
|
||||||
let result = self
|
let result = self
|
||||||
|
|||||||
@ -10,24 +10,11 @@ use super::types::{TaskDefinition, TaskToolArgs};
|
|||||||
/// Task 工具 - 创建和管理子代理
|
/// Task 工具 - 创建和管理子代理
|
||||||
pub struct TaskTool {
|
pub struct TaskTool {
|
||||||
runtime: Arc<dyn SubAgentRuntime>,
|
runtime: Arc<dyn SubAgentRuntime>,
|
||||||
/// 最大嵌套深度(0 = 主 agent 不允许创建子代理,1 = 子 agent 可创建 1 层孙 agent)
|
|
||||||
max_nesting_depth: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskTool {
|
impl TaskTool {
|
||||||
pub fn new(runtime: Arc<dyn SubAgentRuntime>) -> Self {
|
pub fn new(runtime: Arc<dyn SubAgentRuntime>) -> Self {
|
||||||
Self {
|
Self { runtime }
|
||||||
runtime,
|
|
||||||
max_nesting_depth: 0, // 主 agent 无深度限制
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建带嵌套深度限制的 TaskTool(用于子代理)
|
|
||||||
pub fn new_with_depth(runtime: Arc<dyn SubAgentRuntime>, max_nesting_depth: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
runtime,
|
|
||||||
max_nesting_depth,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,19 +126,7 @@ impl Tool for TaskTool {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 深度校验(仅对嵌套场景生效,主 agent 的 max_nesting_depth = 0 不限制)
|
// 4. 执行任务
|
||||||
if self.max_nesting_depth > 0 && context.nesting_depth >= self.max_nesting_depth {
|
|
||||||
return Ok(ToolResult {
|
|
||||||
success: false,
|
|
||||||
output: String::new(),
|
|
||||||
error: Some(format!(
|
|
||||||
"Cannot create nested subagent: max nesting depth ({}) reached",
|
|
||||||
self.max_nesting_depth
|
|
||||||
)),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 执行任务
|
|
||||||
let result = if let Some(task_id) = task_args.task_id {
|
let result = if let Some(task_id) = task_args.task_id {
|
||||||
// 恢复现有任务
|
// 恢复现有任务
|
||||||
self.runtime
|
self.runtime
|
||||||
|
|||||||
@ -182,7 +182,6 @@ mod tests {
|
|||||||
message_id: Some("msg-1".to_string()),
|
message_id: Some("msg-1".to_string()),
|
||||||
message_seq: Some(1),
|
message_seq: Some(1),
|
||||||
subagent_description: None,
|
subagent_description: None,
|
||||||
nesting_depth: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -402,7 +402,6 @@ mod tests {
|
|||||||
message_id: Some("msg-1".to_string()),
|
message_id: Some("msg-1".to_string()),
|
||||||
message_seq: Some(1),
|
message_seq: Some(1),
|
||||||
subagent_description: None,
|
subagent_description: None,
|
||||||
nesting_depth: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,8 +18,6 @@ pub struct ToolContext {
|
|||||||
pub message_seq: Option<i64>,
|
pub message_seq: Option<i64>,
|
||||||
/// 子代理标识,用于标注消息来源
|
/// 子代理标识,用于标注消息来源
|
||||||
pub subagent_description: Option<String>,
|
pub subagent_description: Option<String>,
|
||||||
/// 当前嵌套深度(0 = 主 agent,1 = 子 agent,2 = 孙 agent...)
|
|
||||||
pub nesting_depth: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
|||||||
@ -75,7 +75,6 @@ function App() {
|
|||||||
handleCommand,
|
handleCommand,
|
||||||
clearMessages,
|
clearMessages,
|
||||||
handleServerMessage,
|
handleServerMessage,
|
||||||
setSendMessage,
|
|
||||||
selectTopic,
|
selectTopic,
|
||||||
createTopic,
|
createTopic,
|
||||||
switchTopic,
|
switchTopic,
|
||||||
@ -93,11 +92,6 @@ function App() {
|
|||||||
onMessage: handleServerMessage,
|
onMessage: handleServerMessage,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 将 sendMessage 注入到 useChat,供 handleServerMessage 内部发送命令
|
|
||||||
useEffect(() => {
|
|
||||||
setSendMessage(sendMessage)
|
|
||||||
}, [setSendMessage, sendMessage])
|
|
||||||
|
|
||||||
// ---- 主题状态 ----
|
// ---- 主题状态 ----
|
||||||
|
|
||||||
const [memoryPanelOpen, setMemoryPanelOpen] = useState(() => {
|
const [memoryPanelOpen, setMemoryPanelOpen] = useState(() => {
|
||||||
|
|||||||
@ -29,7 +29,6 @@ import type {
|
|||||||
ChannelList,
|
ChannelList,
|
||||||
StreamDelta,
|
StreamDelta,
|
||||||
StreamEnd,
|
StreamEnd,
|
||||||
WsInbound,
|
|
||||||
} from '../types/protocol'
|
} from '../types/protocol'
|
||||||
|
|
||||||
// 简化后的层级状态
|
// 简化后的层级状态
|
||||||
@ -67,7 +66,6 @@ interface UseChatReturn {
|
|||||||
handleCommand: (command: Command) => void
|
handleCommand: (command: Command) => void
|
||||||
clearMessages: () => void
|
clearMessages: () => void
|
||||||
handleServerMessage: (message: WsOutbound) => void
|
handleServerMessage: (message: WsOutbound) => void
|
||||||
setSendMessage: (fn: (msg: WsInbound) => boolean) => void
|
|
||||||
|
|
||||||
// Topic 方法
|
// Topic 方法
|
||||||
selectTopic: (topicId: string) => void
|
selectTopic: (topicId: string) => void
|
||||||
@ -173,12 +171,6 @@ export function useChat(): UseChatReturn {
|
|||||||
const selectedTopicRef = useRef<string | null>(null)
|
const selectedTopicRef = useRef<string | null>(null)
|
||||||
const pendingNewTopicRef = useRef(false)
|
const pendingNewTopicRef = useRef(false)
|
||||||
|
|
||||||
// Ref to send commands from within handleServerMessage (set by App.tsx)
|
|
||||||
const sendMessageRef = useRef<((msg: WsInbound) => boolean) | null>(null)
|
|
||||||
const setSendMessage = useCallback((fn: (msg: WsInbound) => boolean) => {
|
|
||||||
sendMessageRef.current = fn
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const isConnected = useMemo(() => connectionId !== null, [connectionId])
|
const isConnected = useMemo(() => connectionId !== null, [connectionId])
|
||||||
const selectedSession = useMemo(
|
const selectedSession = useMemo(
|
||||||
() => sessions.find(s => s.session_id === selectedSessionId) ?? null,
|
() => sessions.find(s => s.session_id === selectedSessionId) ?? null,
|
||||||
@ -385,11 +377,6 @@ export function useChat(): UseChatReturn {
|
|||||||
const msgSubagentTaskId = getSubagentTaskId(message)
|
const msgSubagentTaskId = getSubagentTaskId(message)
|
||||||
if (msgSubagentTaskId && msgSubagentTaskId === currentSubAgentView.taskId) {
|
if (msgSubagentTaskId && msgSubagentTaskId === currentSubAgentView.taskId) {
|
||||||
appendToSubAgentViewMessage(message)
|
appendToSubAgentViewMessage(message)
|
||||||
// 子代理 todo_write 完成后自动刷新待办列表
|
|
||||||
if (message.type === 'tool_result' && (message as ToolResult).tool_name === 'todo_write') {
|
|
||||||
const refreshCmd = requestSubAgentTodoList(currentSubAgentView.taskId)
|
|
||||||
sendMessageRef.current?.({ type: 'command', payload: JSON.stringify(refreshCmd) })
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 丢弃其他子智能体的消息,避免 fall through 到主消息处理
|
// 丢弃其他子智能体的消息,避免 fall through 到主消息处理
|
||||||
@ -707,14 +694,6 @@ export function useChat(): UseChatReturn {
|
|||||||
// 忽略这些消息
|
// 忽略这些消息
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主视图 todo_write 完成后自动刷新待办列表
|
|
||||||
if (message.type === 'tool_result' && (message as ToolResult).tool_name === 'todo_write') {
|
|
||||||
const refreshCmd = subAgentViewRef.current?.taskId
|
|
||||||
? requestSubAgentTodoList(subAgentViewRef.current.taskId)
|
|
||||||
: requestTodoList()
|
|
||||||
sendMessageRef.current?.({ type: 'command', payload: JSON.stringify(refreshCmd) })
|
|
||||||
}
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleMessage = useCallback((content: string, attachments?: Attachment[]) => {
|
const handleMessage = useCallback((content: string, attachments?: Attachment[]) => {
|
||||||
@ -959,7 +938,6 @@ export function useChat(): UseChatReturn {
|
|||||||
handleCommand,
|
handleCommand,
|
||||||
clearMessages,
|
clearMessages,
|
||||||
handleServerMessage,
|
handleServerMessage,
|
||||||
setSendMessage,
|
|
||||||
selectTopic,
|
selectTopic,
|
||||||
createTopic,
|
createTopic,
|
||||||
switchTopic,
|
switchTopic,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user