From d30f2e404ebc0f0d14b4319404622133de85a667 Mon Sep 17 00:00:00 2001 From: Erik Dix Date: Tue, 30 Sep 2025 18:01:20 +0200 Subject: [PATCH] eerste check in --- .gitignore | 40 +++++ pom.xml | 100 ++++++++++++ .../kotlin/nl/trivion/softwarefabric/Main.kt | 142 ++++++++++++++++++ .../trivion/softwarefabric/tools/GitTools.kt | 47 ++++++ 4 files changed, 329 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/kotlin/nl/trivion/softwarefabric/Main.kt create mode 100644 src/main/kotlin/nl/trivion/softwarefabric/tools/GitTools.kt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2485648 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store +/.idea/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..054d520 --- /dev/null +++ b/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + nl.trivion + SoftwareFabric + 1.0-SNAPSHOT + + + UTF-8 + official + 21 + + + + + mavenCentral + https://repo1.maven.org/maven2/ + + + + + src/main/kotlin + src/test/kotlin + + + org.jetbrains.kotlin + kotlin-maven-plugin + 2.2.10 + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + + maven-surefire-plugin + 2.22.2 + + + maven-failsafe-plugin + 2.22.2 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + MainKt + + + + + + + + org.jetbrains.kotlin + kotlin-test-junit5 + 2.2.10 + test + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + org.jetbrains.kotlin + kotlin-stdlib + 2.2.10 + + + + ai.koog + koog-agents-jvm + 0.4.2 + + + + org.eclipse.jgit + org.eclipse.jgit + 7.3.0.202506031305-r + + + + \ No newline at end of file diff --git a/src/main/kotlin/nl/trivion/softwarefabric/Main.kt b/src/main/kotlin/nl/trivion/softwarefabric/Main.kt new file mode 100644 index 0000000..7946459 --- /dev/null +++ b/src/main/kotlin/nl/trivion/softwarefabric/Main.kt @@ -0,0 +1,142 @@ +package org.example.nl.trivion.softwarefabric + +import ai.koog.agents.core.agent.AIAgent +import ai.koog.agents.core.agent.config.AIAgentConfig +import ai.koog.agents.core.dsl.builder.forwardTo +import ai.koog.agents.core.dsl.builder.strategy +import ai.koog.agents.core.dsl.extension.nodeExecuteTool +import ai.koog.agents.core.dsl.extension.nodeLLMRequest +import ai.koog.agents.core.dsl.extension.nodeLLMSendToolResult +import ai.koog.agents.core.dsl.extension.onAssistantMessage +import ai.koog.agents.core.dsl.extension.onToolCall +import ai.koog.agents.core.feature.handler.AgentFinishedContext +import ai.koog.agents.core.feature.handler.AgentStartContext +import ai.koog.agents.core.tools.ToolRegistry +import ai.koog.agents.core.tools.annotations.LLMDescription +import ai.koog.agents.core.tools.annotations.Tool +import ai.koog.agents.core.tools.reflect.ToolSet +import ai.koog.agents.core.tools.reflect.asTools +import ai.koog.agents.features.eventHandler.feature.EventHandler +import ai.koog.prompt.dsl.Prompt +import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor +import ai.koog.prompt.llm.LLMCapability +import ai.koog.prompt.llm.LLMProvider +import ai.koog.prompt.llm.LLModel +import kotlinx.coroutines.runBlocking + +// Use the OpenAI executor with an API key from an environment variable +val promptExecutor = simpleOllamaAIExecutor("http://localhost:11434") + +val customModel: LLModel = LLModel( + provider = LLMProvider.Ollama, + id = "gpt-oss:20b", + capabilities = listOf( + LLMCapability.Temperature, + LLMCapability.Tools + ), + contextLength = 2048 +) + +// Create a simple strategy +val agentStrategy = strategy("Simple calculator") { + // Define nodes for the strategy + val nodeSendInput by nodeLLMRequest() + val nodeExecuteTool by nodeExecuteTool() + val nodeSendToolResult by nodeLLMSendToolResult() + + // Define edges between nodes + // Start -> Send input + edge(nodeStart forwardTo nodeSendInput) + + // Send input -> Finish + edge( + (nodeSendInput forwardTo nodeFinish) + transformed { it } + onAssistantMessage { true } + ) + + // Send input -> Execute tool + edge( + (nodeSendInput forwardTo nodeExecuteTool) + onToolCall { true } + ) + + // Execute tool -> Send the tool result + edge(nodeExecuteTool forwardTo nodeSendToolResult) + + // Send the tool result -> finish + edge( + (nodeSendToolResult forwardTo nodeFinish) + transformed { it } + onAssistantMessage { true } + ) +} + +// Configure the agent +val agentConfig = AIAgentConfig( + prompt = Prompt.build("simple-calculator") { + system( + """ + You are a simple calculator assistant. + You can add two numbers together using the calculator tool. + When the user provides input, extract the numbers they want to add. + The input might be in various formats like "add 5 and 7", "5 + 7", or just "5 7". + Extract the two numbers and use the calculator tool to add them. + Always respond with a clear, friendly message showing the calculation and result. + """.trimIndent() + ) + }, + model = customModel, + maxAgentIterations = 10 +) + +// Implement a simple calculator tool that can add two numbers +@LLMDescription("Tools for performing basic arithmetic operations") +class CalculatorTools : ToolSet { + @Tool + @LLMDescription("Add two numbers together and return their sum") + fun add( + @LLMDescription("First number to add (integer value)") + num1: Int, + + @LLMDescription("Second number to add (integer value)") + num2: Int + ): String { + val sum = num1 + num2 + return "The sum of $num1 and $num2 is: $sum" + } +} + +// Add the tool to the tool registry +val toolRegistry = ToolRegistry { + tools(CalculatorTools().asTools()) +} + +// Create the agent +val agent = AIAgent( + promptExecutor = promptExecutor, + toolRegistry = toolRegistry, + strategy = agentStrategy, + agentConfig = agentConfig, + installFeatures = { + install(EventHandler) { + onBeforeAgentStarted { eventContext: AgentStartContext<*> -> + println("Starting strategy: ${eventContext.strategy.name}") + } + onAgentFinished { eventContext: AgentFinishedContext -> + println("Result: ${eventContext.result}") + } + } + } +) + +fun main() { + runBlocking { + println("Enter two numbers to add (e.g., 'add 5 and 7' or '5 + 7'):") + + // Read the user input and send it to the agent + val userInput = readlnOrNull() ?: "" + val agentResult = agent.run(userInput) + println("The agent returned: $agentResult") + } +} \ No newline at end of file diff --git a/src/main/kotlin/nl/trivion/softwarefabric/tools/GitTools.kt b/src/main/kotlin/nl/trivion/softwarefabric/tools/GitTools.kt new file mode 100644 index 0000000..930d3f2 --- /dev/null +++ b/src/main/kotlin/nl/trivion/softwarefabric/tools/GitTools.kt @@ -0,0 +1,47 @@ +package org.example.nl.trivion.softwarefabric.tools + +import ai.koog.agents.core.tools.annotations.LLMDescription +import ai.koog.agents.core.tools.annotations.Tool +import ai.koog.agents.core.tools.reflect.ToolSet +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider +import java.io.File + +val username: String? = System.getenv("GIT_USERNAME") +val password: String? = System.getenv("GIT_PASSWORD") + +// Implement a simple calculator tool that can add two numbers +@LLMDescription("Tools for performing basic git operations") +class GitTools : ToolSet { + + @Tool + @LLMDescription("Clone een git repository") + fun cloneRepository( + @LLMDescription("The remote url from the git repository") + remoteUrl: String, + @LLMDescription("The local path to clone the repository to") + localPath: File) { + + Git.cloneRepository() + .setURI(remoteUrl) + .setDirectory(localPath) + .call() + } + + @Tool + @LLMDescription("Pull a git repository") + fun pull( + @LLMDescription("The local path from the local git repository") + localPath: String, + @LLMDescription("The branch to pull") + branch: String) { + + Git.open(File(localPath)).use { git -> + git.pull() + .setRemote("origin") + .setRemoteBranchName(branch) + .setCredentialsProvider(UsernamePasswordCredentialsProvider(username, password)) + .call() + } + } +} \ No newline at end of file