feat: 新增专家提示词核心模块,支持文件发现、CRUD与运行时选择
- 新增 src/experts/mod.rs 模块,镜像 skills/subagents 模式 - 支持 user/project 双 scope 从 EXPERT.md 文件发现专家 - ExpertRuntime 维护 session→expert 映射与禁用列表,持久化到 expert-state.json - ExpertPromptProvider 实现系统提示词注入,未选中时返回 None - 包含 16 个单元测试覆盖 frontmatter 解析、discover 优先级、CRUD、select/clear、disable 场景
This commit is contained in:
parent
8d30ccd020
commit
c2d9bf8b5e
@ -67,6 +67,7 @@ impl OutputAdapter for WebSocketOutputAdapter {
|
|||||||
code: error.code,
|
code: error.code,
|
||||||
message: error.message,
|
message: error.message,
|
||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
|
subagent_task_id: None,
|
||||||
});
|
});
|
||||||
return outbounds;
|
return outbounds;
|
||||||
}
|
}
|
||||||
@ -197,6 +198,7 @@ impl OutputAdapter for WebSocketOutputAdapter {
|
|||||||
code: "RESPONSE_ERROR".to_string(),
|
code: "RESPONSE_ERROR".to_string(),
|
||||||
message: msg.content.clone(),
|
message: msg.content.clone(),
|
||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
|
subagent_task_id: None,
|
||||||
},
|
},
|
||||||
_ => WsOutbound::AssistantResponse {
|
_ => WsOutbound::AssistantResponse {
|
||||||
id: response.request_id.to_string(),
|
id: response.request_id.to_string(),
|
||||||
|
|||||||
1484
src/experts/mod.rs
Normal file
1484
src/experts/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -267,6 +267,7 @@ async fn handle_socket(ws: WebSocket, state: Arc<GatewayState>) {
|
|||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
code:"SESSION_ERROR".to_string(),
|
code:"SESSION_ERROR".to_string(),
|
||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
|
subagent_task_id: None,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -278,6 +279,7 @@ async fn handle_socket(ws: WebSocket, state: Arc<GatewayState>) {
|
|||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
code:"PARSE_ERROR".to_string(),
|
code:"PARSE_ERROR".to_string(),
|
||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
|
subagent_task_id: None,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -370,6 +372,7 @@ async fn handle_inbound(
|
|||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
code: "INVALID_COMMAND".to_string(),
|
code: "INVALID_COMMAND".to_string(),
|
||||||
message: "Invalid command payload".to_string(),
|
message: "Invalid command payload".to_string(),
|
||||||
|
subagent_task_id: None,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -380,6 +383,7 @@ async fn handle_inbound(
|
|||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
code: "PARSE_ERROR".to_string(),
|
code: "PARSE_ERROR".to_string(),
|
||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
|
subagent_task_id: None,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -796,6 +800,12 @@ fn set_subagent_task_id(outbound: &mut WsOutbound, task_id: &str) {
|
|||||||
}
|
}
|
||||||
| WsOutbound::ToolPending {
|
| WsOutbound::ToolPending {
|
||||||
subagent_task_id, ..
|
subagent_task_id, ..
|
||||||
|
}
|
||||||
|
| WsOutbound::StreamDelta {
|
||||||
|
subagent_task_id, ..
|
||||||
|
}
|
||||||
|
| WsOutbound::StreamEnd {
|
||||||
|
subagent_task_id, ..
|
||||||
} => {
|
} => {
|
||||||
*subagent_task_id = Some(task_id.to_string());
|
*subagent_task_id = Some(task_id.to_string());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ pub mod client;
|
|||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod domain;
|
pub mod domain;
|
||||||
|
pub mod experts;
|
||||||
pub mod gateway;
|
pub mod gateway;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
pub mod mcp;
|
pub mod mcp;
|
||||||
|
|||||||
@ -209,6 +209,8 @@ pub enum WsOutbound {
|
|||||||
message: String,
|
message: String,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
timestamp: Option<i64>,
|
timestamp: Option<i64>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
subagent_task_id: Option<String>,
|
||||||
},
|
},
|
||||||
#[serde(rename = "task_started")]
|
#[serde(rename = "task_started")]
|
||||||
TaskStarted {
|
TaskStarted {
|
||||||
@ -301,6 +303,8 @@ pub enum WsOutbound {
|
|||||||
topic_id: Option<String>,
|
topic_id: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
timestamp: Option<i64>,
|
timestamp: Option<i64>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
subagent_task_id: Option<String>,
|
||||||
},
|
},
|
||||||
#[serde(rename = "todo_list")]
|
#[serde(rename = "todo_list")]
|
||||||
TodoList {
|
TodoList {
|
||||||
|
|||||||
@ -172,6 +172,7 @@ pub(crate) fn ws_outbound_from_outbound_message(message: &OutboundMessage) -> Ve
|
|||||||
code: "AGENT_ERROR".to_string(),
|
code: "AGENT_ERROR".to_string(),
|
||||||
message: message.content.clone(),
|
message: message.content.clone(),
|
||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
|
subagent_task_id: message.metadata.get("subagent_task_id").cloned(),
|
||||||
}],
|
}],
|
||||||
OutboundEventKind::TaskStarted => vec![WsOutbound::TaskStarted {
|
OutboundEventKind::TaskStarted => vec![WsOutbound::TaskStarted {
|
||||||
task_id: message.metadata.get("task_id").cloned().unwrap_or_default(),
|
task_id: message.metadata.get("task_id").cloned().unwrap_or_default(),
|
||||||
@ -197,6 +198,7 @@ pub(crate) fn ws_outbound_from_outbound_message(message: &OutboundMessage) -> Ve
|
|||||||
OutboundEventKind::ExecutionCompleted => vec![WsOutbound::ExecutionCompleted {
|
OutboundEventKind::ExecutionCompleted => vec![WsOutbound::ExecutionCompleted {
|
||||||
topic_id: message.metadata.get("topic_id").cloned(),
|
topic_id: message.metadata.get("topic_id").cloned(),
|
||||||
timestamp: Some(crate::protocol::now_timestamp()),
|
timestamp: Some(crate::protocol::now_timestamp()),
|
||||||
|
subagent_task_id: message.metadata.get("subagent_task_id").cloned(),
|
||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user