Skip to content

Commit 4ba6a8c

Browse files
authored
Merge branch 'main' into lazy-init
2 parents d7b014e + 6975149 commit 4ba6a8c

File tree

183 files changed

+8184
-4304
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

183 files changed

+8184
-4304
lines changed

.github/workflows/checks.yml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# This workflow uses actions that are not certified by GitHub.
2+
# They are provided by a third-party and are governed by
3+
# separate terms of service, privacy policy, and support
4+
# documentation.
5+
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
6+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
7+
8+
name: Checks
9+
10+
on:
11+
push:
12+
branches: [ "main" ]
13+
pull_request:
14+
branches: [ "main" ]
15+
16+
jobs:
17+
compilation:
18+
19+
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read
22+
23+
steps:
24+
- name: Configure Git
25+
run: |
26+
git config --global core.autocrlf input
27+
- uses: actions/checkout@v4
28+
- name: Set up JDK 17
29+
uses: actions/setup-java@v4
30+
with:
31+
java-version: '17'
32+
distribution: 'corretto'
33+
34+
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
35+
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
36+
- name: Setup Gradle
37+
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
38+
39+
- name: Assemble with Gradle Wrapper
40+
run: ./gradlew assemble
41+
42+
- name: TestClasses with Gradle Wrapper
43+
run: ./gradlew jvmTestClasses jsTestClasses
44+
45+
tests:
46+
47+
runs-on: ${{ matrix.os }}
48+
permissions:
49+
contents: read
50+
51+
strategy:
52+
matrix:
53+
os: [ ubuntu-latest, windows-latest ]
54+
55+
steps:
56+
- name: Configure Git
57+
run: |
58+
git config --global core.autocrlf input
59+
- uses: actions/checkout@v4
60+
- name: Set up JDK 17
61+
uses: actions/setup-java@v4
62+
with:
63+
java-version: '17'
64+
distribution: 'corretto'
65+
66+
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
67+
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
68+
- name: Setup Gradle
69+
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
70+
71+
- name: JvmTest with Gradle Wrapper
72+
env:
73+
JB_SPACE_CLIENT_ID: ${{ secrets.JB_SPACE_CLIENT_ID }}
74+
JB_SPACE_CLIENT_SECRET: ${{ secrets.JB_SPACE_CLIENT_SECRET }}
75+
USER_STGN_JWT_TOKEN: ${{ secrets.USER_STGN_JWT_TOKEN }}
76+
run: ./gradlew jvmTest --continue
77+
78+
- name: Collect reports
79+
if: always()
80+
uses: actions/upload-artifact@v4
81+
with:
82+
name: reports-${{ matrix.os }}
83+
path: |
84+
**/build/reports/

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.gradle
22
.idea
33
.kotlin
4-
build
4+
build
5+
**/.claude/settings.local.json

