Skip to content

Commit

Permalink
Added bookstack tool
Browse files Browse the repository at this point in the history
Closes #84
  • Loading branch information
geir-eilertsen committed Jan 8, 2025
1 parent 8986489 commit daff681
Show file tree
Hide file tree
Showing 13 changed files with 231 additions and 23 deletions.
6 changes: 6 additions & 0 deletions marvin.interaction.web/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>marvin.library.bookstack</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down
6 changes: 6 additions & 0 deletions marvin.interaction.web/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ spring:
include:
- environment-openhab
- chat-openai
- library-bookstack
application:
name: Marvin the Robot
version: 0.0.1
Expand Down Expand Up @@ -49,5 +50,10 @@ google:
apikey: ${GOOGLE_APIKEY}
cx: ${GOOGLE_CX}

bookstack:
url: ${BOOKSTACK_URL}
tokenid: ${BOOKSTACK_TOKEN_ID}
tokensecret: ${BOOKSTACK_TOKEN_SECRET}

marvin:
language: 'en'
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ public class ForSearchingInternetGoogleApiAdapter implements ForSearchingInterne
Log LOG = LogFactory.getLog(getClass());

@Resource
private RestClient restClient;
private RestClient googleRestClient;
@Resource
private Environment env;

@Override
public String search(String query) {
LOG.info(query);
try {
String body = restClient.get()
String body = googleRestClient.get()
.uri(uriBuilder -> uriBuilder
.queryParam("key", env.getProperty("google.apikey"))
.queryParam("cx", env.getProperty("google.cx"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
package com.assetvisor.marvin.internet.google.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClient.RequestHeadersSpec;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilder;
import org.springframework.web.util.UriBuilderFactory;

@Configuration
public class GoogleConfig {

@Value("${google.apikey}")
private String apiKey;
@Value("${google.cx}")
private String customSearchEngineId;

@Bean
public RestClient restClient() {
public RestClient googleRestClient() {
String baseUrl = "https://www.googleapis.com/customsearch/v1";

return RestClient.builder()
Expand Down
27 changes: 27 additions & 0 deletions marvin.library.bookstack/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.assetvisor</groupId>
<artifactId>marvin.robot</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>marvin.library.bookstack</artifactId>

<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>marvin.robot.core</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.assetvisor.marvin.library.bookstack.adapters;

import static com.assetvisor.marvin.toolkit.ProfileChecker.LIBRARY_BOOKSTACK;

import com.assetvisor.marvin.toolkit.library.ForListingBooks;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import java.io.IOException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClient;

@Component
@Profile(LIBRARY_BOOKSTACK)
public class ForListingBooksBookStackAdapter implements ForListingBooks {
Log LOG = LogFactory.getLog(getClass());

@Resource
private RestClient bookStackRestClient;

@Override
public List<Book> listBooks() {
LOG.info("Listing books");
try {
String json = bookStackRestClient.get()
.uri("books")
.retrieve()
.body(String.class);
return map(json);
} catch (HttpClientErrorException | IOException e) {
LOG.error("Failed to list books", e);
return List.of();
}
}

private List<Book> map(String json) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();

List<BookJsonEntry> bookJsonEntries = objectMapper.readTree(json)
.get("data")
.traverse(objectMapper)
.readValueAs(new TypeReference<List<BookJsonEntry>>() {});

return bookJsonEntries.stream()
.map(bookJsonEntry -> new Book(bookJsonEntry.id(), bookJsonEntry.name(), bookJsonEntry.description()))
.toList();
}

@JsonIgnoreProperties(ignoreUnknown = true)
private record BookJsonEntry(String id, String name, String description) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.assetvisor.marvin.library.bookstack.config;

import static com.assetvisor.marvin.toolkit.ProfileChecker.LIBRARY_BOOKSTACK;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.client.RestClient;

@Configuration
@Profile(LIBRARY_BOOKSTACK)
public class BookStackConfig {

@Value("${bookstack.tokenid}")
private String tokenId;
@Value("${bookstack.tokensecret}")
private String tokenSecret;
@Value("${bookstack.url}")
private String url;

@Bean
public RestClient bookStackRestClient() {
String baseUrl = url + "/api/";

return RestClient.builder()
.baseUrl(baseUrl)
.defaultHeaders(headers ->
headers.add("Authorization", "Token " + tokenId + ":" + tokenSecret)
)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public Observation(String sender, String itemId, String value, String oldValue,

@Override
public String toString() {
return "Item: " + itemId + " changed value from " + oldValue + " to " + value + " - " + description;
return "Item: " + itemId + " changed value from " + oldValue + " to " + value;
}

public String itemId() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.assetvisor.marvin.toolkit;

import jakarta.annotation.Resource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
public class ProfileChecker {

@Resource
private Environment environment;

public boolean isProfileActive(String profile) {
String[] activeProfiles = environment.getActiveProfiles();
for (String activeProfile : activeProfiles) {
if (activeProfile.equals(profile)) {
return true;
}
}
return false;
}

public static final String ENVIRONMENT_OPENHAB = "environment-openhab";
public static final String LIBRARY_BOOKSTACK = "library-bookstack";
public static final String CHAT_OPENAI = "chat-openai";
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
package com.assetvisor.marvin.toolkit;

import com.assetvisor.marvin.toolkit.memory.ForRemembering;
import com.assetvisor.marvin.toolkit.memory.RememberTool;
import static com.assetvisor.marvin.toolkit.ProfileChecker.LIBRARY_BOOKSTACK;

import com.assetvisor.marvin.robot.domain.tools.ForGettingOwnTools;
import com.assetvisor.marvin.robot.domain.tools.Tool;
import com.assetvisor.marvin.toolkit.internet.ForSearchingInternet;
import com.assetvisor.marvin.toolkit.internet.SearchInternetTool;
import com.assetvisor.marvin.toolkit.library.ForListingBooks;
import com.assetvisor.marvin.toolkit.library.ListLibraryBooksTool;
import com.assetvisor.marvin.toolkit.memory.ForRemembering;
import com.assetvisor.marvin.toolkit.memory.RememberTool;
import com.assetvisor.marvin.toolkit.notebook.NoteBook;
import com.assetvisor.marvin.toolkit.notebook.WriteInNoteBookTool;
import com.assetvisor.marvin.toolkit.watch.LookAtWatchTool;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
public class Toolkit implements ForGettingOwnTools {

@Resource
private ProfileChecker profileChecker;
@Resource
private NoteBook noteBook;
@Resource
private ForRemembering forRemembering;
@Resource
private ForSearchingInternet forSearchingInternet;
@Resource
@Lazy
private ForListingBooks forListingBooks;


@Override
public List<Tool<?, ?>> getOwnTools() {
return List.of(
new LookAtWatchTool(),
new WriteInNoteBookTool(noteBook),
new RememberTool(forRemembering),
new SearchInternetTool(forSearchingInternet)
);
List<Tool<?,?>> ret = new ArrayList<>();
ret.add(new LookAtWatchTool());
ret.add(new WriteInNoteBookTool(noteBook));
ret.add(new RememberTool(forRemembering));
ret.add(new SearchInternetTool(forSearchingInternet));
if (profileChecker.isProfileActive(LIBRARY_BOOKSTACK)) {
ret.add(new ListLibraryBooksTool(forListingBooks));
}
return ret;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.assetvisor.marvin.toolkit.library;

import java.util.List;

public interface ForListingBooks {
List<Book> listBooks();

record Book(String id, String name, String description) {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.assetvisor.marvin.toolkit.library;

import com.assetvisor.marvin.robot.domain.tools.Tool;
import com.assetvisor.marvin.toolkit.library.ForListingBooks.Book;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ListLibraryBooksTool implements Tool<Void, List<Book>> {

private static final Log LOG = LogFactory.getLog(ListLibraryBooksTool.class);
private final ForListingBooks forListingBooks;

public ListLibraryBooksTool(ForListingBooks forListingBooks) {
this.forListingBooks = forListingBooks;
}

@Override
public String name() {
return "ListLibraryBooks";
}

@Override
public String description() {
return "This tool is used for listing books.";
}

@Override
public Class<?> inputType() {
return Void.class;
}

@Override
public List<Book> apply(Void unused) {
return forListingBooks.listBooks();
}

}
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<module>marvin.persistence</module>
<module>marvin.speech.openai</module>
<module>marvin.internet.google</module>
<module>marvin.library.bookstack</module>
</modules>

<properties>
Expand Down Expand Up @@ -42,7 +43,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.0-M5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down

0 comments on commit daff681

Please sign in to comment.