Added My Anime List API wrapper

for documentation on MAL API check out the [API docs](https://myanimelist.net/apiconfig/references/api/v2)

Display:Display.java
- Switched the AI model to `qwen3:8b`
- some temporary test changes
- switched to using static references when supposed too

MALAPITool
- Module for handling the MAL API

MALAPITool:README.md
- Some general information about the tools

Started adding some base systems for finding API endpoints, will later be added to the API module for the ability to add plugins

.gitignore
- Added so all data folder are ignored. So submodules data folder from testing aren't added to git

Core:OllamaObject.java
- switched location of messages.json from the static location of `./cache/` to the dynamic location of `${Core.DATA_DIR}/messages.json`

Core:OllamaPerameter.java
- Added ENUM and ARRAY values. Incidentally also discover that Ollama supports more than just STRING, INT, and BOOLEAN ad parameters

Core:Core.java
- Added precluding day to the name of logging files, now using the format dd_HH-mm-ss
This commit is contained in:
2025-05-23 15:24:58 +02:00
parent 58c23c5897
commit 5c3efa1376
19 changed files with 678 additions and 18 deletions

2
.gitignore vendored
View File

@@ -44,5 +44,5 @@ bin/
/pythonFiles/
/messages/
/logs/
/data/
data
/cache/

1
.idea/gradle.xml generated
View File

@@ -12,6 +12,7 @@
<option value="$PROJECT_DIR$/API" />
<option value="$PROJECT_DIR$/Core" />
<option value="$PROJECT_DIR$/Display" />
<option value="$PROJECT_DIR$/MALAPITool" />
<option value="$PROJECT_DIR$/launcher" />
</set>
</option>

2
.idea/vcs.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -160,7 +160,7 @@ public class Core {
logWriter.close();
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH-mm-ss");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd_HH-mm-ss");
File messagesFile = new File("./messages/"+now.format(formatter)+".json");
@@ -175,7 +175,7 @@ public class Core {
messagesWriter.write(messages.toString());
messagesWriter.close();
File f = new File("./cache/messages.json");
File f = new File("./data/messages.json");
if(f.exists())
{
f.delete();
@@ -236,12 +236,26 @@ public class Core {
/**
* Adds a new tool to the System
* @param funtionTool The tool to add
* @param functionTool The tool to add
* @param source The source of the tool
*/
public void addTool(OllamaFunctionTool funtionTool, @MagicConstant(valuesFromClass = Core.Source.class) String source) {
funtionTools.add(new Pair<>(funtionTool, source));
ollamaObject.addTool(funtionTool);
public void addTool(OllamaFunctionTool functionTool, @MagicConstant(valuesFromClass = Source.class) String source) {
funtionTools.add(new Pair<>(functionTool, source));
ollamaObject.addTool(functionTool);
}
/**
* Adds a list of tools to the System
* @param tools The tools to add
*/
@SuppressWarnings("MagicConstant")
public void addTools(OllamaFunctionTools tools)
{
for(Pair<OllamaFunctionTool, String> tool : tools)
{
addTool(tool.getKey(), tool.getValue());
}
}
/**
@@ -324,6 +338,7 @@ public class Core {
throw new RuntimeException("HTTP Response code - " + responseCode);
}
} catch (IOException e) {
// System.err.println("Error: JSON: "+);
throw new RuntimeException(e);
}
}

View File

@@ -0,0 +1,111 @@
package me.zacharias.chat.ollama;
import me.zacharias.chat.core.Core;
import me.zacharias.chat.core.Pair;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;
public class OllamaFunctionTools implements Iterable<Pair<OllamaFunctionTool, String>> {
/**
* A list of tools for the OllamaObject.
* OPS! Shuld only be ussed to add a set of tools to the OllamaObject, not to be used for storage of tools internaly or externaly
*/
private ArrayList<OllamaFunctionTool> tools;
/**
* A list of source for the tools.
* OPS! Shuld only be ussed to add a set of tools to the OllamaObject, not to be used for storage of tools internaly or externaly
* OPS! most be the same size as the tools list! since each tool matches to a source!
*/
private ArrayList<String> source;
/**
* Gets the tools of the {@link OllamaFunctionTools}
* @param tools A list of {@link OllamaFunctionTool}
* @param source The source of the tools
*/
private OllamaFunctionTools(ArrayList<OllamaFunctionTool> tools, ArrayList<String> source) {
if(source == null || tools == null || source.size() != tools.size() || source.isEmpty())
throw new IllegalArgumentException("The source and tools must be the same size! and not empty!");
this.tools = tools;
this.source = source;
}
/**
* Gets the tools of the {@link OllamaFunctionTools}
* @param tools A list of {@link OllamaFunctionTool}
* @param source The source of the tools
*/
private OllamaFunctionTools(OllamaFunctionTool[] tools, @MagicConstant(valuesFromClass = Core.Source.class) String[] source) {
if(source == null || tools == null || source.length != tools.length || source.length == 0)
throw new IllegalArgumentException("The source and tools must be the same size! and not empty!");
this.tools = new ArrayList<>();
this.source = new ArrayList<>();
for (OllamaFunctionTool tool : tools) {
this.tools.add(tool);
this.source.add(tool.name());
}
for (String s : source) {
if (s.equals(Core.Source.INTERNAL)) {
this.source.add(s);
}
}
}
public static OllamaFunctionToolsBuilder builder() {
return new OllamaFunctionToolsBuilder();
}
@Override
public @NotNull Iterator<Pair<OllamaFunctionTool, String>> iterator() {
ArrayList<Pair<OllamaFunctionTool, String>> pairs = new ArrayList<>();
for (int i = 0; i < tools.size(); i++) {
pairs.add(new Pair<>(tools.get(i), source.get(i)));
}
return pairs.iterator();
}
@Override
public void forEach(Consumer<? super Pair<OllamaFunctionTool, String>> action) {
for (Pair<OllamaFunctionTool, String> pair : this) {
action.accept(pair);
}
}
@Override
public Spliterator<Pair<OllamaFunctionTool, String>> spliterator() {
// TODO: Implement this method
throw new UnsupportedOperationException("Not implemented yet");
//return Iterable.super.spliterator();
}
public static class OllamaFunctionToolsBuilder {
private ArrayList<OllamaFunctionTool> tools = new ArrayList<>();
private ArrayList<String> source = new ArrayList<>();
public OllamaFunctionToolsBuilder addTool(OllamaFunctionTool tool, @MagicConstant(valuesFromClass = Core.Source.class) String source) {
this.tools.add(tool);
this.source.add(source);
return this;
}
public OllamaFunctionToolsBuilder addTools(HashMap<OllamaFunctionTool, String> tools) {
for (OllamaFunctionTool tool : tools.keySet()) {
this.tools.add(tool);
this.source.add(tools.get(tool));
}
return this;
}
public OllamaFunctionTools build() {
return new OllamaFunctionTools(tools, source);
}
}
}

View File

@@ -75,7 +75,7 @@ public class OllamaObject {
LaunchOptions launchOptions = new LaunchOptions();
if(launchOptions.isLoadOld()) {
System.out.println("Loading old data...");
File f = new File("./cache/messages.json");
File f = new File(Core.DATA_DIR+"/messages.json");
if(f.exists()) {
try {
BufferedReader br = new BufferedReader(new FileReader(f));
@@ -375,7 +375,8 @@ public class OllamaObject {
FileHandler fileHandler = new FileHandler(baseDirectory);
if(false);
return this;
throw new IllegalArgumentException("FileHandler is not supported yet!");
}
/**

View File

@@ -192,7 +192,15 @@ public class OllamaPerameter {
/**
* Represents a boolean parameter.
*/
BOOLEAN("boolean");
BOOLEAN("boolean"),
/**
* Represents a enum parameter.
*/
ENUM("enum"),
/**
* Represents a array parameter.
*/
ARRAY("array");
/**
* The type of the parameter.

View File

@@ -7,6 +7,7 @@ version = '1.0-SNAPSHOT'
dependencies {
implementation project(":Core")
implementation project(":MALAPITool")
}
test {

View File

@@ -5,6 +5,7 @@ import me.zacharias.chat.core.Pair;
import me.zacharias.chat.core.PrintMessageHandler;
import me.zacharias.chat.core.files.FileHandlerLocation;
import me.zacharias.chat.core.memory.CoreMemory;
import me.zacharias.chat.mal.api.MALAPITool;
import me.zacharias.chat.ollama.*;
import org.json.JSONObject;
@@ -42,16 +43,18 @@ public class Display {
public Display()
{
core.setOllamaObject(OllamaObject.builder()
.setModel("llama3.2")
//.setModel("deepseek-r1")
core.setOllamaObject/*NoMemory*/(OllamaObject.builder()
//.setModel("llama3.2")
//.setModel("gemma3:12b")
.setModel("qwen3:8b")
.keep_alive(10)
//.stream(false)
.addFileTools(FileHandlerLocation.DATA_FILES)
//.addFileTools(FileHandlerLocation.DATA_FILES)
.build());
//core.addTool(new TimeTool(), Core.Source.INTERNAL);
core.addTool(new TimeTool(), Core.Source.INTERNAL);
//core.addTool(new PythonRunner(core), Core.Source.INTERNAL);
core.addTools(new MALAPITool().getOllamaTools());
//core.getOllamaObject().addMessage(new OllamaMessage(OllamaMessageRole.SYSTEM, "Have a nice tone and use formal wording"));
@@ -101,7 +104,7 @@ public class Display {
System.exit(0);
return;
case "write":
core.flushLog();
Core.flushLog();
break;
case "peek":
CoreMemory coreMemory = CoreMemory.getInstance();

17
MALAPITool/README.md Normal file
View File

@@ -0,0 +1,17 @@
# MAL API wrapper
## Important notes
### Scope
This wrapper is not fully implemented, some endpoints are missing, as well as no user-specific endpoints are added.
### Rate limits
I'm yet to enforce the rate limit, due to in there the Ollama backend won't be fast enough, but this is subject to change
### API Key Required
You must provide your own API key
Store the key in `${DATE_DIR}/malapi.json` using the following format:
```jsonc
{
"client_id": "<client_id>",
"client_secret": "<client_secret>"// This is for the moment not used but shuld till be added
}
```

View File

@@ -0,0 +1,108 @@
package me.zacharias.chat.mal.api;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ClassInfoList;
import io.github.classgraph.ScanResult;
import me.zacharias.chat.core.Core;
import me.zacharias.chat.ollama.*;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
public class MALAPITool {
public final String Client_ID;
public final String Client_Secret;
public final String BaseURL = "https://api.myanimelist.net/v2";
public final OllamaFunctionTools MALAPITools;
public MALAPITool() {
super();
try {
JSONObject obj = new JSONObject(Files.readString(Path.of(Core.DATA_DIR + "/malapi.json")));
this.Client_ID = obj.getString("client_id");
this.Client_Secret = obj.getString("client_secret");
} catch (IOException e) {
throw new RuntimeException(e);
}
OllamaFunctionTools.OllamaFunctionToolsBuilder builder = new OllamaFunctionTools.OllamaFunctionToolsBuilder();
try(ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages("me.zacharias.chat.mal.api.endpoints").scan()) {
ClassInfoList endpoints = scanResult.getClassesWithAnnotation(MALEndpoint.class.getName());
for (ClassInfo classInfo : endpoints) {
Class<?> clazz = classInfo.loadClass();
if (OllamaFunctionTool.class.isAssignableFrom(clazz)) {
//System.out.println("Found endpoint: " + clazz.getName() + " With constructor: " + clazz.getDeclaredConstructors().f.getName() + " and arguments: " + Arrays.toString(clazz.getDeclaredConstructor().getParameterTypes()));
MALEndpointTool tool = (MALEndpointTool) clazz.getDeclaredConstructor(MALAPITool.class).newInstance(MALAPITool.this);
builder.addTool(tool, Core.Source.INTERNAL);
}
}
} catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
this.MALAPITools = builder.build();
}
public OllamaFunctionTools getOllamaTools() {
return this.MALAPITools;
}
public JSONObject APIRequest(String endpoint, HashMap<String, String> params) {
try {
String urlParams = ParameterStringBuilder.getParamsString(params);
URL url = new URI(this.BaseURL + endpoint + "?" + urlParams).toURL();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("X-MAL-CLIENT-ID", this.Client_ID);
connection.setDoOutput(true);
connection.setConnectTimeout(80 * 1000);
int responseCode = connection.getResponseCode();
// HTTP_OK or 200 response code generally means that the server ran successfully without any errors
StringBuilder response = new StringBuilder();
// Read response content
// connection.getInputStream() purpose is to obtain an input stream for reading the server's response.
try (
BufferedReader reader = new BufferedReader( new InputStreamReader( connection.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
response.append(line); // Adds every line to response till the end of file.
}
}
if (responseCode == HttpURLConnection.HTTP_OK) {
connection.disconnect();
return new JSONObject(response.toString());
}
else {
connection.disconnect();
System.err.println("Error: HTTP Response code - " + responseCode + "\n"+response.toString());
throw new RuntimeException("HTTP Response code - " + responseCode);
}
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,11 @@
package me.zacharias.chat.mal.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MALEndpoint {
}

View File

@@ -0,0 +1,11 @@
package me.zacharias.chat.mal.api;
import me.zacharias.chat.ollama.OllamaFunctionTool;
public abstract class MALEndpointTool extends OllamaFunctionTool {
protected MALAPITool MALAPIToolInstance;
public MALEndpointTool(MALAPITool malAPITool) {
super();
this.MALAPIToolInstance = malAPITool;
}
}

View File

@@ -0,0 +1,25 @@
package me.zacharias.chat.mal.api;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public class ParameterStringBuilder {
public static String getParamsString(Map<String, String> params)
throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
result.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
result.append("&");
}
String resultString = result.toString();
return !resultString.isEmpty()
? resultString.substring(0, resultString.length() - 1)
: resultString;
}
}

View File

@@ -0,0 +1,86 @@
package me.zacharias.chat.mal.api.endpoints;
import me.zacharias.chat.mal.api.MALAPITool;
import me.zacharias.chat.mal.api.MALEndpoint;
import me.zacharias.chat.mal.api.MALEndpointTool;
import me.zacharias.chat.ollama.OllamaFunctionArgument;
import me.zacharias.chat.ollama.OllamaPerameter;
import me.zacharias.chat.ollama.OllamaToolRespnce;
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
@MALEndpoint
public class GetAnimeDetails extends MALEndpointTool {
public GetAnimeDetails(MALAPITool malAPITool) {
super(malAPITool);
}
@Override
public String name() {
return "get_anime_details";
}
@Override
public String description() {
return "Gets the details of an anime from the MAL API";
}
@Override
public OllamaPerameter parameters() {
return OllamaPerameter.builder()
.addProperty("id", OllamaPerameter.OllamaPerameterBuilder.Type.INT, "The id of the anime", true)
.addProperty("fields", OllamaPerameter.OllamaPerameterBuilder.Type.ARRAY, "The fields to return, defaults to [\"id\", \"title\", \"synopsis\", \"genres\"]")
.build();
}
@Override
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
int id = -1;
String[] fields = null;
for (OllamaFunctionArgument arg : args) {
switch (arg.argument()) {
case "id":
id = (Integer) arg.value();
break;
case "fields":
JSONArray jsonArray = (JSONArray) arg.value();
for (int i = 0; i < jsonArray.length(); i++) {
if (jsonArray.get(i) instanceof String) {
if (fields == null) {
fields = new String[jsonArray.length()];
}
fields[i] = jsonArray.getString(i);
} else {
throw new OllamaToolErrorException(this.name(), "The fields must be a string array");
}
}
break;
}
}
if (id == -1) {
throw new OllamaToolErrorException(this.name(), "The id must be specified");
}
if (fields == null) {
fields = new String[]{
"id",
"title",
"synopsis",
"genres"
};
}
HashMap<String, String> map = new HashMap<>();
map.put("fields", String.join(",", fields));
JSONObject obj = MALAPIToolInstance.APIRequest("/anime/"+id, map);
return new OllamaToolRespnce(this.name(), obj.toString());
}
}

View File

@@ -0,0 +1,88 @@
package me.zacharias.chat.mal.api.endpoints;
import me.zacharias.chat.mal.api.MALAPITool;
import me.zacharias.chat.mal.api.MALEndpoint;
import me.zacharias.chat.mal.api.MALEndpointTool;
import me.zacharias.chat.ollama.OllamaFunctionArgument;
import me.zacharias.chat.ollama.OllamaPerameter;
import me.zacharias.chat.ollama.OllamaToolRespnce;
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
@MALEndpoint
public class GetAnimeList extends MALEndpointTool {
public GetAnimeList(MALAPITool malAPITool) {
super(malAPITool);
}
@Override
public String name() {
return "get_anime_list";
}
@Override
public String description() {
return "Gets a list of anime from the MAL API";
}
@Override
public OllamaPerameter parameters() {
return OllamaPerameter.builder()
.addProperty("query", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The query to search for",true)
.addProperty("offset", OllamaPerameter.OllamaPerameterBuilder.Type.INT, "The offset to start from")
.addProperty("fields", OllamaPerameter.OllamaPerameterBuilder.Type.ARRAY, "The fields to return")
.build();
}
@Override
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
String query = "";
int offset = 0;
String[] fields = null;
for (OllamaFunctionArgument arg : args) {
switch (arg.argument()) {
case "query":
query = (String)arg.value();
break;
case "offset":
offset = (Integer) arg.value();
break;
case "fields":
JSONArray jsonArray = (JSONArray) arg.value();
if(!jsonArray.isEmpty()) {
fields = new String[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
if (jsonArray.get(i) instanceof String) {
fields[i] = jsonArray.getString(i);
} else {
throw new OllamaToolErrorException(this.name(), "The fields must be a string array");
}
}
}
break;
}
}
if (query.isEmpty()) {
throw new OllamaToolErrorException(this.name(), "Query cannot be empty");
}
HashMap<String, String> params = new HashMap<>();
params.put("q", query);
if (offset > 0) {
params.put("offset", String.valueOf(offset));
}
if (fields != null) {
params.put("fields", String.join(",", fields));
}
JSONObject response = MALAPIToolInstance.APIRequest("/anime", params);
return new OllamaToolRespnce(this.name(), response.toString());
}
}

View File

@@ -0,0 +1,85 @@
package me.zacharias.chat.mal.api.endpoints;
import me.zacharias.chat.mal.api.MALAPITool;
import me.zacharias.chat.mal.api.MALEndpoint;
import me.zacharias.chat.mal.api.MALEndpointTool;
import me.zacharias.chat.ollama.OllamaFunctionArgument;
import me.zacharias.chat.ollama.OllamaPerameter;
import me.zacharias.chat.ollama.OllamaToolRespnce;
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
@MALEndpoint
public class GetManagDetails extends MALEndpointTool {
public GetManagDetails(MALAPITool malAPITool) {
super(malAPITool);
}
@Override
public String name() {
return "get_manag_details";
}
@Override
public String description() {
return "Gets the details of an manga from the MAL API";
}
@Override
public OllamaPerameter parameters() {
return OllamaPerameter.builder()
.addProperty("id", OllamaPerameter.OllamaPerameterBuilder.Type.INT, "The id of the manga", true)
.addProperty("fields", OllamaPerameter.OllamaPerameterBuilder.Type.ARRAY, "The fields to return, defaults to [\"id\", \"title\", \"synopsis\", \"genres\"]")
.build();
}
@Override
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
int id = -1;
String[] fields = null;
for (OllamaFunctionArgument arg : args) {
switch (arg.argument()) {
case "id":
id = (Integer) arg.value();
break;
case "fields":
JSONArray jsonArray = (JSONArray) arg.value();
for (int i = 0; i < jsonArray.length(); i++) {
if (jsonArray.get(i) instanceof String) {
if (fields == null) {
fields = new String[jsonArray.length()];
}
fields[i] = jsonArray.getString(i);
} else {
throw new OllamaToolErrorException(this.name(), "The fields must be a string array");
}
}
break;
}
}
if (id == -1) {
throw new OllamaToolErrorException(this.name(), "The id must be specified");
}
if (fields == null) {
fields = new String[]{
"id",
"title",
"synopsis",
"genres"
};
}
HashMap<String, String> map = new HashMap<>();
map.put("fields", String.join(",", fields));
JSONObject obj = MALAPIToolInstance.APIRequest("/manga/"+id, map);
return new OllamaToolRespnce(this.name(), obj.toString());
}
}

View File

@@ -0,0 +1,87 @@
package me.zacharias.chat.mal.api.endpoints;
import me.zacharias.chat.mal.api.MALAPITool;
import me.zacharias.chat.mal.api.MALEndpoint;
import me.zacharias.chat.mal.api.MALEndpointTool;
import me.zacharias.chat.ollama.OllamaFunctionArgument;
import me.zacharias.chat.ollama.OllamaPerameter;
import me.zacharias.chat.ollama.OllamaToolRespnce;
import me.zacharias.chat.ollama.exceptions.OllamaToolErrorException;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
@MALEndpoint
public class GetMangaList extends MALEndpointTool {
public GetMangaList(MALAPITool malAPITool) {
super(malAPITool);
}
@Override
public String name() {
return "get_manga_list";
}
@Override
public String description() {
return "Gets a list of manga from the MAL API";
}
@Override
public OllamaPerameter parameters() {
return OllamaPerameter.builder()
.addProperty("query", OllamaPerameter.OllamaPerameterBuilder.Type.STRING, "The query to search for",true)
.addProperty("offset", OllamaPerameter.OllamaPerameterBuilder.Type.INT, "The offset to start from")
.addProperty("fields", OllamaPerameter.OllamaPerameterBuilder.Type.ARRAY, "The fields to return")
.build();
}
@Override
public OllamaToolRespnce function(OllamaFunctionArgument... args) {
String query = "";
int offset = 0;
String[] fields = null;
for (OllamaFunctionArgument arg : args) {
switch (arg.argument()) {
case "query":
query = (String)arg.value();
break;
case "offset":
offset = (Integer) arg.value();
break;
case "fields":
JSONArray jsonArray = (JSONArray) arg.value();
if(!jsonArray.isEmpty()) {
fields = new String[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
if (jsonArray.get(i) instanceof String) {
fields[i] = jsonArray.getString(i);
} else {
throw new OllamaToolErrorException(this.name(), "The fields must be a string array");
}
}
}
break;
}
}
if (query.isEmpty()) {
throw new OllamaToolErrorException(this.name(), "Query cannot be empty");
}
HashMap<String, String> params = new HashMap<>();
params.put("q", query);
if (offset > 0) {
params.put("offset", String.valueOf(offset));
}
if (fields != null) {
params.put("fields", String.join(",", fields));
}
JSONObject response = MALAPIToolInstance.APIRequest("/manga", params);
return new OllamaToolRespnce(this.name(), response.toString());
}
}

View File

@@ -1,3 +1,5 @@
rootProject.name = 'AI-test'
include 'API', 'Core', 'Display', 'launcher'
include 'MALAPITool'