CLAUDE.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This repository contains the Koan Agents framework, a Kotlin multiplatform library for building AI agents. The framework enables creating intelligent agents that interact with tools, handle complex workflows, and maintain context across conversations.
8+
9+
## Building and Testing
10+
11+
### Basic Commands
12+
13+
```bash
14+
# Build the project
15+
./gradlew assemble
16+
17+
# Compile test classes
18+
./gradlew jvmTestClasses jsTestClasses
19+
20+
# Run all JVM tests
21+
./gradlew jvmTest
22+
23+
# Run all JS tests
24+
./gradlew jsTest
25+
26+
# Run a specific test class
27+
./gradlew jvmTest --tests "fully.qualified.TestClassName"
28+
# Example:
29+
./gradlew jvmTest --tests "ai.grazie.code.agents.test.SimpleAgentIntegrationTest"
30+
31+
# Run a specific test method
32+
./gradlew jvmTest --tests "fully.qualified.TestClassName.testMethodName"
33+
# Example:
34+
./gradlew jvmTest --tests "ai.grazie.code.agents.test.SimpleAgentIntegrationTest.simpleChatAgent should call default tools"
35+
```
36+
37+
## Architecture
38+
39+
### Key Modules
40+
41+
1. **agents-core**: Core abstractions and interfaces
42+
- AIAgent, AIAgentStrategy, event handling system
43+
44+
2. **agents-core-tools**: Tool infrastructure
45+
- Tool, ToolRegistry, ToolDescriptor
46+
47+
3. **agents-local**: Local execution implementation
48+
- KotlinAIAgent, execution strategies, session management
49+
50+
4. **agents-local-features**: Extensible agent capabilities
51+
- Memory, tracing, and other features
52+
53+
5. **prompt**: LLM interaction layer
54+
- LLM executors, prompt construction, structured data processing
55+
56+
### Core Concepts
57+
58+
- **Agents**: State-machine graphs with nodes that process inputs and produce outputs
59+
- **Tools**: Encapsulated actions with standardized interfaces
60+
- **Strategies**: Define agent behavior and execution flow
61+
- **Features**: Installable extensions that enhance agent capabilities
62+
- **Event Handling**: System for intercepting and processing agent lifecycle events
63+
64+
### Implementation Pattern
65+
66+
1. Define tools that agents can use
67+
2. Register tools in the ToolRegistry
68+
3. Configure agent with strategy
69+
4. Set up communication (if integrating with external systems)
70+
71+
## Testing
72+
73+
The project has extensive testing support:
74+
75+
- **Mocking LLM responses**:
76+
```kotlin
77+
val mockLLMApi = getMockExecutor(toolRegistry, eventHandler) {
78+
mockLLMAnswer("Hello!") onRequestContains "Hello"
79+
mockLLMToolCall(CreateTool, CreateTool.Args("solve")) onRequestEquals "Solve task"
80+
}
81+
```
82+
83+
- **Mocking tool calls**:
84+
```kotlin
85+
mockTool(PositiveToneTool) alwaysReturns "The text has a positive tone."
86+
```
87+
88+
- **Testing agent graph structure**:
89+
```kotlin
90+
testGraph {
91+
assertStagesOrder("first", "second")
92+
// ...
93+
}
94+
```
95+
96+
For detailed testing guidelines, refer to `agents/TESTING.md`.

