diff --git a/README.md b/README.md index a841e91..bb2627c 100644 --- a/README.md +++ b/README.md @@ -125,10 +125,8 @@ fun main() { If you want to write AI agents, you need tools, and this is where this library shines: ```kotlin -@AnthropicTool( - name = "get_weather", - description = "Get the weather for a specific location" -) +@AnthropicTool("get_weather") +@Description("Get the weather for a specific location") data class WeatherTool(val location: String): UsableTool { override fun use( toolUseId: String @@ -187,10 +185,8 @@ services providing some facilities, like HTTP client to connect to the internet or DB connection pool to access the database. ```kotlin -@AnthropicTool( - name = "query_database", - description = "Executes SQL on the database" -) +@AnthropicTool("query_database") +@Description("Executes SQL on the database") data class DatabaseQueryTool(val sql: String): UsableTool { @Transient diff --git a/src/commonMain/kotlin/schema/JsonSchema.kt b/src/commonMain/kotlin/schema/JsonSchema.kt index d6ef32b..8e3326f 100644 --- a/src/commonMain/kotlin/schema/JsonSchema.kt +++ b/src/commonMain/kotlin/schema/JsonSchema.kt @@ -6,7 +6,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @OptIn(ExperimentalSerializationApi::class) -@Target(AnnotationTarget.PROPERTY) +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS) @MetaSerializable annotation class Description( val value: String diff --git a/src/commonMain/kotlin/tool/Tools.kt b/src/commonMain/kotlin/tool/Tools.kt index 5fafc58..079eaa6 100644 --- a/src/commonMain/kotlin/tool/Tools.kt +++ b/src/commonMain/kotlin/tool/Tools.kt @@ -3,6 +3,7 @@ package com.xemantic.anthropic.tool import com.xemantic.anthropic.message.CacheControl import com.xemantic.anthropic.message.Tool import com.xemantic.anthropic.message.ToolResult +import com.xemantic.anthropic.schema.Description import com.xemantic.anthropic.schema.jsonSchemaOf import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.MetaSerializable @@ -16,14 +17,12 @@ import kotlinx.serialization.serializer * of the Anthropic API. It includes a name and description for the tool. * * @property name The name of the tool. This name is used during serialization and should be a unique identifier for the tool. - * @property description A comprehensive description of what the tool does and how it should be used. */ @OptIn(ExperimentalSerializationApi::class) @MetaSerializable @Target(AnnotationTarget.CLASS) annotation class AnthropicTool( - val name: String, - val description: String = "" + val name: String ) /** @@ -45,15 +44,6 @@ interface UsableTool { } -fun Tool.cacheControl( - cacheControl: CacheControl? = null -): Tool = if (cacheControl == null) this else Tool( - name, - description, - inputSchema, - cacheControl -) - @OptIn(ExperimentalSerializationApi::class) inline fun toolOf( cacheControl: CacheControl? = null // TODO should it be here? @@ -78,10 +68,17 @@ inline fun toolOf( "The class ${T::class.qualifiedName} must be annotated with @AnthropicTool" ) + val description = serializer + .descriptor + .annotations + .filterIsInstance() + .firstOrNull() + ?.value + return Tool( name = anthropicTool.name, // annotation description cannot be null, so we allow empty and detect it here - description = if (anthropicTool.description.isNotBlank()) anthropicTool.description else null, + description = description, inputSchema = jsonSchemaOf(), cacheControl = cacheControl ) diff --git a/src/commonTest/kotlin/test/AnthropicTestTools.kt b/src/commonTest/kotlin/test/AnthropicTestTools.kt index 6aa6a06..79713b4 100644 --- a/src/commonTest/kotlin/test/AnthropicTestTools.kt +++ b/src/commonTest/kotlin/test/AnthropicTestTools.kt @@ -1,14 +1,13 @@ package com.xemantic.anthropic.test import com.xemantic.anthropic.message.ToolResult +import com.xemantic.anthropic.schema.Description import com.xemantic.anthropic.tool.AnthropicTool import com.xemantic.anthropic.tool.UsableTool import kotlinx.serialization.Transient -@AnthropicTool( - name = "FibonacciTool", - description = "Calculate Fibonacci number n" -) +@AnthropicTool("FibonacciTool") +@Description("Calculate Fibonacci number n") data class FibonacciTool(val n: Int): UsableTool { tailrec fun fibonacci( @@ -23,10 +22,8 @@ data class FibonacciTool(val n: Int): UsableTool { } -@AnthropicTool( - name = "Calculator", - description = "Calculates the arithmetic outcome of an operation when given the arguments a and b" -) +@AnthropicTool("Calculator") +@Description("Calculates the arithmetic outcome of an operation when given the arguments a and b") data class Calculator( val operation: Operation, val a: Double, @@ -64,10 +61,8 @@ class TestDatabase : Database { } } -@AnthropicTool( - name = "DatabaseQuery", - description = "Executes database query" -) +@AnthropicTool("DatabaseQuery") +@Description("Executes database query") data class DatabaseQueryTool( val query: String ) : UsableTool { diff --git a/src/commonTest/kotlin/tool/UsableToolTest.kt b/src/commonTest/kotlin/tool/UsableToolTest.kt index 4c32b0c..6ff5258 100644 --- a/src/commonTest/kotlin/tool/UsableToolTest.kt +++ b/src/commonTest/kotlin/tool/UsableToolTest.kt @@ -14,10 +14,8 @@ import kotlin.test.Test class UsableToolTest { - @AnthropicTool( - name = "TestTool", - description = "Test tool receiving a message and outputting it back" - ) + @AnthropicTool("TestTool") + @Description("Test tool receiving a message and outputting it back") class TestTool( @Description("the message") val message: String