Skip to content

Commit 9661450

Browse files
feat: Support AI Studio API (box/box-codegen#626) (#409)
1 parent 1af0a6a commit 9661450

File tree

45 files changed

+1614
-15
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1614
-15
lines changed

.codegen.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "c1e6fc8", "specHash": "59747aa", "version": "1.6.0" }
1+
{ "engineHash": "8a9cc1d", "specHash": "f20ba3f", "version": "1.6.0" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using Box.Sdk.Gen.Internal;
3+
using System;
4+
using System.Collections.ObjectModel;
5+
using System.Collections.Generic;
6+
using Box.Sdk.Gen;
7+
using Box.Sdk.Gen.Schemas;
8+
using Box.Sdk.Gen.Managers;
9+
10+
namespace Box.Sdk.Gen.Tests.Integration {
11+
[TestClass]
12+
public class AiStudioManagerTests {
13+
public BoxClient client { get; }
14+
15+
public AiStudioManagerTests() {
16+
client = new CommonsManager().GetDefaultClient();
17+
}
18+
[TestMethod]
19+
public async System.Threading.Tasks.Task TestAiStudioCrud() {
20+
string agentName = Utils.GetUUID();
21+
AiSingleAgentResponseFull createdAgent = await client.AiStudio.CreateAiAgentAsync(requestBody: new CreateAiAgent(name: agentName, accessState: "enabled") { Ask = new AiStudioAgentAsk(accessState: "enabled", description: "desc1") });
22+
Assert.IsTrue(createdAgent.Name == agentName);
23+
AiMultipleAgentResponse agents = await client.AiStudio.GetAiAgentsAsync();
24+
int numAgents = agents.Entries.Count;
25+
Assert.IsTrue(StringUtils.ToStringRepresentation(agents.Entries[0].Type?.Value) == "ai_agent");
26+
AiSingleAgentResponseFull retrievedAgent = await client.AiStudio.GetAiAgentByIdAsync(agentId: createdAgent.Id, queryParams: new GetAiAgentByIdQueryParams() { Fields = Array.AsReadOnly(new [] {"ask"}) });
27+
Assert.IsTrue(retrievedAgent.Name == agentName);
28+
Assert.IsTrue(StringUtils.ToStringRepresentation(retrievedAgent.AccessState) == "enabled");
29+
Assert.IsTrue(StringUtils.ToStringRepresentation(NullableUtils.Unwrap(retrievedAgent.Ask).AccessState) == "enabled");
30+
Assert.IsTrue(NullableUtils.Unwrap(retrievedAgent.Ask).Description == "desc1");
31+
AiSingleAgentResponseFull updatedAgent = await client.AiStudio.UpdateAiAgentByIdAsync(agentId: createdAgent.Id, requestBody: new CreateAiAgent(name: agentName, accessState: "enabled") { Ask = new AiStudioAgentAsk(accessState: "disabled", description: "desc2") });
32+
Assert.IsTrue(StringUtils.ToStringRepresentation(updatedAgent.AccessState) == "enabled");
33+
Assert.IsTrue(StringUtils.ToStringRepresentation(NullableUtils.Unwrap(updatedAgent.Ask).AccessState) == "disabled");
34+
Assert.IsTrue(NullableUtils.Unwrap(updatedAgent.Ask).Description == "desc2");
35+
await client.AiStudio.DeleteAiAgentByIdAsync(agentId: createdAgent.Id);
36+
AiMultipleAgentResponse agentsAfterDelete = await client.AiStudio.GetAiAgentsAsync();
37+
Assert.IsTrue(agentsAfterDelete.Entries.Count == numAgents - 1);
38+
}
39+
40+
[TestMethod]
41+
public async System.Threading.Tasks.Task TestUseAiAgentReferenceInAiAsk() {
42+
string agentName = Utils.GetUUID();
43+
AiSingleAgentResponseFull createdAgent = await client.AiStudio.CreateAiAgentAsync(requestBody: new CreateAiAgent(name: agentName, accessState: "enabled") { Ask = new AiStudioAgentAsk(accessState: "enabled", description: "desc1") });
44+
FileFull fileToAsk = await new CommonsManager().UploadNewFileAsync();
45+
AiResponseFull? response = await client.Ai.CreateAiAskAsync(requestBody: new AiAsk(mode: AiAskModeField.SingleItemQa, prompt: "which direction sun rises", items: Array.AsReadOnly(new [] {new AiItemAsk(id: fileToAsk.Id, type: AiItemAskTypeField.File) { Content = "Sun rises in the East" }})) { AiAgent = new AiAgentReference() { Id = createdAgent.Id } });
46+
Assert.IsTrue(NullableUtils.Unwrap(response).Answer.Contains("East"));
47+
Assert.IsTrue(NullableUtils.Unwrap(response).CompletionReason == "done");
48+
Assert.IsTrue(NullableUtils.Unwrap(NullableUtils.Unwrap(NullableUtils.Unwrap(response).AiAgentInfo).Models).Count > 0);
49+
await client.Files.DeleteFileByIdAsync(fileId: fileToAsk.Id);
50+
await client.AiStudio.DeleteAiAgentByIdAsync(agentId: createdAgent.Id);
51+
}
52+
53+
}
54+
}

Box.Sdk.Gen/Client/BoxClient.cs

+3
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ public class BoxClient : IBoxClient {
149149

150150
public IAiManager Ai { get; }
151151

152+
public IAiStudioManager AiStudio { get; }
153+
152154
public IDocgenTemplateManager DocgenTemplate { get; }
153155

154156
public IDocgenManager Docgen { get; }
@@ -226,6 +228,7 @@ public BoxClient(IAuthentication auth, NetworkSession? networkSession = default)
226228
SignTemplates = new SignTemplatesManager(networkSession: this.NetworkSession) { Auth = this.Auth };
227229
IntegrationMappings = new IntegrationMappingsManager(networkSession: this.NetworkSession) { Auth = this.Auth };
228230
Ai = new AiManager(networkSession: this.NetworkSession) { Auth = this.Auth };
231+
AiStudio = new AiStudioManager(networkSession: this.NetworkSession) { Auth = this.Auth };
229232
DocgenTemplate = new DocgenTemplateManager(networkSession: this.NetworkSession) { Auth = this.Auth };
230233
Docgen = new DocgenManager(networkSession: this.NetworkSession) { Auth = this.Auth };
231234
}

Box.Sdk.Gen/Client/IBoxClient.cs

+2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ public interface IBoxClient {
147147

148148
public IAiManager Ai { get => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it."); }
149149

150+
public IAiStudioManager AiStudio { get => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it."); }
151+
150152
public IDocgenTemplateManager DocgenTemplate { get => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it."); }
151153

152154
public IDocgenManager Docgen { get => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it."); }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class AiStudioManager : IAiStudioManager {
10+
public IAuthentication? Auth { get; init; }
11+
12+
public NetworkSession NetworkSession { get; }
13+
14+
public AiStudioManager(NetworkSession? networkSession = default) {
15+
NetworkSession = networkSession ?? new NetworkSession();
16+
}
17+
/// <summary>
18+
/// Lists AI agents based on the provided parameters.
19+
/// </summary>
20+
/// <param name="queryParams">
21+
/// Query parameters of getAiAgents method
22+
/// </param>
23+
/// <param name="headers">
24+
/// Headers of getAiAgents method
25+
/// </param>
26+
/// <param name="cancellationToken">
27+
/// Token used for request cancellation.
28+
/// </param>
29+
public async System.Threading.Tasks.Task<AiMultipleAgentResponse> GetAiAgentsAsync(GetAiAgentsQueryParams? queryParams = default, GetAiAgentsHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
30+
queryParams = queryParams ?? new GetAiAgentsQueryParams();
31+
headers = headers ?? new GetAiAgentsHeaders();
32+
Dictionary<string, string> queryParamsMap = Utils.PrepareParams(map: new Dictionary<string, string?>() { { "mode", StringUtils.ToStringRepresentation(queryParams.Mode) }, { "fields", StringUtils.ToStringRepresentation(queryParams.Fields) }, { "agent_state", StringUtils.ToStringRepresentation(queryParams.AgentState) }, { "include_box_default", StringUtils.ToStringRepresentation(queryParams.IncludeBoxDefault) }, { "marker", StringUtils.ToStringRepresentation(queryParams.Marker) }, { "limit", StringUtils.ToStringRepresentation(queryParams.Limit) } });
33+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
34+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/ai_agents"), method: "GET", responseFormat: Box.Sdk.Gen.ResponseFormat.Json) { Parameters = queryParamsMap, Headers = headersMap, Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken }).ConfigureAwait(false);
35+
return SimpleJsonSerializer.Deserialize<AiMultipleAgentResponse>(NullableUtils.Unwrap(response.Data));
36+
}
37+
38+
/// <summary>
39+
/// Creates an AI agent. At least one of the following capabilities must be provided: `ask`, `text_gen`, `extract`.
40+
/// </summary>
41+
/// <param name="requestBody">
42+
/// Request body of createAiAgent method
43+
/// </param>
44+
/// <param name="headers">
45+
/// Headers of createAiAgent method
46+
/// </param>
47+
/// <param name="cancellationToken">
48+
/// Token used for request cancellation.
49+
/// </param>
50+
public async System.Threading.Tasks.Task<AiSingleAgentResponseFull> CreateAiAgentAsync(CreateAiAgent requestBody, CreateAiAgentHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
51+
headers = headers ?? new CreateAiAgentHeaders();
52+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
53+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/ai_agents"), method: "POST", contentType: "application/json", responseFormat: Box.Sdk.Gen.ResponseFormat.Json) { Headers = headersMap, Data = SimpleJsonSerializer.Serialize(requestBody), Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken }).ConfigureAwait(false);
54+
return SimpleJsonSerializer.Deserialize<AiSingleAgentResponseFull>(NullableUtils.Unwrap(response.Data));
55+
}
56+
57+
/// <summary>
58+
/// Updates an AI agent.
59+
/// </summary>
60+
/// <param name="agentId">
61+
/// The ID of the agent to update.
62+
/// Example: "1234"
63+
/// </param>
64+
/// <param name="requestBody">
65+
/// Request body of updateAiAgentById method
66+
/// </param>
67+
/// <param name="headers">
68+
/// Headers of updateAiAgentById method
69+
/// </param>
70+
/// <param name="cancellationToken">
71+
/// Token used for request cancellation.
72+
/// </param>
73+
public async System.Threading.Tasks.Task<AiSingleAgentResponseFull> UpdateAiAgentByIdAsync(string agentId, CreateAiAgent requestBody, UpdateAiAgentByIdHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
74+
headers = headers ?? new UpdateAiAgentByIdHeaders();
75+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
76+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/ai_agents/", StringUtils.ToStringRepresentation(agentId)), method: "PUT", contentType: "application/json", responseFormat: Box.Sdk.Gen.ResponseFormat.Json) { Headers = headersMap, Data = SimpleJsonSerializer.Serialize(requestBody), Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken }).ConfigureAwait(false);
77+
return SimpleJsonSerializer.Deserialize<AiSingleAgentResponseFull>(NullableUtils.Unwrap(response.Data));
78+
}
79+
80+
/// <summary>
81+
/// Gets an AI Agent using the `agent_id` parameter.
82+
/// </summary>
83+
/// <param name="agentId">
84+
/// The agent id to get.
85+
/// Example: "1234"
86+
/// </param>
87+
/// <param name="queryParams">
88+
/// Query parameters of getAiAgentById method
89+
/// </param>
90+
/// <param name="headers">
91+
/// Headers of getAiAgentById method
92+
/// </param>
93+
/// <param name="cancellationToken">
94+
/// Token used for request cancellation.
95+
/// </param>
96+
public async System.Threading.Tasks.Task<AiSingleAgentResponseFull> GetAiAgentByIdAsync(string agentId, GetAiAgentByIdQueryParams? queryParams = default, GetAiAgentByIdHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
97+
queryParams = queryParams ?? new GetAiAgentByIdQueryParams();
98+
headers = headers ?? new GetAiAgentByIdHeaders();
99+
Dictionary<string, string> queryParamsMap = Utils.PrepareParams(map: new Dictionary<string, string?>() { { "fields", StringUtils.ToStringRepresentation(queryParams.Fields) } });
100+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
101+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/ai_agents/", StringUtils.ToStringRepresentation(agentId)), method: "GET", responseFormat: Box.Sdk.Gen.ResponseFormat.Json) { Parameters = queryParamsMap, Headers = headersMap, Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken }).ConfigureAwait(false);
102+
return SimpleJsonSerializer.Deserialize<AiSingleAgentResponseFull>(NullableUtils.Unwrap(response.Data));
103+
}
104+
105+
/// <summary>
106+
/// Deletes an AI agent using the provided parameters.
107+
/// </summary>
108+
/// <param name="agentId">
109+
/// The ID of the agent to delete.
110+
/// Example: "1234"
111+
/// </param>
112+
/// <param name="headers">
113+
/// Headers of deleteAiAgentById method
114+
/// </param>
115+
/// <param name="cancellationToken">
116+
/// Token used for request cancellation.
117+
/// </param>
118+
public async System.Threading.Tasks.Task DeleteAiAgentByIdAsync(string agentId, DeleteAiAgentByIdHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
119+
headers = headers ?? new DeleteAiAgentByIdHeaders();
120+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
121+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/ai_agents/", StringUtils.ToStringRepresentation(agentId)), method: "DELETE", responseFormat: Box.Sdk.Gen.ResponseFormat.NoContent) { Headers = headersMap, Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken }).ConfigureAwait(false);
122+
}
123+
124+
}
125+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class CreateAiAgentHeaders {
10+
/// <summary>
11+
/// Extra headers that will be included in the HTTP request.
12+
/// </summary>
13+
public Dictionary<string, string?> ExtraHeaders { get; }
14+
15+
public CreateAiAgentHeaders(Dictionary<string, string?>? extraHeaders = default) {
16+
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class DeleteAiAgentByIdHeaders {
10+
/// <summary>
11+
/// Extra headers that will be included in the HTTP request.
12+
/// </summary>
13+
public Dictionary<string, string?> ExtraHeaders { get; }
14+
15+
public DeleteAiAgentByIdHeaders(Dictionary<string, string?>? extraHeaders = default) {
16+
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class GetAiAgentByIdHeaders {
10+
/// <summary>
11+
/// Extra headers that will be included in the HTTP request.
12+
/// </summary>
13+
public Dictionary<string, string?> ExtraHeaders { get; }
14+
15+
public GetAiAgentByIdHeaders(Dictionary<string, string?>? extraHeaders = default) {
16+
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class GetAiAgentByIdQueryParams {
10+
/// <summary>
11+
/// The fields to return in the response.
12+
/// </summary>
13+
public IReadOnlyList<string>? Fields { get; init; }
14+
15+
public GetAiAgentByIdQueryParams() {
16+
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class GetAiAgentsHeaders {
10+
/// <summary>
11+
/// Extra headers that will be included in the HTTP request.
12+
/// </summary>
13+
public Dictionary<string, string?> ExtraHeaders { get; }
14+
15+
public GetAiAgentsHeaders(Dictionary<string, string?>? extraHeaders = default) {
16+
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Box.Sdk.Gen;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Generic;
5+
using Box.Sdk.Gen.Internal;
6+
using Box.Sdk.Gen.Schemas;
7+
8+
namespace Box.Sdk.Gen.Managers {
9+
public class GetAiAgentsQueryParams {
10+
/// <summary>
11+
/// The mode to filter the agent config to return. Possible values are: `ask`, `text_gen`, and `extract`.
12+
/// </summary>
13+
public IReadOnlyList<string>? Mode { get; init; }
14+
15+
/// <summary>
16+
/// The fields to return in the response.
17+
/// </summary>
18+
public IReadOnlyList<string>? Fields { get; init; }
19+
20+
/// <summary>
21+
/// The state of the agents to return. Possible values are: `enabled`, `disabled` and `enabled_for_selected_users`.
22+
/// </summary>
23+
public IReadOnlyList<string>? AgentState { get; init; }
24+
25+
/// <summary>
26+
/// Whether to include the Box default agents in the response.
27+
/// </summary>
28+
public bool? IncludeBoxDefault { get; init; }
29+
30+
/// <summary>
31+
/// Defines the position marker at which to begin returning results.
32+
/// </summary>
33+
public string? Marker { get; init; }
34+
35+
/// <summary>
36+
/// The maximum number of items to return per page.
37+
/// </summary>
38+
public long? Limit { get; init; }
39+
40+
public GetAiAgentsQueryParams() {
41+
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)