feat: expose structured context during execution

This commit is contained in:
lda
2026-09-05 00:16:25 +07:00 Verified
parent a519f5e2e4
commit 0c0dcbce49
7 changed files with 436 additions and 11 deletions
+12
View File
@@ -161,10 +161,22 @@ def _foreach_ancestor_ids(run: RunState, frame: ExecutionFrame) -> list[str]:
def finalize_run(workflow: Workflow, run: RunState) -> RunState:
if run.outcome is None:
run.outcome = "ok"
# Root workflow output keeps standard root facts consistent by projecting
# against the root frame's derived context rather than an empty mapping.
from wf_core.run_state import ROOT_FRAME_ID
from wf_core.runtime.ops.frames import frame_context_view
root_frame = run.frames.get(ROOT_FRAME_ID)
root_context: dict[str, Any] = (
dict(frame_context_view(run, root_frame).graph)
if root_frame is not None
else {}
)
run.output = project_output(
workflow,
run.state,
workflow_input=run.workflow_input,
context=root_context,
)
validate_payload_against_schema(
workflow.output_schema, run.output, "workflow output"
+2 -2
View File
@@ -23,7 +23,7 @@ from wf_core.runtime.lineage import (
scope_input_for_frame,
)
from wf_core.runtime.ops.flow import advance_frame, append_step_result_trace
from wf_core.runtime.ops.frames import frame_context_values
from wf_core.runtime.ops.frames import frame_context_view
from wf_core.runtime.ops.index import WorkflowIndex
from wf_core.runtime.ops.merges import ReducerDefinition
from wf_core.runtime.ops.overlays import state_view_for_frame
@@ -174,7 +174,7 @@ def _resolve_foreach_iterable(
str(step.over),
state=state_view_for_frame(run, frame),
workflow_input=scope_input_for_frame(run, frame),
context=frame_context_values(frame),
context=frame_context_view(run, frame).graph,
)
if not isinstance(iterable, list):
raise WorkflowExecutionError(
+2 -2
View File
@@ -14,7 +14,7 @@ from wf_core.run_state import (
)
from wf_core.runtime.lineage import scope_input_for_frame
from wf_core.runtime.ops.flow import append_trace
from wf_core.runtime.ops.frames import frame_context_values
from wf_core.runtime.ops.frames import frame_context_view
from wf_core.runtime.ops.interrupts import build_interrupt_request
from wf_core.runtime.ops.overlays import state_view_for_frame
@@ -75,7 +75,7 @@ def handle_interrupt_step(
frame_id=frame.id,
state=state_view_for_frame(run, frame),
workflow_input=scope_input_for_frame(run, frame),
context=frame_context_values(frame),
context=dict(frame_context_view(run, frame).graph),
public_frame_id=public_frame.id,
public_node_id=public_frame.node_id,
route=route,
+4 -2
View File
@@ -20,7 +20,7 @@ from wf_core.runtime.lineage import (
commit_foreach_aware_patch,
scope_input_for_frame,
)
from wf_core.runtime.ops.frames import frame_context_values
from wf_core.runtime.ops.frames import frame_context_view
from wf_core.runtime.ops.merges import ReducerDefinition
from wf_core.runtime.ops.overlays import state_view_for_frame
from wf_core.runtime.ops.schemas import validate_payload_against_schema
@@ -54,7 +54,8 @@ def _resolve_node_execution(
node_def: NodeDef,
platform: object | None = None,
) -> tuple[dict[str, Any], RuntimeContext, dict[str, Any]]:
context_values = frame_context_values(frame)
context_view = frame_context_view(run, frame)
context_values = context_view.graph
state_view = state_view_for_frame(run, frame)
resolved_input = resolve_step_input_bindings(
node.input,
@@ -76,6 +77,7 @@ def _resolve_node_execution(
prior_outcome=frame.prior_outcome,
activated_incoming_edge=frame.activated_incoming_edge,
metadata=dict(frame.metadata),
foreach=dict(context_view.foreach),
platform=platform,
)
return resolved_input, context, state_view