Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5e673da
Removing server-url from suggested Planner parameters
teresaqhoang May 3, 2023
0f82054
Merge branch 'main' into prohibit-planner-server-url-override
adrianwyatt May 3, 2023
7e8805e
removing ContainsKey check
teresaqhoang May 3, 2023
bdafba1
Merge branch 'prohibit-planner-server-url-override' of https://github…
teresaqhoang May 3, 2023
ad41431
Merge branch 'main' into prohibit-planner-server-url-override
adrianwyatt May 4, 2023
4790d1c
Merge branch 'main' into prohibit-planner-server-url-override
teresaqhoang May 4, 2023
67278c2
Merge branch 'main' into prohibit-planner-server-url-override
adrianwyatt May 4, 2023
5b95eb3
GitHub OpenAPI skill integration with planner (#792)
teresaqhoang May 4, 2023
0fb66c6
fixing default value bug
teresaqhoang May 4, 2023
ae35d1d
Merge branch 'main' into prohibit-planner-server-url-override
teresaqhoang May 4, 2023
37bbe07
Merge branch 'main' into prohibit-planner-server-url-override
teresaqhoang May 4, 2023
1ee0d71
Adding support for overriding server-url
teresaqhoang May 4, 2023
17cdfea
Updating other import methods
teresaqhoang May 4, 2023
d6d7f71
updating function calls
teresaqhoang May 4, 2023
8d46ae5
Reverting appsettings.json
teresaqhoang May 4, 2023
ab4c6f2
Merge branch 'main' into prohibit-planner-server-url-override
adrianwyatt May 5, 2023
5ac7a4d
Addressing comments
teresaqhoang May 5, 2023
fb488f4
Fix build breaks
adrianwyatt May 5, 2023
1478343
Update unit test with server-url
adrianwyatt May 5, 2023
7a52b46
Updated with PR comments
adrianwyatt May 5, 2023
5e8f0c3
dotnet format
adrianwyatt May 5, 2023
f977bf7
Fixup unit tests
adrianwyatt May 5, 2023
a382d56
Merge branch 'main' into prohibit-planner-server-url-override
adrianwyatt May 5, 2023
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 @@ -173,7 +173,7 @@ public string GoodExamples(string goal, SKContext context)
Parameter ""path"": Source file.
// Write a file.
FileIOSkill.WriteAsync
Parameter ""path"": Destination file.
Parameter ""path"": Destination file. (default value: sample.txt)
Parameter ""content"": File content.
// Get the current time.
TimeSkill.Time
Expand Down Expand Up @@ -208,7 +208,7 @@ public string EdgeCaseExamples(string goal, SKContext context)
No parameters.
// Write a file.
FileIOSkill.WriteAsync
Parameter ""path"": Destination file.
Parameter ""path"": Destination file. (default value: sample.txt)
Parameter ""content"": File content.
// Makes a POST request to a uri.
HttpSkill.PostAsync
Expand Down Expand Up @@ -254,7 +254,8 @@ private void PopulateList(StringBuilder list, IDictionary<string, List<FunctionV
foreach (var p in func.Parameters)
{
var description = string.IsNullOrEmpty(p.Description) ? p.Name : p.Description;
list.AppendLine($"Parameter \"{p.Name}\": {AddPeriod(description)}");
var defaultValueString = string.IsNullOrEmpty(p.DefaultValue) ? string.Empty : $" (default value: {p.DefaultValue})";
list.AppendLine($"Parameter \"{p.Name}\": {AddPeriod(description)} {defaultValueString}");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ internal sealed class RestApiOperation
/// <summary>
/// The server URL.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1056:URI-like properties should not be strings", Justification = "Having this property as a string can be useful for scenarios when AI creates an instance of the operation.")]
public string ServerUrl { get; }
public Uri? ServerUrl { get; }

/// <summary>
/// The operation headers.
Expand Down Expand Up @@ -81,10 +80,9 @@ internal sealed class RestApiOperation
/// <param name="parameters">The operation parameters.</param>
/// <param name="headers">The operation headers.</param>
/// <param name="payload">The operation payload.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1056:URI-like properties should not be strings", Justification = "Having this property as a string can be useful for scenarios when AI creates an instance of the operation.")]
public RestApiOperation(
string id,
string serverUrl,
Uri? serverUrl,
string path,
HttpMethod method,
string description,
Expand Down Expand Up @@ -113,13 +111,19 @@ public Uri BuildOperationUrl(IDictionary<string, string> arguments)

path = this.AddQueryString(path, arguments);

Uri serverUrl;

//Override defined server url - https://api.example.com/v1 by the one from arguments.
if (!arguments.TryGetValue(ServerUrlArgumentName, out var serverUrl))
if (arguments.TryGetValue(ServerUrlArgumentName, out string serverUrlString))
{
serverUrl = new Uri(serverUrlString);
}
else
{
serverUrl = this.ServerUrl;
serverUrl = this.ServerUrl ?? throw new InvalidOperationException($"Server url is not defined for operation {this.Id}");
}

return new Uri($"{serverUrl.TrimEnd('/')}/{path.TrimStart('/')}", UriKind.Absolute);
return new Uri(serverUrl, $"{path.TrimStart('/')}");
}

/// <summary>
Expand Down Expand Up @@ -151,12 +155,8 @@ public IDictionary<string, string> RenderHeaders(IDictionary<string, string> arg
}

//Getting metadata for the header
var headerMetadata = this.Parameters.FirstOrDefault(p => p.Location == RestApiOperationParameterLocation.Header && p.Name == headerName);
if (headerMetadata == null)
{
//No metadata found for the header.
throw new RestApiOperationException($"No value for the '{headerName} header is found.'");
}
var headerMetadata = this.Parameters.FirstOrDefault(p => p.Location == RestApiOperationParameterLocation.Header && p.Name == headerName)
?? throw new RestApiOperationException($"No value for the '{headerName} header is found.'");

//If parameter is required it's value should always be provided.
if (headerMetadata.IsRequired)
Expand Down Expand Up @@ -249,7 +249,7 @@ private string AddQueryString(string path, IDictionary<string, string> arguments
return string.IsNullOrEmpty(queryString) ? path : $"{path}?{queryString}";
}

private static readonly Regex s_urlParameterMatch = new Regex(@"\{([\w-]+)\}");
private static readonly Regex s_urlParameterMatch = new(@"\{([\w-]+)\}");

# endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public async Task ItCanRunCreateAndUpdateOperationsWithJsonPayloadSuccessfullyAs

var operation = new RestApiOperation(
"fake-id",
"https://fake-random-test-host",
new Uri("https://fake-random-test-host"),
"fake-path",
HttpMethod.Post,
"fake-description",
Expand All @@ -75,8 +75,10 @@ public async Task ItCanRunCreateAndUpdateOperationsWithJsonPayloadSuccessfullyAs
}
};

var arguments = new Dictionary<string, string>();
arguments.Add("payload", System.Text.Json.JsonSerializer.Serialize(payload));
var arguments = new Dictionary<string, string>
{
{ "payload", System.Text.Json.JsonSerializer.Serialize(payload) }
};

var sut = new RestApiOperationRunner(this._httpClient, this._authenticationHandlerMock.Object);

Expand Down Expand Up @@ -130,7 +132,7 @@ public async Task ItCanRunCreateAndUpdateOperationsWithPlainTextPayloadSuccessfu

var operation = new RestApiOperation(
"fake-id",
"https://fake-random-test-host",
new Uri("https://fake-random-test-host"),
"fake-path",
HttpMethod.Post,
"fake-description",
Expand All @@ -139,8 +141,10 @@ public async Task ItCanRunCreateAndUpdateOperationsWithPlainTextPayloadSuccessfu
payload
);

var arguments = new Dictionary<string, string>();
arguments.Add("payload", "fake-input-value");
var arguments = new Dictionary<string, string>
{
{ "payload", "fake-input-value" }
};

var sut = new RestApiOperationRunner(this._httpClient, this._authenticationHandlerMock.Object);

Expand Down Expand Up @@ -178,21 +182,25 @@ public async Task ItCanRunCreateAndUpdateOperationsWithPlainTextPayloadSuccessfu
public async Task ItShouldAddHeadersToHttpRequestAsync()
{
// Arrange
var headers = new Dictionary<string, string>();
headers.Add("fake-header", string.Empty);
var headers = new Dictionary<string, string>
{
{ "fake-header", string.Empty }
};

var operation = new RestApiOperation(
"fake-id",
"https://fake-random-test-host",
new Uri("https://fake-random-test-host"),
"fake-path",
HttpMethod.Get,
"fake-description",
new List<RestApiOperationParameter>(),
headers
);

var arguments = new Dictionary<string, string>();
arguments.Add("fake-header", "fake-header-value");
var arguments = new Dictionary<string, string>
{
{ "fake-header", "fake-header-value" }
};

var sut = new RestApiOperationRunner(this._httpClient, this._authenticationHandlerMock.Object);

Expand All @@ -210,21 +218,25 @@ public async Task ItShouldAddHeadersToHttpRequestAsync()
public async Task ItShouldAddUserAgentHeaderToHttpRequestIfConfiguredAsync()
{
// Arrange
var headers = new Dictionary<string, string>();
headers.Add("fake-header", string.Empty);
var headers = new Dictionary<string, string>
{
{ "fake-header", string.Empty }
};

var operation = new RestApiOperation(
"fake-id",
"https://fake-random-test-host",
new Uri("https://fake-random-test-host"),
"fake-path",
HttpMethod.Get,
"fake-description",
new List<RestApiOperationParameter>(),
headers
);

var arguments = new Dictionary<string, string>();
arguments.Add("fake-header", "fake-header-value");
var arguments = new Dictionary<string, string>
{
{ "fake-header", "fake-header-value" }
};

var sut = new RestApiOperationRunner(this._httpClient, this._authenticationHandlerMock.Object, "fake-user-agent");

Expand All @@ -247,7 +259,7 @@ public async Task ItShouldUsePayloadAndContentTypeArgumentsIfPayloadMetadataIsMi

var operation = new RestApiOperation(
"fake-id",
"https://fake-random-test-host",
new Uri("https://fake-random-test-host"),
"fake-path",
HttpMethod.Post,
"fake-description",
Expand All @@ -264,9 +276,11 @@ public async Task ItShouldUsePayloadAndContentTypeArgumentsIfPayloadMetadataIsMi
}
};

var arguments = new Dictionary<string, string>();
arguments.Add("payload", System.Text.Json.JsonSerializer.Serialize(payload));
arguments.Add("content-type", "application/json");
var arguments = new Dictionary<string, string>
{
{ "payload", System.Text.Json.JsonSerializer.Serialize(payload) },
{ "content-type", "application/json" }
};

var sut = new RestApiOperationRunner(this._httpClient, this._authenticationHandlerMock.Object);

Expand Down Expand Up @@ -321,8 +335,10 @@ private sealed class HttpMessageHandlerStub : DelegatingHandler

public HttpMessageHandlerStub()
{
this.ResponseToReturn = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
this.ResponseToReturn.Content = new StringContent("{}", Encoding.UTF8, MediaTypeNames.Application.Json);
this.ResponseToReturn = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
Content = new StringContent("{}", Encoding.UTF8, MediaTypeNames.Application.Json)
};
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Expand Down
Loading