Move explicit skill invocation into SkillsExtension

This commit is contained in:
jif-oai
2026-06-18 11:48:21 +02:00
parent 7d97a6f571
commit b991d3854d
26 changed files with 846 additions and 599 deletions
@@ -23,13 +23,20 @@ const LOCAL_SKILL_MARKER: &str = "LOCAL_SKILL_BODY_MARKER";
#[tokio::test]
async fn selected_executor_root_exposes_plugin_skill() -> Result<()> {
let server = responses::start_mock_server().await;
let response_mock = responses::mount_sse_once(
let response_mock = responses::mount_sse_sequence(
&server,
responses::sse(vec![
responses::ev_response_created("resp-selected"),
responses::ev_assistant_message("msg-selected", "Done"),
responses::ev_completed("resp-selected"),
]),
vec![
responses::sse(vec![
responses::ev_response_created("resp-selected"),
responses::ev_assistant_message("msg-selected", "Done"),
responses::ev_completed("resp-selected"),
]),
responses::sse(vec![
responses::ev_response_created("resp-host"),
responses::ev_assistant_message("msg-host", "Done"),
responses::ev_completed("resp-host"),
]),
],
)
.await;
@@ -145,5 +152,55 @@ stream_max_retries = 0
assert!(skill_fragment.contains(SKILL_MARKER));
assert!(!skill_fragment.contains(LOCAL_SKILL_MARKER));
let request_id = app_server
.send_thread_start_request(ThreadStartParams {
model: Some("mock-model".to_string()),
..Default::default()
})
.await?;
let response: JSONRPCResponse = timeout(
READ_TIMEOUT,
app_server.read_stream_until_response_message(RequestId::Integer(request_id)),
)
.await??;
let ThreadStartResponse { thread, .. } = to_response(response)?;
let request_id = app_server
.send_turn_start_request(TurnStartParams {
thread_id: thread.id,
input: vec![UserInput::Text {
text: format!("Use ${SKILL_NAME}"),
text_elements: Vec::new(),
}],
..Default::default()
})
.await?;
timeout(
READ_TIMEOUT,
app_server.read_stream_until_response_message(RequestId::Integer(request_id)),
)
.await??;
timeout(
READ_TIMEOUT,
app_server.read_stream_until_notification_message("turn/completed"),
)
.await??;
let host_request = response_mock
.requests()
.last()
.cloned()
.expect("host skill request should be captured");
let host_skill_fragments = host_request
.message_input_texts("user")
.into_iter()
.filter(|text| text.starts_with("<skill>"))
.collect::<Vec<_>>();
assert_eq!(1, host_skill_fragments.len());
let host_skill_fragment = host_skill_fragments
.first()
.expect("host skill instructions should be model-visible");
assert!(host_skill_fragment.contains(LOCAL_SKILL_MARKER));
assert!(!host_skill_fragment.contains(SKILL_MARKER));
Ok(())
}