Fix gateway workflow harness test and mock OpenAI request parsing

This commit is contained in:
Illia Polosukhin
2026-03-08 14:58:29 -07:00
parent 4d5ba6b7e0
commit 44bf5ce565
3 changed files with 56 additions and 20 deletions
+28 -14
View File
@@ -30,15 +30,11 @@ mod tests {
"name": "wf-ci-webhook-demo",
"description": "CI webhook workflow demo",
"trigger_type": "system_event",
"trigger": {
"source": "github",
"event_type": "issue.opened",
"filters": {"repository": "nearai/ironclaw"}
},
"event_source": "github",
"event_type": "issue.opened",
"event_filters": {"repository": "nearai/ironclaw"},
"action_type": "lightweight",
"action": {
"prompt": "Summarize webhook and report issue number"
}
"prompt": "Summarize webhook and report issue number"
}),
)]),
))
@@ -69,6 +65,30 @@ mod tests {
harness
.send_chat(&thread_id, "create workflow routine")
.await;
harness
.wait_for_turns(&thread_id, 1, Duration::from_secs(10))
.await;
let mut routine = None;
for _ in 0..30 {
routine = harness.routine_by_name("wf-ci-webhook-demo").await;
if routine.is_some() {
break;
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
let routine = if let Some(r) = routine {
r
} else {
let history_dbg = harness.history(&thread_id).await;
let started_dbg = harness.test_channel.tool_calls_started();
let requests_dbg = mock.requests().await;
panic!(
"routine not created; tool_calls_started={started_dbg:?}; history={history_dbg}; mock_requests={requests_dbg:?}"
);
};
let routine_id = routine["id"].as_str().expect("routine id missing");
harness.send_chat(&thread_id, "emit webhook event").await;
let history = harness
@@ -77,12 +97,6 @@ mod tests {
let turns = history["turns"].as_array().expect("turns array missing");
assert!(turns.len() >= 2, "expected at least 2 turns");
let routine = harness
.routine_by_name("wf-ci-webhook-demo")
.await
.expect("routine not created");
let routine_id = routine["id"].as_str().expect("routine id missing");
let runs_before = harness.routine_runs(routine_id).await;
let before_count = runs_before["runs"]
.as_array()
+1 -2
View File
@@ -17,8 +17,7 @@ use ironclaw::channels::web::server::{GatewayState, RateLimiter, start_server};
use ironclaw::channels::web::sse::SseManager;
use ironclaw::channels::web::ws::WsConnectionTracker;
use ironclaw::channels::{Channel, IncomingMessage, MessageStream};
use ironclaw::config::llm::RegistryProviderConfig;
use ironclaw::config::{Config, RoutineConfig};
use ironclaw::config::{Config, RegistryProviderConfig, RoutineConfig};
use ironclaw::context::ContextManager;
use ironclaw::db::Database;
use ironclaw::db::libsql::LibSqlBackend;
+27 -4
View File
@@ -198,15 +198,37 @@ async fn chat_completions_handler(
.and_then(|r| r.as_str())
.unwrap_or_default();
fn extract_text_content(msg: &Value) -> Option<String> {
let content = msg.get("content")?;
if let Some(s) = content.as_str() {
return Some(s.to_string());
}
if let Some(parts) = content.as_array() {
let mut out = String::new();
for part in parts {
if part.get("type").and_then(|v| v.as_str()) == Some("text")
&& let Some(text) = part.get("text").and_then(|v| v.as_str())
{
if !out.is_empty() {
out.push(' ');
}
out.push_str(text);
}
}
if !out.is_empty() {
return Some(out);
}
}
None
}
let latest_user = body
.pointer("/messages")
.and_then(|m| m.as_array())
.and_then(|arr| {
arr.iter().rev().find_map(|msg| {
if msg.get("role").and_then(|r| r.as_str()) == Some("user") {
msg.get("content")
.and_then(|c| c.as_str())
.map(ToOwned::to_owned)
extract_text_content(msg)
} else {
None
}
@@ -215,10 +237,11 @@ async fn chat_completions_handler(
.unwrap_or_default();
let selected = if last_role == "user" {
let latest_user_lower = latest_user.to_ascii_lowercase();
state
.rules
.iter()
.find(|r| latest_user.contains(&r.contains))
.find(|r| latest_user_lower.contains(&r.contains.to_ascii_lowercase()))
.map(|r| r.response.clone())
.unwrap_or_else(|| state.default_response.clone())
} else {