feat(workflow): support single-node execution and MCP Streamable HTTP protocol

- Add `run_single_node` method in workflow service for isolated node execution
- Refactor MCP client to support Streamable HTTP protocol (2025-03-26) with session ID handling, SSE/JSON response parsing, and proper initialized notification
- Update iteration node to conditionally initialize stream writer based on stream flag
- Improve cycle graph node invocation with checkpoint config passing
This commit is contained in:
Timebomb2018
2026-05-07 17:18:21 +08:00
parent 595c3517e3
commit 8d3da2fd0e
7 changed files with 302 additions and 28 deletions

View File

@@ -70,7 +70,7 @@ class IterationRuntime:
self.variable_pool = variable_pool
self.cycle_nodes = cycle_nodes
self.cycle_edges = cycle_edges
self.event_write = get_stream_writer()
self.event_write = get_stream_writer() if self.stream else (lambda x: None)
self.output_value = None
self.result: list = []
@@ -196,7 +196,7 @@ class IterationRuntime:
})
result = graph.get_state(config=checkpoint).values
else:
result = await graph.ainvoke(init_state)
result = await graph.ainvoke(init_state, config=checkpoint)
output = child_pool.get_value(self.output_value)
stopped = result["looping"] == 2

View File

@@ -57,7 +57,7 @@ class LoopRuntime:
self.looping = True
self.variable_pool = variable_pool
self.child_variable_pool = child_variable_pool
self.event_write = get_stream_writer()
self.event_write = get_stream_writer() if self.stream else (lambda x: None)
self.checkpoint = RunnableConfig(
configurable={
@@ -223,7 +223,7 @@ class LoopRuntime:
})
return self.graph.get_state(config=self.checkpoint).values
else:
return await self.graph.ainvoke(loopstate)
return await self.graph.ainvoke(loopstate, config=self.checkpoint)
async def run(self):
"""

View File

@@ -385,6 +385,7 @@ class HttpRequestNode(BaseNode):
logger.info(f"Node {self.node_id}: HTTP request succeeded")
response = HttpResponse(resp)
# Build raw request summary for process_data
await resp.request.aread()
raw_request = (
f"{self.typed_config.method.upper()} {resp.request.url} HTTP/1.1\r\n"
+ "".join(f"{k}: {v}\r\n" for k, v in resp.request.headers.items())