Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added AI related API support #249

Closed
wants to merge 1 commit into from
Closed
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
4 changes: 4 additions & 0 deletions src/main/java/com/crowdin/client/Client.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.crowdin.client;

import com.crowdin.client.ai.AiApi;
import com.crowdin.client.applications.ApplicationsApi;
import com.crowdin.client.bundles.BundlesApi;
import com.crowdin.client.clients.ClientsApi;
Expand Down Expand Up @@ -68,6 +69,7 @@ public class Client extends CrowdinApi {
private final NotificationsApi notificationsApi;
private final ApplicationsApi applicationsApi;
private final ClientsApi clientsApi;
private final AiApi aiApi;

public Client(Credentials credentials) {
super(credentials);
Expand Down Expand Up @@ -101,6 +103,7 @@ public Client(Credentials credentials) {
this.notificationsApi = new NotificationsApi(credentials);
this.applicationsApi = new ApplicationsApi(credentials);
this.clientsApi = new ClientsApi(credentials);
this.aiApi = new AiApi(credentials);
}

public Client(Credentials credentials, ClientConfig clientConfig) {
Expand Down Expand Up @@ -135,6 +138,7 @@ public Client(Credentials credentials, ClientConfig clientConfig) {
this.notificationsApi = new NotificationsApi(credentials, clientConfig);
this.applicationsApi = new ApplicationsApi(credentials, clientConfig);
this.clientsApi = new ClientsApi(credentials, clientConfig);
this.aiApi = new AiApi(credentials,clientConfig);
}

}
196 changes: 196 additions & 0 deletions src/main/java/com/crowdin/client/ai/AiApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package com.crowdin.client.ai;

import com.crowdin.client.ai.model.AddAiPromptRequest;
import com.crowdin.client.ai.model.AddAiProviderRequest;
import com.crowdin.client.ai.model.AiPrompt;
import com.crowdin.client.ai.model.AiPromptResponseList;
import com.crowdin.client.ai.model.AiPromptResponseObject;
import com.crowdin.client.ai.model.AiProvider;
import com.crowdin.client.ai.model.AiProviderModel;
import com.crowdin.client.ai.model.AiProviderModelResponseList;
import com.crowdin.client.ai.model.AiProviderResponseList;
import com.crowdin.client.ai.model.AiProviderResponseObject;
import com.crowdin.client.ai.model.AiProxyChatCompletionRequest;
import com.crowdin.client.ai.model.AiProxyChatCompletionResponse;
import com.crowdin.client.core.CrowdinApi;
import com.crowdin.client.core.http.HttpRequestConfig;
import com.crowdin.client.core.http.exceptions.HttpBadRequestException;
import com.crowdin.client.core.http.exceptions.HttpException;
import com.crowdin.client.core.model.ClientConfig;
import com.crowdin.client.core.model.Credentials;
import com.crowdin.client.core.model.PatchRequest;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;

import java.util.List;
import java.util.Map;
import java.util.Optional;

public class AiApi extends CrowdinApi {

public AiApi(Credentials credentials) {
super(credentials);
}

public AiApi(Credentials credentials, ClientConfig clientConfig) {
super(credentials, clientConfig);
}

/**
* @param userId User identifier
* @return list of Ai Prompts
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.ai.prompts.getMany" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseList<AiPrompt> listAiPrompts (Long userId, Long projectId, String action, Long limit, Integer offset) throws HttpException, HttpBadRequestException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public ResponseList<AiPrompt> listAiPrompts (Long userId, Long projectId, String action, Long limit, Integer offset) throws HttpException, HttpBadRequestException {
public ResponseList<AiPrompt> listAiPrompts(Long userId, Long projectId, String action, Long limit, Integer offset) throws HttpException, HttpBadRequestException {

Usually we don't put a space after the method name. Please fix this here and in other methods

Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"projectId", Optional.ofNullable(projectId),
"action", Optional.ofNullable(action),
"limit", Optional.ofNullable(limit),
"offset", Optional.ofNullable(offset)
);
AiPromptResponseList aiPromptResponseList = this.httpClient.get(this.url + "/users/" + userId + "/ai/prompts", new HttpRequestConfig(queryParams), AiPromptResponseList.class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Crowdin Enterprise version of these API endpoints has a different request URL (without the userId subpath)

https://developer.crowdin.com/enterprise/api/v2/#operation/api.ai.prompts.getMany

A similar situation existed in PR #242. Please consider the same approach in the current implementation.

return AiPromptResponseList.to(aiPromptResponseList);
}

/**
* @param userId user identifier
* @param request request object
* @return newly created Ai prompt
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.prompts.post" target="_blank"><b>API Documentation</b></a></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Crowdin Enterprise links

* </ul>
*/
public ResponseObject<AiPrompt> addAiPrompt (Long userId, AddAiPromptRequest request) throws HttpException, HttpBadRequestException {
AiPromptResponseObject aiPromptResponseObject = this.httpClient.post(this.url + "/users/" + userId + "/ai/prompts", request, new HttpRequestConfig(), AiPromptResponseObject.class);
return ResponseObject.of(aiPromptResponseObject.getData());
}

/**
* @param userId User identifier
* @return list of Ai Prompts
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.ai.prompts.getMany" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<AiPrompt> getAiPrompt (Long userId, Long aiPromptId) throws HttpException, HttpBadRequestException {
AiPromptResponseObject response = this.httpClient.get(this.url + "/users/" + userId + "/ai/prompts/" + aiPromptId, new HttpRequestConfig(), AiPromptResponseObject.class);
return ResponseObject.of(response.getData());
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change


/**
* @param userId user identifier
* @param aiPromptId ai prompt identifier
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.prompts.delete" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public void deleteAiPrompt (Long userId, Long aiPromptId) throws HttpException, HttpBadRequestException {
this.httpClient.delete(this.url + "/users/" + userId + "/ai/prompts/" + aiPromptId, new HttpRequestConfig(), Void.class);
}

/**
* @param userId user identifier
* @param aiPromptId ai prompt identifier
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.prompts.delete" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<AiPrompt> editAiPrompt (Long userId, Long aiPromptId, List<PatchRequest> request) throws HttpException, HttpBadRequestException {
AiPromptResponseObject response = this.httpClient.patch(this.url + "/users/" + userId + "/ai/prompts/" + aiPromptId, request, new HttpRequestConfig(), AiPromptResponseObject.class);
return ResponseObject.of(response.getData());
}

/**
* @param userId User identifier
* @return list of Ai Providers
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.ai.providers.getMany" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseList<AiProvider> listAiProviders (Long userId, Long limit, Integer offset) throws HttpException, HttpBadRequestException {
Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"limit", Optional.ofNullable(limit),
"offset", Optional.ofNullable(offset)
);
AiProviderResponseList response = this.httpClient.get(this.url + "/users/" + userId + "/ai/providers", new HttpRequestConfig(queryParams), AiProviderResponseList.class);
return AiProviderResponseList.to(response);
}

/**
* @param userId user identifier
* @return newly created Ai Provider
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.providers.post" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<AiProvider> addAiProvider (Long userId, AddAiProviderRequest request) throws HttpException, HttpBadRequestException {
AiProviderResponseObject aiProviderResponseObject = this.httpClient.post(this.url + "/users/" + userId + "/ai/providers", request, new HttpRequestConfig(), AiProviderResponseObject.class);
return ResponseObject.of(aiProviderResponseObject.getData());
}

/**
* @param userId User identifier
* @param aiProviderId Ai Provider Identifier
* @return list of Ai Prompts
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.providers.get" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<AiProvider> getAiProvider (Long userId, Long aiProviderId) throws HttpException, HttpBadRequestException {
AiProviderResponseObject response = this.httpClient.get(this.url + "/users/" + userId + "/ai/providers" + aiProviderId, new HttpRequestConfig(), AiProviderResponseObject.class);
return ResponseObject.of(response.getData());
}

/**
* @param userId user identifier
* @param aiProviderId Ai Provider Identifier
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.providers.delete" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public void deleteAiProvider (Long userId, Long aiProviderId) throws HttpException, HttpBadRequestException {
this.httpClient.delete(this.url + "/users/" + userId + "/ai/providers/" + aiProviderId, new HttpRequestConfig(), Void.class);
}

/**
* @param userId user identifier
* @param aiProviderId ai prompt identifier
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.prompts.delete" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<AiProvider> editAiProvider (Long userId, Long aiProviderId, List<PatchRequest> request) throws HttpException, HttpBadRequestException {
AiProviderResponseObject response = this.httpClient.patch(this.url + "/users/" + userId + "/ai/providers/" + aiProviderId, request, new HttpRequestConfig(), AiProviderResponseObject.class);
return ResponseObject.of(response.getData());
}


/**
* @param userId User identifier
* @param aiProviderId ai prompt identifier
* @return list of Ai Provider Models
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.ai.providers.models.getMany" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public ResponseList<AiProviderModel> listAiProviderModels (Long userId, Long aiProviderId) throws HttpException, HttpBadRequestException {
AiProviderModelResponseList response = this.httpClient.get(this.url + "/users/" + userId + "/ai/providers" + aiProviderId + "/models", new HttpRequestConfig(), AiProviderModelResponseList.class);
return AiProviderModelResponseList.to(response);
}

/**
* @param userId user identifier
* @param aiProviderId ai prompt identifier
* @param request request object
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.providers.chat.completions.post" target="_blank"><b>API Documentation</b></a></li>
* </ul>
*/
public AiProxyChatCompletionResponse createAiProxyChatCompletion (Long userId, Long aiProviderId, AiProxyChatCompletionRequest request) throws HttpException, HttpBadRequestException {
AiProxyChatCompletionResponse aiProxyChatCompletionResponse = this.httpClient.post(this.url + "/users/" + userId + "/ai/providers" + aiProviderId + "/chat/completions", request, new HttpRequestConfig(), AiProxyChatCompletionResponse.class);
return aiProxyChatCompletionResponse;
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/AddAiPromptRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.crowdin.client.ai.model;

import lombok.Data;

import java.util.List;

@Data
public class AddAiPromptRequest {
private String name;
private String action;
private long aiProviderId;
private String aiModelId;
private boolean isEnabled;
private List<Long> enabledProjectIds;
private Config config;

@Data
private static class Config {
private String mode;
private String companyDescription;
private String projectDescription;
private String audienceDescription;
private OtherLanguageTranslations otherLanguageTranslations;
private boolean glossaryTerms;
private boolean tmSuggestions;
private boolean fileContent;
private boolean fileContext;
private boolean publicProjectDescription;

@Data
private static class OtherLanguageTranslations {
private boolean isEnabled;
private List<String> languageIds;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.crowdin.client.ai.model;

import lombok.Data;

import java.util.List;

@Data
public class AddAiProviderRequest {
private String name;
private String type;
private Credentials credentials;
private Config config;
private boolean isEnabled;
private boolean useSystemCredentials;

@Data
private static class Credentials {
private String apiKey;
}

@Data
private static class Config {
private List<Config.ActionRule> actionRules;

@Data
private static class ActionRule {
private String action;
private List<String> availableAiModelIds;
}
}
}
39 changes: 39 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/AiPrompt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.crowdin.client.ai.model;

import lombok.Data;

import java.util.List;

@Data
public class AiPrompt {
private long id;
private String name;
private String action;
private long aiProviderId;
private String aiModelId;
private boolean isEnabled;
private List<Long> enabledProjectIds;
private Config config;
private String createdAt;
private String updatedAt;

@Data
private static class Config {
private String mode;
private String companyDescription;
private String projectDescription;
private String audienceDescription;
private OtherLanguageTranslations otherLanguageTranslations;
private boolean glossaryTerms;
private boolean tmSuggestions;
private boolean fileContent;
private boolean fileContext;
private boolean publicProjectDescription;

@Data
private static class OtherLanguageTranslations {
private boolean isEnabled;
private List<String> languageIds;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.crowdin.client.ai.model;

import com.crowdin.client.core.model.Pagination;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;

@Data
public class AiPromptResponseList {
private List<AiPromptResponseObject> data;
private Pagination pagination;

public static ResponseList<AiPrompt> to (AiPromptResponseList aiPromptResponseList) {
return ResponseList.of(
aiPromptResponseList.getData().stream()
.map(AiPromptResponseObject::getData)
.map(ResponseObject::of)
.collect(Collectors.toList()),
aiPromptResponseList.getPagination()
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.crowdin.client.ai.model;

import lombok.Data;

@Data
public class AiPromptResponseObject {
private AiPrompt data;
}

Loading