Skip to content

Commit da20ade

Browse files
Refactor: Update koog and refactor WeatherTools
1 parent 732ff0d commit da20ade

File tree

8 files changed

+89
-94
lines changed

8 files changed

+89
-94
lines changed

.github/workflows/demo-compose-app.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ jobs:
2525
gradle-tasks: [
2626
"ktlintCheck lint :androidApp:assembleDebug :androidApp:assembleRelease",
2727
":desktopApp:jar",
28-
":webApp:composeCompatibilityBrowserDistribution"
28+
":webApp:jsBrowserDevelopmentWebpack"
2929
]
3030
os: [ ubuntu-latest ]
3131
include:
3232
- gradle-tasks: ":commonApp:iosSimulatorArm64Binaries"
33-
os: macos-latest-xlarge
33+
os: macos-latest
3434

3535
steps:
3636
- name: Configure Git

examples/demo-compose-app/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ To run the application on iPhone device/simulator:
3939
- Or use [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio
4040

4141
### Web Distribution
42-
Build web distribution: `./gradlew :webApp:composeCompatibilityBrowserDistribution`
42+
Build web pack: `./gradlew :webApp:jsBrowserDevelopmentWebpack`
4343
Deploy a dir `webApp/build/dist/composeWebCompatibility/productionExecutable` to a web server
4444

4545
### JS Browser

examples/demo-compose-app/commonApp/src/commonMain/kotlin/com/jetbrains/example/koog/compose/agents/calculator/CalculatorAgentProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ internal class CalculatorAgentProvider(private val provideLLMClient: suspend ()
124124
) {
125125
handleEvents {
126126
onToolCallStarting { ctx ->
127-
onToolCallEvent("Tool ${ctx.tool.name}, args ${ctx.toolArgs}")
127+
onToolCallEvent("Tool ${ctx.toolName}, args ${ctx.toolArgs}")
128128
}
129129

130130
onAgentExecutionFailed { ctx ->

examples/demo-compose-app/commonApp/src/commonMain/kotlin/com/jetbrains/example/koog/compose/agents/calculator/CalculatorTools.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import ai.koog.agents.core.tools.annotations.LLMDescription
55
import kotlinx.serialization.Serializable
66

77
sealed class CalculatorTool(
8-
override val name: String,
9-
override val description: String,
10-
) : Tool<CalculatorTool.Args, CalculatorTool.Result>() {
8+
name: String,
9+
description: String,
10+
) : Tool<CalculatorTool.Args, CalculatorTool.Result>(
11+
argsSerializer = Args.serializer(),
12+
resultSerializer = Result.serializer(),
13+
name = name,
14+
description = description
15+
) {
1116
@Serializable
1217
data class Args(
1318
@property:LLMDescription("First number")
@@ -19,9 +24,6 @@ sealed class CalculatorTool(
1924
@Serializable
2025
class Result(val result: Float)
2126

22-
final override val argsSerializer = Args.serializer()
23-
final override val resultSerializer = Result.serializer()
24-
2527
/**
2628
* 2. Implement the tool (tools).
2729
*/

examples/demo-compose-app/commonApp/src/commonMain/kotlin/com/jetbrains/example/koog/compose/agents/common/ExitTool.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import ai.koog.agents.core.tools.SimpleTool
44
import ai.koog.agents.core.tools.annotations.LLMDescription
55
import kotlinx.serialization.Serializable
66

7-
object ExitTool : SimpleTool<ExitTool.Args>() {
7+
object ExitTool : SimpleTool<ExitTool.Args>(
8+
argsSerializer = Args.serializer(),
9+
name = "exit",
10+
description = "Exit the agent session with the specified result. Call this tool to finish the conversation with the user."
11+
) {
812
@Serializable
913
data class Args(
1014
@property:LLMDescription("The result of the agent session. Default is empty, if there's no particular result.")
1115
val result: String = ""
1216
)
1317

14-
override val argsSerializer = Args.serializer()
15-
override val description: String =
16-
"Exit the agent session with the specified result. Call this tool to finish the conversation with the user."
17-
18-
override suspend fun doExecute(args: Args): String = args.result
18+
override suspend fun execute(args: Args): String = args.result
1919
}

examples/demo-compose-app/commonApp/src/commonMain/kotlin/com/jetbrains/example/koog/compose/agents/weather/WeatherAgentProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ internal class WeatherAgentProvider(private val provideLLMClient: suspend () ->
132132
) {
133133
handleEvents {
134134
onToolCallStarting { ctx ->
135-
onToolCallEvent("Tool ${ctx.tool.name}, args ${ctx.toolArgs}")
135+
onToolCallEvent("Tool ${ctx.toolName}, args ${ctx.toolArgs}")
136136
}
137137

138138
onAgentExecutionFailed { ctx ->

examples/demo-compose-app/commonApp/src/commonMain/kotlin/com/jetbrains/example/koog/compose/agents/weather/WeatherTools.kt

Lines changed: 69 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.jetbrains.example.koog.compose.agents.weather
22

33
import ai.koog.agents.core.tools.Tool
4-
import ai.koog.agents.core.tools.ToolResult
5-
import ai.koog.agents.core.tools.ToolResultUtils
64
import ai.koog.agents.core.tools.annotations.LLMDescription
75
import kotlinx.datetime.DateTimePeriod
86
import kotlinx.datetime.LocalDate
@@ -12,7 +10,6 @@ import kotlinx.datetime.offsetAt
1210
import kotlinx.datetime.plus
1311
import kotlinx.datetime.toInstant
1412
import kotlinx.datetime.toLocalDateTime
15-
import kotlinx.serialization.KSerializer
1613
import kotlinx.serialization.SerialName
1714
import kotlinx.serialization.Serializable
1815
import kotlin.time.Clock
@@ -46,7 +43,12 @@ sealed interface WeatherTools {
4643
class CurrentDatetimeTool(
4744
val defaultTimeZone: TimeZone = UTC_ZONE,
4845
val clock: Clock = CLOCK,
49-
) : Tool<CurrentDatetimeTool.Args, CurrentDatetimeTool.Result>() {
46+
) : Tool<CurrentDatetimeTool.Args, CurrentDatetimeTool.Result>(
47+
argsSerializer = Args.serializer(),
48+
resultSerializer = Result.serializer(),
49+
name = "current_datetime",
50+
description = "Get the current date and time in the specified timezone"
51+
) {
5052
@Serializable
5153
data class Args(
5254
@property:LLMDescription("The timezone to get the current date and time in (e.g., 'UTC', 'America/New_York', 'Europe/London'). Defaults to UTC.")
@@ -59,17 +61,7 @@ sealed interface WeatherTools {
5961
val date: String,
6062
val time: String,
6163
val timezone: String
62-
) : ToolResult.TextSerializable() {
63-
override fun textForLLM(): String {
64-
return "Current datetime: $datetime, Date: $date, Time: $time, Timezone: $timezone"
65-
}
66-
}
67-
68-
override val argsSerializer = Args.serializer()
69-
override val resultSerializer: KSerializer<Result> = ToolResultUtils.toTextSerializer<Result>()
70-
71-
override val name = "current_datetime"
72-
override val description = "Get the current date and time in the specified timezone"
64+
)
7365

7466
override suspend fun execute(args: Args): Result {
7567
val zoneId = try {
@@ -94,6 +86,10 @@ sealed interface WeatherTools {
9486
timezone = zoneId.id
9587
)
9688
}
89+
90+
override fun encodeResultToString(result: Result): String {
91+
return "Current datetime: ${result.datetime}, Date: ${result.date}, Time: ${result.time}, Timezone: ${result.timezone}"
92+
}
9793
}
9894

9995
/**
@@ -102,7 +98,12 @@ sealed interface WeatherTools {
10298
class AddDatetimeTool(
10399
val defaultTimeZone: TimeZone = UTC_ZONE,
104100
val clock: Clock = CLOCK,
105-
) : Tool<AddDatetimeTool.Args, AddDatetimeTool.Result>() {
101+
) : Tool<AddDatetimeTool.Args, AddDatetimeTool.Result>(
102+
argsSerializer = Args.serializer(),
103+
resultSerializer = Result.serializer(),
104+
name = "add_datetime",
105+
description = "Add a duration to a date. Use this tool when you need to calculate offsets, such as tomorrow, in two days, etc."
106+
) {
106107
@Serializable
107108
data class Args(
108109
@property:LLMDescription("The date to add to in ISO format (e.g., '2023-05-20')")
@@ -122,43 +123,7 @@ sealed interface WeatherTools {
122123
val daysAdded: Int,
123124
val hoursAdded: Int,
124125
val minutesAdded: Int
125-
) : ToolResult.TextSerializable() {
126-
override fun textForLLM(): String {
127-
return buildString {
128-
append("Date: $date")
129-
if (originalDate.isBlank()) {
130-
append(" (starting from today)")
131-
} else {
132-
append(" (starting from $originalDate)")
133-
}
134-
135-
if (daysAdded != 0 || hoursAdded != 0 || minutesAdded != 0) {
136-
append(" after adding")
137-
138-
if (daysAdded != 0) {
139-
append(" $daysAdded days")
140-
}
141-
142-
if (hoursAdded != 0) {
143-
if (daysAdded != 0) append(",")
144-
append(" $hoursAdded hours")
145-
}
146-
147-
if (minutesAdded != 0) {
148-
if (daysAdded != 0 || hoursAdded != 0) append(",")
149-
append(" $minutesAdded minutes")
150-
}
151-
}
152-
}
153-
}
154-
}
155-
156-
override val argsSerializer = Args.serializer()
157-
override val resultSerializer = ToolResultUtils.toTextSerializer<Result>()
158-
159-
override val name = "add_datetime"
160-
override val description =
161-
"Add a duration to a date. Use this tool when you need to calculate offsets, such as tomorrow, in two days, etc."
126+
)
162127

163128
override suspend fun execute(args: Args): Result {
164129
val baseDate = if (args.date.isNotBlank()) {
@@ -193,6 +158,35 @@ sealed interface WeatherTools {
193158
minutesAdded = args.minutes
194159
)
195160
}
161+
162+
override fun encodeResultToString(result: Result): String {
163+
return buildString {
164+
append("Date: ${result.date}")
165+
if (result.originalDate.isBlank()) {
166+
append(" (starting from today)")
167+
} else {
168+
append(" (starting from ${result.originalDate})")
169+
}
170+
171+
if (result.daysAdded != 0 || result.hoursAdded != 0 || result.minutesAdded != 0) {
172+
append(" after adding")
173+
174+
if (result.daysAdded != 0) {
175+
append(" ${result.daysAdded} days")
176+
}
177+
178+
if (result.hoursAdded != 0) {
179+
if (result.daysAdded != 0) append(",")
180+
append(" ${result.hoursAdded} hours")
181+
}
182+
183+
if (result.minutesAdded != 0) {
184+
if (result.daysAdded != 0 || result.hoursAdded != 0) append(",")
185+
append(" ${result.minutesAdded} minutes")
186+
}
187+
}
188+
}
189+
}
196190
}
197191

198192
/**
@@ -201,7 +195,12 @@ sealed interface WeatherTools {
201195
class WeatherForecastTool(
202196
private val openMeteoClient: OpenMeteoClient = OpenMeteoClient(),
203197
val defaultTimeZone: TimeZone = UTC_ZONE
204-
) : Tool<WeatherForecastTool.Args, WeatherForecastTool.Result>() {
198+
) : Tool<WeatherForecastTool.Args, WeatherForecastTool.Result>(
199+
argsSerializer = Args.serializer(),
200+
resultSerializer = Result.serializer(),
201+
name = "weather_forecast",
202+
description = "Get a weather forecast for a location with specified granularity (daily or hourly)"
203+
) {
205204
@Serializable
206205
data class Args(
207206
@property:LLMDescription("The location to get the weather forecast for (e.g., 'New York', 'London', 'Paris')")
@@ -221,28 +220,7 @@ sealed interface WeatherTools {
221220
val forecast: String,
222221
val date: String,
223222
val granularity: Granularity
224-
) : ToolResult.TextSerializable() {
225-
override fun textForLLM(): String {
226-
val granularityText = when (granularity) {
227-
Granularity.DAILY -> "daily"
228-
Granularity.HOURLY -> "hourly"
229-
}
230-
val dateInfo = if (date.isBlank()) "starting from today" else "for $date"
231-
val formattedLocation = if (locationCountry.isNullOrBlank()) {
232-
locationName
233-
} else {
234-
"$locationName, $locationCountry"
235-
}.trim().trimEnd(',')
236-
237-
return "Weather forecast for $formattedLocation ($granularityText, $dateInfo):\n$forecast"
238-
}
239-
}
240-
241-
override val argsSerializer = Args.serializer()
242-
override val resultSerializer = ToolResultUtils.toTextSerializer<Result>()
243-
244-
override val name = "weather_forecast"
245-
override val description = "Get a weather forecast for a location with specified granularity (daily or hourly)"
223+
)
246224

247225
override suspend fun execute(args: Args): Result {
248226
// Search for the location
@@ -371,5 +349,20 @@ sealed interface WeatherTools {
371349
else -> "Unknown"
372350
}
373351
}
352+
353+
override fun encodeResultToString(result: Result): String {
354+
val granularityText = when (result.granularity) {
355+
Granularity.DAILY -> "daily"
356+
Granularity.HOURLY -> "hourly"
357+
}
358+
val dateInfo = if (result.date.isBlank()) "starting from today" else "for ${result.date}"
359+
val formattedLocation = if (result.locationCountry.isNullOrBlank()) {
360+
result.locationName
361+
} else {
362+
"${result.locationName}, ${result.locationCountry}"
363+
}.trim().trimEnd(',')
364+
365+
return "Weather forecast for $formattedLocation ($granularityText, $dateInfo):\n${result.forecast}"
366+
}
374367
}
375368
}

examples/demo-compose-app/gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ javaVersion = "17"
88
jetbrains-lifecycle = "2.9.6"
99
jetbrains-navigation = "2.9.1"
1010
koin-bom = "4.1.1"
11-
koog = "0.5.2"
11+
koog = "0.6.0"
1212
kotlin = "2.2.21"
1313
kotlinx-coroutines = "1.10.2"
1414
kotlinx-datetime = "0.7.1-0.6.x-compat"

0 commit comments

Comments
 (0)