Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,42 @@ private static AIFunctionArguments ConvertToFunctionArguments(JsonElement? argum
return [];
}

if (arguments.Value.ValueKind != JsonValueKind.Object)
JsonDocument? parsedStringArguments = null;
var argumentElement = arguments.Value;

if (argumentElement.ValueKind == JsonValueKind.String)
{
throw new InvalidOperationException(
$"Inline skill scripts expect arguments as a JSON object but received a JSON element of kind '{arguments.Value.ValueKind}'.");
string? rawArguments = argumentElement.GetString();
try
{
parsedStringArguments = JsonDocument.Parse(rawArguments ?? string.Empty);
argumentElement = parsedStringArguments.RootElement;
}
catch (JsonException ex)
{
throw new InvalidOperationException("Inline skill scripts received arguments as a JSON string, but the string did not contain valid JSON.", ex);
}
}

var dict = new Dictionary<string, object?>();
foreach (var property in arguments.Value.EnumerateObject())
if (argumentElement.ValueKind != JsonValueKind.Object)
{
dict[property.Name] = property.Value;
throw new InvalidOperationException(
$"Inline skill scripts expect arguments as a JSON object but received a JSON element of kind '{argumentElement.ValueKind}'.");
}

return new AIFunctionArguments(dict);
try
{
var dict = new Dictionary<string, object?>();
foreach (var property in argumentElement.EnumerateObject())
{
dict[property.Name] = parsedStringArguments is null ? property.Value : property.Value.Clone();
}

return new AIFunctionArguments(dict);
}
finally
{
parsedStringArguments?.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,37 @@ public async Task RunAsync_WithParameters_PassesArgumentsAsync()
Assert.Equal(10, int.Parse(result?.ToString()!));
}

[Fact]
public async Task RunAsync_WithJsonStringObjectArguments_PassesArgumentsAsync()
{
// Arrange
var script = new AgentInlineSkillScript("add", (int a, int b) => a + b);
var skill = new AgentInlineSkill("calc-skill", "Calc.", "Instructions.");
using var argsDoc = JsonDocument.Parse("\"{\\\"a\\\":3,\\\"b\\\":7}\"");
var args = argsDoc.RootElement;

// Act
var result = await script.RunAsync(skill, args, null, CancellationToken.None);

// Assert
Assert.Equal(10, int.Parse(result?.ToString()!));
}

[Fact]
public async Task RunAsync_WithInvalidJsonStringArguments_ThrowsInvalidOperationExceptionAsync()
{
// Arrange
var script = new AgentInlineSkillScript("noop", () => "ok");
var skill = new AgentInlineSkill("test-skill", "Test.", "Instructions.");
using var argsDoc = JsonDocument.Parse("\"not json\"");
var args = argsDoc.RootElement;

// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
() => script.RunAsync(skill, args, null, CancellationToken.None));
Assert.Contains("did not contain valid JSON", ex.Message);
}

[Fact]
public void ParametersSchema_NoParameters_ReturnsSchema()
{
Expand Down