package me.zacharias.chat.api; import me.zacharias.chat.api.payload.request.NewQurryResponceHook; import me.zacharias.chat.api.payload.request.NewToolRequest; import me.zacharias.chat.core.Core; import me.zacharias.chat.core.GlobalObjects; import me.zacharias.chat.core.PrintMessageHandler; import me.zacharias.chat.ollama.OllamaObject; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @SpringBootApplication public class APIApplication { public static void start(){ ConfigurableApplicationContext ctx = SpringApplication.run(APIApplication.class); } public static void main(String[] args) { SpringApplication.run(APIApplication.class, args); } private static APIApplication instance; private final Map tools = new HashMap<>(); private final ArrayList querryResponceEndpoints = new ArrayList<>(); private final Core core; WebClient webClient = WebClient.create(); public APIApplication() { if(instance != null) throw new IllegalStateException("APIApplication is already running!"); instance = this; if(GlobalObjects.getObject("core") instanceof Core coreInstance) { this.core = coreInstance; } else { this.core = new Core(new PrintMessageHandler() { @Override public void printMessage(String message) { synchronized (querryResponceEndpoints) { querryResponceEndpoints.forEach(endpoint -> { webClient.post().uri(endpoint.getUrl()).bodyValue(message).retrieve() .onStatus( status -> status.is4xxClientError() || status.is5xxServerError() || status.isError(), clientResponse -> { return clientResponse.bodyToMono(String.class).flatMap(body -> { endpoint.sendError("Failed to send message for qurry response"); querryResponceEndpoints.remove(endpoint); return Mono.error(new RuntimeException("Webhook call failed with status: " + clientResponse.statusCode())); }); }) .toBodilessEntity() .doOnError(e -> { }) .subscribe(); }); } } @Override public boolean color() { return false; } }); core.setOllamaObject(OllamaObject.builder() .setModel("qwen3:8b") .keep_alive(10) .build()); } } public static APIApplication getInstance() { return instance; } public boolean addTool(String name, NewToolRequest request) { if (name == null || name.isEmpty()) { throw new IllegalArgumentException("Tool name cannot be null or empty"); } if (tools.containsKey(name)) { return false; // Tool with this name already exists } APITool tool = new APITool(request); tools.put(name, tool); core.addTool(tool, Core.Source.API); return true; } public boolean removeTool(String name) { if(name == null || name.isEmpty()) { throw new IllegalArgumentException("Tool name cannot be null or empty"); } if (!tools.containsKey(name)) { return false; // Tool with this name does not exist } APITool tool = tools.remove(name); core.removeTool(tool.name()); return true; } public void addQurryResponseHook(NewQurryResponceHook request) { if (request == null || request.getUrl() == null || request.getUrl().isEmpty()) { throw new IllegalArgumentException("Request and URL cannot be null or empty"); } QuerryResponceEndpoint endpoint = new QuerryResponceEndpoint(request.getUrl(), request.getErrorUrl()); synchronized (querryResponceEndpoints) { querryResponceEndpoints.add(endpoint); } } public Core getCore() { return core; } }