fix(wfe-core): resolve .outputs. paths flat and pass empty object to child workflows

This commit is contained in:
2026-03-26 23:18:48 +00:00
parent f0cc531ada
commit ed38caecec
2 changed files with 27 additions and 4 deletions

View File

@@ -92,11 +92,28 @@ fn resolve_field_path<'a>(
} }
let segments: Vec<&str> = path.split('.').collect(); let segments: Vec<&str> = path.split('.').collect();
// Try resolving the full path first (for nested data like {"outputs": {"x": 1}}).
// If the first segment is "outputs"/"inputs" and doesn't exist as a key,
// strip it and resolve flat (for workflow data where outputs merge flat).
if segments.len() >= 2
&& (segments[0] == "outputs" || segments[0] == "inputs")
&& data.get(segments[0]).is_none()
{
return walk_segments(&segments[1..], data);
}
walk_segments(&segments, data)
}
fn walk_segments<'a>(
segments: &[&str],
data: &'a serde_json::Value,
) -> Result<&'a serde_json::Value, EvalError> {
let mut current = data; let mut current = data;
for segment in &segments { for segment in segments {
if let Ok(idx) = segment.parse::<usize>() { if let Ok(idx) = segment.parse::<usize>() {
// Try array index access.
match current.as_array() { match current.as_array() {
Some(arr) => { Some(arr) => {
current = arr.get(idx).ok_or(EvalError::FieldNotPresent)?; current = arr.get(idx).ok_or(EvalError::FieldNotPresent)?;
@@ -106,7 +123,6 @@ fn resolve_field_path<'a>(
} }
} }
} else { } else {
// Object field access.
match current.as_object() { match current.as_object() {
Some(obj) => { Some(obj) => {
current = obj.get(*segment).ok_or(EvalError::FieldNotPresent)?; current = obj.get(*segment).ok_or(EvalError::FieldNotPresent)?;

View File

@@ -110,8 +110,15 @@ impl StepBody for SubWorkflowStep {
) )
})?; })?;
// Use inputs if set, otherwise pass an empty object so the child
// workflow has a valid JSON object for storing step outputs.
let child_data = if self.inputs.is_null() {
serde_json::json!({})
} else {
self.inputs.clone()
};
let child_instance_id = host let child_instance_id = host
.start_workflow(&self.workflow_id, self.version, self.inputs.clone()) .start_workflow(&self.workflow_id, self.version, child_data)
.await?; .await?;
Ok(ExecutionResult::wait_for_event( Ok(ExecutionResult::wait_for_event(