agents/README.md

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ To start working with IdeFormer in your project, you will need:
6464
- `ai.jetbrains.code.agents`
6565
- [agents-core](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.agents/agents-core)
6666
- [agents-core-tools](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.agents/agents-core-tools)
67-
- [agents-tools-registry](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.agents/agents-tools-registry)
68-
- [code-agents-ideformer-client](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.agents/code-agents-ideformer-client)
69-
- [code-agents-ideformer-daemon](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.agents/code-agents-ideformer-daemon)
70-
- [code-agents-ideformer-executable](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.agents/code-agents-ideformer-executable)
7167
- `ai.jetbrains.code.files`
7268
- [code-files-jvm](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.files/code-files-jvm)
7369
- [code-files-model](https://jetbrains.team/p/grazi/packages/maven/grazie-platform-public/ai.jetbrains.code.files/code-files-model)
@@ -466,17 +462,3 @@ and ensuring proper communication with the IdeFormer service.
466462
This framework is flexible and allows you to customize the tools and the agent's logic for any arbitrary use case.
467463
Feel free to extend it to suit more complex scenarios, such as multi-stage processes, integrating additional tools,
468464
or handling different types of events and exceptions.
469-
470-
[^1]:
471-
The required version for these dependencies is influenced by the version of `code-engine` you are using.
472-
For example, if you are using `1.0.0-beta.26+0.4.16`, then you will need either `0.4.16` or later patches.
473-
474-
[^2]:
475-
Defining tool descriptors in code is good for fast experiments, but for production purposes this method is not recommended.
476-
Please contribute to `GlobalAgentToolsRegistry.Tools` and then feel free to use the `fromRegistry` method instead.
477-
You can read more about contributing [here](https://github.com/JetBrains/koan-agents/tree/main/agents/agents-tools-registry#contributing-tools).
478-
479-
[^3]:
480-
Writing prompts in code is good for fast experiments, but for production purposes this method is not recommended.
481-
Please contribute to `GlobalAgentToolsRegistry.Prompts` and then feel free to use `fromRegistry` method.
482-
You can read more about contributing [here](https://github.com/JetBrains/koan-agents/tree/main/agents/agents-tools-registry#contributing-prompts).

agents/TESTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ fun testMultiStageAgentStructure() = runBlocking {
452452
mockLLMToolCall(CreateTool, CreateTool.Args("solve")) onRequestEquals "Solve task"
453453
}
454454

455-
val basePrompt = prompt(JetBrainsAIModels.OpenAI.GPT4oMini, "test") {}
455+
val basePrompt = prompt(OpenAIModels.GPT4o, "test") {}
456456

457457
KotlinAIAgent(
458458
toolRegistry = toolRegistry,

agents/agents-core-tools/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ kotlin {
1616
}
1717
}
1818

19+
jvmMain {
20+
dependencies {
21+
implementation(kotlin("reflect"))
22+
}
23+
}
24+
1925
commonTest {
2026
dependencies {
2127
implementation(kotlin("test"))
@@ -26,6 +32,7 @@ kotlin {
2632
jvmTest {
2733
dependencies {
2834
implementation(kotlin("test-junit5"))
35+
implementation(libs.junit.jupiter.params)
2936
}
3037
}
3138
}

agents/agents-core-tools/src/commonMain/kotlin/ai/grazie/code/agents/core/tools/Tool.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package ai.grazie.code.agents.core.tools
22

3-
import ai.grazie.code.agents.core.tools.serialization.JsonForTool
3+
import ai.grazie.code.agents.core.tools.serialization.ToolJson
44
import kotlinx.serialization.KSerializer
55
import kotlinx.serialization.Serializable
66
import kotlinx.serialization.json.JsonObject
@@ -167,29 +167,29 @@ abstract class Tool<TArgs : Tool.Args, TResult : ToolResult> {
167167
* @param args The arguments to be encoded.
168168
* @return A JsonObject representing the encoded arguments.
169169
*/
170-
fun encodeArgs(args: TArgs): JsonObject = JsonForTool.encodeToJsonElement(argsSerializer, args).jsonObject
170+
fun encodeArgs(args: TArgs): JsonObject = ToolJson.encodeToJsonElement(argsSerializer, args).jsonObject
171171
/**
172172
* Encodes the provided arguments into a JSON string representation using the configured serializer.
173173
*
174174
* @param args the arguments to be encoded into a JSON string
175175
* @return the JSON string representation of the provided arguments
176176
*/
177-
fun encodeArgsToString(args: TArgs): String = JsonForTool.encodeToString(argsSerializer, args)
177+
fun encodeArgsToString(args: TArgs): String = ToolJson.encodeToString(argsSerializer, args)
178178

179179
/**
180180
* Decodes the provided raw JSON arguments into an instance of the specified arguments type.
181181
*
182182
* @param rawArgs the raw JSON object that contains the encoded arguments
183183
* @return the decoded arguments of type TArgs
184184
*/
185-
fun decodeArgs(rawArgs: JsonObject): TArgs = JsonForTool.decodeFromJsonElement(argsSerializer, rawArgs)
185+
fun decodeArgs(rawArgs: JsonObject): TArgs = ToolJson.decodeFromJsonElement(argsSerializer, rawArgs)
186186
/**
187187
* Decodes a raw string representation of arguments into the corresponding object of type TArgs.
188188
*
189189
* @param rawArgs The raw string containing the encoded arguments.
190190
* @return The decoded arguments as an instance of type TArgs.
191191
*/
192-
fun decodeArgsFromString(rawArgs: String): TArgs = JsonForTool.decodeFromString(argsSerializer, rawArgs)
192+
fun decodeArgsFromString(rawArgs: String): TArgs = ToolJson.decodeFromString(argsSerializer, rawArgs)
193193

194194

195195
/**
Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package ai.grazie.code.agents.core.tools
22

3-
import kotlinx.serialization.KSerializer
4-
import kotlinx.serialization.builtins.ListSerializer
5-
import kotlinx.serialization.builtins.serializer
3+
64
import kotlin.enums.EnumEntries
75

86
/**
@@ -19,8 +17,8 @@ import kotlin.enums.EnumEntries
1917
data class ToolDescriptor(
2018
val name: String,
2119
val description: String,
22-
val requiredParameters: List<ToolParameterDescriptor<*>> = emptyList(),
23-
val optionalParameters: List<ToolParameterDescriptor<*>> = emptyList(),
20+
val requiredParameters: List<ToolParameterDescriptor> = emptyList(),
21+
val optionalParameters: List<ToolParameterDescriptor> = emptyList(),
2422
)
2523

2624
/**
@@ -37,11 +35,8 @@ data class ToolDescriptor(
3735
* @property type The data type of the tool parameter.
3836
* @property defaultValue The default value of the tool parameter (nullable).
3937
*/
40-
data class ToolParameterDescriptor<T>(
41-
val name: String,
42-
val description: String,
43-
val type: ToolParameterType<T>,
44-
val defaultValue: T? = null
38+
data class ToolParameterDescriptor(
39+
val name: String, val description: String, val type: ToolParameterType
4540
)
4641

4742
/**
@@ -52,58 +47,48 @@ data class ToolParameterDescriptor<T>(
5247
* @param T The type of data that the tool parameter represents.
5348
* @property name The name associated with the type of tool parameter.
5449
*/
55-
sealed class ToolParameterType<T>(val name: kotlin.String) {
56-
/**
57-
* Describes how to serialize default value for a given type
58-
*/
59-
internal abstract val serializer: KSerializer<T>
50+
sealed class ToolParameterType(val name: kotlin.String) {
6051

6152
/**
6253
* Represents a string type parameter.
6354
*/
64-
data object String : ToolParameterType<kotlin.String>("STRING") {
65-
override val serializer = kotlin.String.serializer()
66-
}
55+
data object String : ToolParameterType("STRING")
6756

6857
/**
6958
* Represents an integer type parameter.
7059
*/
71-
data object Integer : ToolParameterType<Int>("INT") {
72-
override val serializer = Int.serializer()
73-
}
60+
data object Integer : ToolParameterType("INT")
7461

7562
/**
7663
* Represents a float type parameter.
7764
*/
78-
data object Float : ToolParameterType<kotlin.Float>("FLOAT") {
79-
override val serializer = kotlin.Float.serializer()
80-
}
81-
65+
data object Float : ToolParameterType("FLOAT")
8266
/**
8367
* Represents a boolean type parameter.
8468
*/
85-
data object Boolean : ToolParameterType<kotlin.Boolean>("BOOLEAN") {
86-
override val serializer = kotlin.Boolean.serializer()
87-
}
69+
data object Boolean : ToolParameterType("BOOLEAN")
8870

8971
/**
9072
* Represents an enum type parameter.
9173
*
9274
* @param E The specific enumeration type handled by this parameter type.
9375
* @property entries The entries for the enumeration, allowing the parameter to be one of these values.
9476
*/
95-
data class Enum<E : kotlin.Enum<E>>(
96-
val entries: EnumEntries<E>,
97-
override val serializer: KSerializer<E>
98-
) : ToolParameterType<E>("ENUM")
77+
data class Enum(
78+
val entries: Array<kotlin.String>,
79+
) : ToolParameterType("ENUM")
9980

10081
/**
10182
* Represents an array type parameter.
10283
*
10384
* @param T The type of each item within the array.
10485
* @property itemsType The type definition for the items within the array.
10586
*/
106-
data class List<T>(val itemsType: ToolParameterType<T>) : ToolParameterType<kotlin.collections.List<T>>("ARRAY") {
107-
override val serializer = ListSerializer(itemsType.serializer)
87+
data class List(val itemsType: ToolParameterType) : ToolParameterType("ARRAY")
88+
89+
companion object {
90+
fun Enum(entries: EnumEntries<*>): Enum = Enum(entries.map { it.name }.toTypedArray())
91+
fun Enum(entries: Array<kotlin.Enum<*>>): Enum = Enum(entries.map { it.name }.toTypedArray())
10892
}
10993
}
94+

0 commit comments

Comments
 (0)