JetBrains-Research/kotlinllm-plugin
GitHub: JetBrains-Research/kotlinllm-plugin
KotlinLLM 是一个 IntelliJ IDEA 插件原型,通过 LLM agent 在 Kotlin/JVM 项目运行时按需生成代码、编译并热重载,将学习到的行为持久化为可移植的 Kotlin 源代码。
Stars: 89 | Forks: 4
# KotlinLLM IntelliJ 插件
KotlinLLM 是一个 IntelliJ IDEA 插件原型,用于在 Kotlin/JVM 项目中试验 **Smart macros**。Smart macro 是一个显式的 Kotlin 调用,其行为由生成的 Kotlin 源代码提供支持。当运行中的应用程序遇到不支持的场景时,该插件可以捕获运行时值,请求 LLM agent 生成一个窄范围的实现更新,编译更改后的源代码,并通过 JDI 热重载受影响的类。
其设计目标是:由 LLM 支持的行为在调用处应当是显式的,作为源代码是持久化的,并且在生成后作为普通的 Kotlin 代码是可移植的。
## Smart Macros
公共 API 暴露了两个 Smart macro:
- `asLlm(from, hint)` 将类型为 `F` 的值转换为类型为 `T` 的值。
- `mockLlm()` 创建接口 `T` 的一个实现,其行为可以从运行时交互中演进。
与直接将运行时委托给 LLM 服务不同,KotlinLLM 不会在每次调用 Smart macro 时都调用模型。当生成的代码尚无法处理某个场景时,才会使用 LLM。成功的行为会被存储在生成的 Kotlin 文件中,后续运行将直接执行该代码。
## 架构
KotlinLLM 具有三个层级:
- **公共 API**:目标项目使用的稳定的 `asLlm` 和 `mockLlm` 函数。
- **静态基础设施**:将 Smart macro 调用路由到生成的 provider 的管理器。
- **动态基础设施**:由插件维护的生成的 bootstrap、provider、parser 和 mock 类。
目标项目同时拥有静态 API 文件和生成的源代码文件夹。插件会在应用程序运行之前及运行期间准备并更新动态基础设施。
## 运行时流程
当通过 KotlinLLM 运行配置启动项目时:
1. 插件扫描 Kotlin 项目以查找 `asLlm` 和 `mockLlm` 调用。
2. 它创建或更新生成的 bootstrap、provider、parser 和 mock 文件。
3. 它在 JDI 下启动原始的运行配置。
4. 它在生成的 regenerate hook 上注册断点。
5. 如果生成的逻辑与运行时场景不匹配,执行将到达一个 regenerate hook。
6. 插件从挂起的栈帧中捕获运行时值和类型信息。
7. LLM agent 接收到专门的工具,用于读取值、grep 大型输入、检查目标类型以及提交代码更新。
8. 插件将更新插入到生成的 Kotlin 源代码中,对其进行编译,并重新定义已加载的类。
9. 使用更新后的实现重试原始应用程序调用。
## 插件开发设置
要求:
- IntelliJ IDEA 2025.2.x。Gradle 目标为 `intellijIdea("2025.2.4")`。
- JDK 21。
- 通过 `Tools > KotlinLLM Settings` 保存在目标项目 `.kotlinllm` 文件中的 OpenAI API 密钥。
构建插件:
```
./gradlew compileKotlin --no-daemon
```
运行测试:
```
./gradlew test
```
在沙箱 IDE 中运行插件:
```
./gradlew runIde
```
你也可以从 IntelliJ 中运行 Gradle 的 `runIde` 任务。通过 `Tools > KotlinLLM Settings` 配置目标项目的 `.kotlinllm` 文件;当插件请求 Koog/OpenAI 生成实现时,它会从该文件中读取 API 密钥。
## 目标项目设置
目标 Kotlin/JVM 项目必须包含稳定的 Smart macro API 文件。本仓库将其作为 [templates/KotlinLLM.kt](templates/KotlinLLM.kt) 包含在内。
将其复制到目标项目的 `com.jetbrains.kotlinllm` 包中。示例将此文件放置在:
```
src/main/kotlin/com/jetbrains/kotlinllm/KotlinLlm.kt
```
要进行成功的 `Run with KotlinLLM`,必须要有此 `KotlinLlm.kt` 文件:它定义了 `asLlm`、`mockLlm` 以及生成代码所使用的运行时管理器。
然后就可以从应用程序代码中使用该 API:
```
import com.jetbrains.kotlinllm.asLlm
import com.jetbrains.kotlinllm.mockLlm
val apiUrl: String = asLlm("JetBrains/kotlin", hint = "Return a GitHub issues API URL")
val service: GithubService = mockLlm()
```
`mockLlm()` 适用于接口。插件会为该接口生成一个实现类,并根据观察到的运行时调用来演进方法体。
## 示例项目
- [GithubIssueRadar](examples/GithubIssueRadar) 是一个独立的 Kotlin/JVM 示例,它使用 `asLlm` 推导 GitHub issues API URL,解析 GitHub issue JSON,并对适合新手的 issue 标签进行分类。它包含生成的 KotlinLLM 源代码,因此可以将学习到的行为作为普通的 Kotlin 进行检查和运行。通过插件运行该示例时,请将示例内的 `.kotlinllm.example` 复制为 `.kotlinllm` 并填入 `apiKey`。
## 初始化 KotlinLLM
每个目标项目都需要一个生成源代码的位置和一个 builds 文件夹。在首次运行前初始化它们:
1. 在沙箱 IDE 中打开目标项目。
2. 运行 `Tools > KotlinLLM Settings`,或使用 KotlinLLM 工具栏操作。
3. 输入 API 密钥,选择一个现有的 Kotlin 源代码根目录(通常是 `src/main/kotlin`),并指定用于热重载类发现的 builds 文件夹。
必须指定 builds 文件夹。在 `Run with KotlinLLM` 期间,KotlinLLM 使用它来查找编译后的类文件以进行热重载。
设置会使用项目相对路径(包括 `generatedFolder` 和 `buildsFolder`)写入目标项目中的 `.kotlinllm` 文件。使用隐藏的 Advanced 部分在以下位置初始化生成的文件:
```
src/main/kotlin/com/jetbrains/kotlinllm/generated
|-- core
|-- asLlm
`-- mockLlm
```
`core` 中生成的运行时文件使用 `com.jetbrains.kotlinllm.generated.core` 包,并将 provider 安装到 `AsLlmManager` 和 `MockLlmManager` 中。Parser 实现写在 `asLlm` 下,使用包 `com.jetbrains.kotlinllm.generated.asLlm`;mock 实现写在 `mockLlm` 下,使用包 `com.jetbrains.kotlinllm.generated.mockLlm`。API 文件会在首次调用 `asLlm` 或 `mockLlm` 时延迟加载 `com.jetbrains.kotlinllm.generated.core.KotlinLlmBootstrap`,因此应用程序代码不需要手动调用 bootstrap。
你也可以在 Project 视图中右键单击文件夹并选择 `Set KotlinLLM Folder`。如果项目缺少生成的源代码根目录或 builds 文件夹,首次尝试 `Run with KotlinLLM` 时会在启动继续前提示进行必要的设置。
## 运行目标应用程序
首先为目标应用程序创建一个普通的 IntelliJ 运行配置。然后使用自定义执行器启动它:
- 从工具栏或运行上下文菜单中使用 `Run with KotlinLLM`。
- 当你希望进行 Smart macro 生成时,请不要使用普通的 Run 操作。
插件拥有启动控制权,因此它可以运行启动前任务、准备生成的文件、通过 JDI attach、注册 regenerate-hook 断点、编译更新以及重新定义运行中 VM 内的类。
在启动期间,控制台应显示:
```
KotlinLLM: Running before-launch task 'Build'...
KotlinLLM: Ready. Monitoring for asLlm and mockLlm calls...
```
当执行到达不受支持的 Smart macro 场景时,KotlinLLM 会捕获挂起的栈帧,请求 LLM agent 进行源代码更新,编译更改后的生成文件,热重载该类,并重试原始应用程序调用。
## 生成的文件
插件在以下位置创建生成的源代码:
```
com.jetbrains.kotlinllm.generated.core
```
生成的文件包括:
- `KotlinLlmBootstrap`,它将生成的 provider 安装到 `AsLlmManager` 和 `MockLlmManager` 中。
- 生成的 provider,它们通过 `KType` 分发 Smart macro 调用。
- 生成的 `asLlm` parser 类。
- 生成的 `mockLlm` 实现。
这些文件是普通的 Kotlin 源代码文件。一旦生成了行为,目标项目就可以编译并运行该行为,而无需针对同一场景再次发起 LLM 请求。
## 注意事项
- KotlinLLM 面向 Kotlin/JVM,因为运行时演进循环依赖于通过 JDI 进行的 JVM 类重定义。
- 生成的更新是刻意收窄的:LLM agent 仅更新准备好的实现主体,而不是更改任意的项目文件。
- 如果生成的实现不匹配新的运行时场景,它应该 fall through 到 regenerate hook,而不是静默返回错误的值。
- 生成的源代码是项目的一部分,当学习到的行为需要具备可移植性时,可以将其提交。
## 许可证
KotlinLLM 采用 Apache License 2.0 授权。这使得项目对插件用户和贡献者保持宽松,同时保留版权声明并提供明确的专利授权。
标签:DLL 劫持, IntelliJ IDEA, Kotlin, Petitpotam, 代码生成, 后台面板检测, 大语言模型, 渗透测试工具, 热重载, 集成开发环境插件