feat: basic app add thought field

This commit is contained in:
Novice
2025-12-25 10:28:21 +08:00
parent 047ea8c143
commit 7fc25cafb2
12 changed files with 314 additions and 179 deletions

View File

@ -1,3 +1,4 @@
"""
Mark agent test modules as a package to avoid import name collisions.
"""

View File

@ -0,0 +1,48 @@
from unittest.mock import MagicMock
from core.app.apps.base_app_queue_manager import PublishFrom
from core.app.apps.workflow_app_runner import WorkflowBasedAppRunner
from core.workflow.graph_events import NodeRunStreamChunkEvent
from core.workflow.nodes import NodeType
class DummyQueueManager:
def __init__(self) -> None:
self.published = []
def publish(self, event, publish_from: PublishFrom) -> None:
self.published.append((event, publish_from))
def test_skip_empty_final_chunk() -> None:
queue_manager = DummyQueueManager()
runner = WorkflowBasedAppRunner(queue_manager=queue_manager, app_id="app")
empty_final_event = NodeRunStreamChunkEvent(
id="exec",
node_id="node",
node_type=NodeType.LLM,
selector=["node", "text"],
chunk="",
is_final=True,
)
runner._handle_event(workflow_entry=MagicMock(), event=empty_final_event)
assert queue_manager.published == []
normal_event = NodeRunStreamChunkEvent(
id="exec",
node_id="node",
node_type=NodeType.LLM,
selector=["node", "text"],
chunk="hi",
is_final=False,
)
runner._handle_event(workflow_entry=MagicMock(), event=normal_event)
assert len(queue_manager.published) == 1
published_event, publish_from = queue_manager.published[0]
assert publish_from == PublishFrom.APPLICATION_MANAGER
assert published_event.text == "hi"

View File

@ -6,6 +6,7 @@ from core.workflow.entities.tool_entities import ToolResultStatus
from core.workflow.enums import NodeType
from core.workflow.graph.graph import Graph
from core.workflow.graph_engine.response_coordinator.coordinator import ResponseStreamCoordinator
from core.workflow.graph_engine.response_coordinator.session import ResponseSession
from core.workflow.graph_events import (
ChunkType,
NodeRunStreamChunkEvent,
@ -13,6 +14,7 @@ from core.workflow.graph_events import (
ToolResult,
)
from core.workflow.nodes.base.entities import BaseNodeData
from core.workflow.nodes.base.template import Template, VariableSegment
from core.workflow.runtime import VariablePool
@ -186,3 +188,44 @@ class TestResponseCoordinatorObjectStreaming:
assert ("node1", "generation", "content") in children
assert ("node1", "generation", "tool_calls") in children
assert ("node1", "generation", "thought") in children
def test_special_selector_rewrites_to_active_response_node(self):
"""Ensure special selectors attribute streams to the active response node."""
graph = MagicMock(spec=Graph)
variable_pool = MagicMock(spec=VariablePool)
response_node = MagicMock()
response_node.id = "response_node"
response_node.node_type = NodeType.ANSWER
graph.nodes = {"response_node": response_node}
graph.root_node = response_node
coordinator = ResponseStreamCoordinator(variable_pool, graph)
coordinator.track_node_execution("response_node", "exec_resp")
coordinator._active_session = ResponseSession(
node_id="response_node",
template=Template(segments=[VariableSegment(selector=["sys", "foo"])]),
)
event = NodeRunStreamChunkEvent(
id="stream_1",
node_id="llm_node",
node_type=NodeType.LLM,
selector=["sys", "foo"],
chunk="hi",
is_final=True,
chunk_type=ChunkType.TEXT,
)
coordinator._stream_buffers[("sys", "foo")] = [event]
coordinator._stream_positions[("sys", "foo")] = 0
coordinator._closed_streams.add(("sys", "foo"))
events, is_complete = coordinator._process_variable_segment(VariableSegment(selector=["sys", "foo"]))
assert is_complete
assert len(events) == 1
rewritten = events[0]
assert rewritten.node_id == "response_node"
assert rewritten.id == "exec_resp"

View File

@ -146,3 +146,4 @@ def test_serialize_tool_call_strips_files_to_ids():
assert serialized["name"] == "do"
assert serialized["arguments"] == '{"a":1}'
assert serialized["output"] == "ok"