mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
DevUI: Serialize workflow input as string to maintain conformance with OpenAI Responses format (#2021)
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
1aaf37dab8
commit
4201b9a122
@@ -182,7 +182,9 @@ internal sealed class ResponseInputJsonConverter : JsonConverter<ResponseInput>
|
||||
return messages is not null ? ResponseInput.FromMessages(messages) : null;
|
||||
}
|
||||
|
||||
throw new JsonException($"Unexpected token type for ResponseInput: {reader.TokenType}");
|
||||
throw new JsonException(
|
||||
"ResponseInput must be either a string or an array of messages. " +
|
||||
$"Objects are not supported. Received token type: {reader.TokenType}");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
+14
@@ -344,6 +344,20 @@ public sealed class OpenAIResponsesSerializationTests : ConformanceTestBase
|
||||
Assert.NotNull(request.Input);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialize_InvalidInputObject_ThrowsHelpfulException()
|
||||
{
|
||||
// Arrange
|
||||
const string Json = "{\"model\":\"gpt-4o-mini\",\"input\":{\"input\":\"testing!\"},\"stream\":true}";
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<JsonException>(() =>
|
||||
JsonSerializer.Deserialize(Json, OpenAIHostingJsonContext.Default.CreateResponse));
|
||||
|
||||
Assert.Contains("ResponseInput must be either a string or an array of messages", exception.Message);
|
||||
Assert.Contains("Objects are not supported", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialize_AllRequests_CanBeDeserialized()
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -747,7 +747,7 @@ class ApiClient {
|
||||
// Convert to OpenAI format - use metadata.entity_id for routing
|
||||
const openAIRequest: AgentFrameworkRequest = {
|
||||
metadata: { entity_id: workflowId }, // Entity ID in metadata for routing
|
||||
input: request.input_data || "", // Send dict directly, no stringification needed
|
||||
input: JSON.stringify(request.input_data || {}), // Serialize workflow input as JSON string
|
||||
stream: true,
|
||||
conversation: request.conversation_id, // Include conversation if present
|
||||
extra_body: request.checkpoint_id
|
||||
|
||||
@@ -238,6 +238,29 @@ def test_executor_parse_raw_falls_back_to_string():
|
||||
assert parsed == "hi there"
|
||||
|
||||
|
||||
def test_executor_parse_stringified_json_workflow_input():
|
||||
"""Stringified JSON workflow input (from frontend JSON.stringify) is correctly parsed."""
|
||||
from pydantic import BaseModel
|
||||
|
||||
class WorkflowInput(BaseModel):
|
||||
input: str
|
||||
metadata: dict | None = None
|
||||
|
||||
executor = AgentFrameworkExecutor(EntityDiscovery(None), MessageMapper())
|
||||
start_executor = _DummyStartExecutor(handlers={WorkflowInput: lambda *_: None})
|
||||
workflow = _DummyWorkflow(start_executor)
|
||||
|
||||
# Simulate frontend sending JSON.stringify({"input": "testing!", "metadata": {"key": "value"}})
|
||||
stringified_json = '{"input": "testing!", "metadata": {"key": "value"}}'
|
||||
|
||||
parsed = executor._parse_raw_workflow_input(workflow, stringified_json)
|
||||
|
||||
# Should parse into WorkflowInput object
|
||||
assert isinstance(parsed, WorkflowInput)
|
||||
assert parsed.input == "testing!"
|
||||
assert parsed.metadata == {"key": "value"}
|
||||
|
||||
|
||||
async def test_executor_handles_non_streaming_agent():
|
||||
"""Test executor can handle agents with only run() method (no run_stream)."""
|
||||
from agent_framework import AgentRunResponse, AgentThread, ChatMessage, Role, TextContent
|
||||
|
||||
Reference in New Issue
Block a user