Kilo JetBrains 插件 Context 设置页实现:基于共享 kilo.json 的压缩与文件监视配置 UI
2026/9/11 10:21:45 网站建设 项目流程

Kilo JetBrains 插件 Context 设置页实现:基于共享 kilo.json 的压缩与文件监视配置 UI

【免费下载链接】kilocodeKilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kilocode

导读

本文完整讲解 Kilo 开源仓库中 JetBrains 插件新增Context 设置页Settings -> Tools -> Kilo Code -> Context)的实现方案。该页面围绕共享配置kilo.json中的compaction(自动压缩)与watcher(文件监视忽略)两组键,为 JetBrains 端补齐与 VS Code 对齐的 UI 入口。读完本文,你将掌握:Context 四个配置项在共享 DTO、后端 CLI 解析器、前端草稿状态与 Swing 设置页之间的完整数据流,以及显式null清空、布尔false序列化、字符串数组编辑等易错细节的处理方式。

一、背景:JetBrains ↔ VS Code 设置对齐中的“轻松赢项”

Kilo 的双端(VS Code 与 JetBrains)客户端都通过 CLI 编辑同一份共享kilo.json。这意味着:只要某项设置的行为完全由 CLI 承担,JetBrains 端就只需要一个写配置键的 UI 行即可,无需改动 CLI,也无需新增运行时特性。源码层面,这一思路完整记录在 docs/jetbrains-vscode-settings-parity.md 中,其实现三件套是:

  1. 使用既有settings/base/原语(BaseSettingsUiSettingsRowSettingsToggleSettingsListPanel)新增一个Configurable页面,并在 kilo.jetbrains.frontend.xml 注册;
  2. 扩展 KiloCliDataParser.kt 中buildConfigPatch的键白名单(此前仅支持modelsmall_modelsubagent_modelsubagent_variantdefault_agent五个字符串键),并补充布尔/数字的 JSON 序列化能力;
  3. KiloBundle.properties中补充本地化文案。

Context 页属于 parity 文档中的Tier 1(真正轻松)档位:CLI 已完成所有工作,JetBrains 只需加 UI 与配置键。parity 文档同时划清了边界——索引(indexing)、沙箱(sandboxing)等“隐含启用新特性”的项不属于 easy win;snapshot(检查点)按建议放独立的 Checkpoints 页;本页也不包含 VS Code Context 标签页中的 memory/indexing 控件,因为 JetBrains 尚无对应的 memory/indexing 设置服务。

二、目标与范围:四个配置项

本计划在Settings -> Tools -> Kilo Code -> Context下提供四个设置项:

设置项配置键类型
自动压缩 Auto-compactioncompaction.autoboolean
压缩阈值百分比 Compaction threshold percentcompaction.threshold_percentnumber 或 null
压缩时剪枝 Prune on compactioncompaction.pruneboolean
文件监视忽略模式 Watcher ignore patternswatcher.ignorestring array

设计约束明确:首次实现只走全局配置写路径(复用既有 app 级设置写通道),不引入项目级配置;不为非字符串值重载ConfigPatchDto.values,而是新增类型化 DTO 字段watcher.ignore使用共享列表原语而不是自造增删控件。

三、Part A:共享 DTO——类型化读取与补丁

配置文件:KiloAppStateDto.kt。该文件当前已包含计划中定义的读取与补丁 DTO(ConfigDto已在 60-74 行接入watcher/compaction字段)。

读取侧 DTO:

@Serializable data class WatcherConfigDto( val ignore: List<String> = emptyList(), ) @Serializable data class CompactionConfigDto( val auto: Boolean? = null, val threshold_percent: Double? = null, val prune: Boolean? = null, )

补丁侧 DTO(ConfigPatchDto中对应字段为watcher: WatcherPatchDto? = nullcompaction: CompactionPatchDto? = null):

@Serializable data class WatcherPatchDto( val ignore: List<String>? = null, ) @Serializable data class CompactionPatchDto( val clear: List<String> = emptyList(), val auto: Boolean? = null, val threshold_percent: Double? = null, val prune: Boolean? = null, )

这套 DTO 形态背后是四个容易踩坑的语义约定,务必理解:

  • watcher.ignore = null表示不修改
  • watcher.ignore = emptyList()表示显式保存为空列表(删除最后一个模式时依赖此语义);
  • compaction.threshold_percent = null单独出现表示不修改
  • compaction.clear = listOf("threshold_percent")才表示真正清空——因为Double?无法区分“未提供”与“显式 null”,所以必须用独立的clear列表来发射 JSON"threshold_percent": null
  • 布尔false必须被序列化,绝不能把false当作“未提供”而省略。

四、Part B:后端解析器与序列化器

配置文件:KiloCliDataParser.kt。

4.1 解析 parseConfig

parseConfig(raw)读取GET /global/config响应,现已解析watcher.ignorecompaction.autocompaction.threshold_percentcompaction.prune。私有助手沿用既有风格(见 566-582 行):

  • 字符串用str(...)
  • 布尔用flagOrNull(...)(并包一层runCatching容错);
  • 数字用num(...)
  • 字符串数组用arr()?.mapNotNull { it.jsonPrimitive.contentOrNull }

parseConfig整体包在runCatching中,解析失败回退ConfigDto(),保证坏配置不会阻塞插件启动。

4.2 序列化 buildConfigPatch

buildConfigPatch(patch)生成PATCH /global/config请求体。Context 相关补丁的期望输出:

{ "watcher": { "ignore": ["**/node_modules/**"] }, "compaction": { "auto": true, "threshold_percent": 80, "prune": false } }

显式清空阈值时的输出:

{ "compaction": { "threshold_percent": null } }

实现要点:compaction块先按clear列表逐项写入JsonNull,再写入非空的新值;watcher块在ignore != null时整体发射数组。既有的values白名单继续只服务字符串模型键(model等五个),Context 值不经过values通道。

4.3 写路径调用链

Context 页的保存沿用的是既有全局配置写路径,从源码结构可以梳理出完整调用链:

  • 前端:KiloAppService.updateConfigAsync(...)(见 ContextSettingsUi.kt 第 79 行调用);
  • RPC:KiloAppRpcApi.updateConfig(patch: ConfigPatchDto)
  • 后端:KiloBackendAppService.updateConfig(...)
  • HTTP:PATCH /global/config,随后GET /global/config刷新回读。

五、Part C:前端状态模型——字符串化阈值草稿

状态文件:ContextSettingsState.kt。

internal data class ContextDraft( val auto: Boolean = false, val threshold: String = "", val prune: Boolean = false, val editor: Boolean = KiloPluginSettings.getAutoEditorContext(), val ignore: List<String> = emptyList(), )

关键设计:阈值在草稿中保持字符串,这样 UI 可以承载空串/非法中间输入而不丢失用户文本,只在构建补丁时才转换为数字。实际实现比计划多了一个本地editor字段(自动编辑器上下文),它走KiloPluginSettings本地持久化而非全局配置。

核心函数(均已实现):

  • contextDraft(config: ConfigDto?): ContextDraft——从回读配置生成基线草稿;formatThreshold会把整数 80.0 格式化为"80"
  • patch(from, to): ConfigPatchDto?——只发射变化字段,阈值非法时返回null
  • savedMatches(base, draft): Boolean——通过normalizeThreshold归一化后比较;
  • thresholdStatus(value)——空串合法;非数字、非有限数或超出0..100判为INVALID
  • compactionPatch(from, to)——内部按字段差异逐个生成补丁。

补丁行为约定(计划文档要求、实现已覆盖):

  • 用户关闭自动压缩 → 发射CompactionPatchDto(auto = false)
  • 用户关闭剪枝 → 发射CompactionPatchDto(prune = false)
  • 输入合法的非空数字 → 发射CompactionPatchDto(threshold_percent = 80.0)
  • 清空既有阈值 → 发射CompactionPatchDto(clear = listOf("threshold_percent"))
  • 删除最后一个忽略模式 → 发射WatcherPatchDto(ignore = emptyList())
  • 所有字段与基线一致 → 页面不产生任何变更。

六、Part D:前端 UI 页面

6.1 Configurable 注册类

ContextConfigurable.kt 镜像ModelsConfigurable

  • 继承DraftReadyConfigurable<JComponent>
  • ID = "ai.kilocode.jetbrains.settings.context"
  • getDisplayName()返回KiloBundle.message("settings.context.displayName")
  • create(cs)返回ContextSettingsUi(cs)

6.2 设置 UI

ContextSettingsUi.kt 继承BaseSettingsUi<ContextSettingsContent, ContextDraft, ConfigPatchDto, KiloAppStateDto, Unit>,职责映射:

  • save(change, done)app.updateConfigAsync(change, done),成功回调里同步写本地editor设置;
  • base(result)/draft(state)contextDraft(state.config)
  • saved(base, draft)savedMatches(...)
  • pendingText()/failedText()→ 对应settings.context.save.pending/settings.context.save.failed
  • loadWorkspace(root)/applyWorkspace(result)Unitmodels(state)Unit(本页不涉及工作区与模型状态);
  • syncContent()→ 根据 app 状态READYsaving标志更新控件可用性、字段值、保存进度遮罩与校验提示。

页面布局:Compaction 分区(自动压缩开关、阈值数字行、剪枝开关)+ Watcher ignore patterns 分区(列表编辑器)。控件选择遵循 AGENTS.md 的 UI 规则:布尔用SettingsToggle,阈值用JBTextField(配合DocumentFilter限制输入),忽略模式列表用JBList+CollectionListModel+ScrollingUtil.installActions,全部是 IntelliJ 平台组件而非裸 Swing。页面在 app 状态为 ready 且无保存挂起时可编辑,保存期间禁用控件。

6.3 校验规则

  • 空阈值合法,含义是“清空/复位该配置值”(若与基线不同则发射 clear);
  • 非数字阈值非法,阻止apply()发送补丁(patch()返回null);
  • 建议接受范围0..100,与 CLI 行为保持一致;
  • 校验信息通过既有设置消息机制呈现,不引入临时标签。

七、Part E:设置注册与根页导航

7.1 XML 注册

kilo.jetbrains.frontend.xml 中已注册子配置项(76-80 行):

<applicationConfigurable parentId="ai.kilocode.jetbrains.settings" id="ai.kilocode.jetbrains.settings.context" groupWeight="-1" instance="ai.kilocode.client.settings.context.ContextConfigurable" bundle="messages.KiloBundle" key="settings.context.displayName"/>

计划建议通过权重稳定顺序(User Profile=5、Models=4、Context=3、Providers=2、Agent Behavior=1);实际落地的 XML 以既有各页的groupWeight为准(Models=4、Providers=2、Agent Behavior=1,Context 取 -1,位于两者之间且紧随 Providers 之后)。若需调整显示顺序,改groupWeight即可。

7.2 根页导航

KiloSettingsConfigurable.kt 在根页 Models 与 Providers 之间新增指向ContextConfigurable.IDActionLink,文案使用settings.context.displayNameKiloSettingsSelection.kt无需改动,因为子页面 ID 已共享根前缀ai.kilocode.jetbrains.settings

八、Part F:本地化字符串

基础文案位于 KiloBundle.properties:

settings.context.displayName=Context settings.context.description=Configure compaction and file-watcher context behavior. settings.context.save.pending=Saving context settings... settings.context.save.failed=Failed to save context settings settings.context.compaction.title=Compaction settings.context.compaction.description=Control when Kilo summarizes long sessions to reduce context usage. settings.context.compaction.auto.title=Auto-compaction settings.context.compaction.auto.description=Automatically compact long conversations before they exceed the model context window. settings.context.compaction.threshold.title=Compaction threshold settings.context.compaction.threshold.description=Percent of the context window to use before auto-compaction starts. Leave blank to use the default. settings.context.compaction.threshold.invalid=Enter a number from 0 to 100, or leave the field blank. settings.context.compaction.prune.title=Prune on compaction settings.context.compaction.prune.description=Drop older raw conversation details after compaction to keep the session context smaller. settings.context.watcher.title=Watcher ignore patterns settings.context.watcher.description=Glob patterns Kilo should ignore when watching repository file changes. settings.context.watcher.add=Add pattern settings.context.watcher.empty=No ignore patterns configured. settings.context.watcher.placeholder=e.g. **/dist/** settings.context.watcher.remove=Remove {0}

当前仓库中这些键已同步复制进KiloBundle_zh_CNKiloBundle_jaKiloBundle_de等多语言 bundle(资源包检查要求每键在每语言包存在时,先复制英文值,翻译工作留给后续 i18n 批次)。用户可见字符串一律走*.properties,符合 AGENTS.md 的 UI 规则。

九、Part G:测试覆盖

计划与实现均强调“每个写设置的页面都需要 fake-RPC 前端测试 + MockCliServer 后端断言”这一仓库测试模式(见 packages/kilo-jetbrains/AGENTS.md 的 Settings Test Coverage Pattern)。

9.1 前端状态测试

ContextSettingsStateTest.kt 覆盖:草稿正确读取ConfigDto.watcher/compaction;未变更草稿不发射补丁;布尔变更正确发射false/true;设置阈值发射threshold_percent;清空阈值发射clear = listOf("threshold_percent");忽略列表增删发射完整新列表(含空列表);非法阈值在保存前被拒绝。

9.2 前端 UI 测试

ContextSettingsUiTest.kt 以ModelsSettingsUiTest为模板:BasePlatformTestCase+ 真实 EDT +FakeAppRpcApi+KiloAppService+flushUntil助手,断言交互后的rpc.configPatches、保存挂起期间控件禁用、保存失败后页面保持 modified 并显示settings.context.save.failed。配套 FakeAppRpcApi.kt 需要:应用patch.watcher/patch.compaction到假配置状态,保留显式空列表与布尔false,并按compaction.clear将对应字段置null

9.3 后端解析器与 app 服务测试

KiloCliDataParserTest.kt 增加精确 JSON 断言:parseConfig读取 watcher/compaction 字段;buildConfigPatch发射 ignore 数组、auto=falseprune=false、数字threshold_percent、以及clear含该字段时的显式"threshold_percent": null。KiloBackendAppServiceTest.kt 则调用updateConfig(ConfigPatchDto(watcher = ..., compaction = ...)),断言MockCliServer.lastConfigPatchBody与期望嵌套 JSON 完全一致,且回读的ConfigDto包含已保存的 Context 值。

9.4 根页测试

KiloSettingsConfigurableTest.kt 断言ContextConfigurable.ID == "ai.kilocode.jetbrains.settings.context"、根页包含 Context 链接、链接顺序与 XML 顺序一致。

十、构建验证与手动验收

packages/kilo-jetbrains/下运行:

./gradlew typecheck ./gradlew test

迭代期间的聚焦检查:

./gradlew :shared:test --tests '*ContextSettingsStateTest' ./gradlew :frontend:test --tests '*ContextSettingsUiTest' ./gradlew :backend:test --tests '*KiloCliDataParserTest' ./gradlew :backend:test --tests '*KiloBackendAppServiceTest'

手动验收流程:

  1. packages/kilo-jetbrains/下运行./gradlew runIde启动沙箱 IDE;
  2. 打开Settings -> Tools -> Kilo Code -> Context
  3. 切换自动压缩与剪枝开关;
  4. 设置阈值数字 → Apply → 重开设置页,确认持久化;
  5. 清空阈值 → Apply → 重开设置页,确认复位;
  6. 增删 watcher 忽略模式 → Apply → 重开设置页,确认列表持久化;
  7. 必要时通过既有Open: global ...动作直接检查全局 Kilo 配置文件内容。

十一、风险与后续事项

  • 全局 vs 项目级配置:本方案复用全局配置写路径;若未来要做项目级 Context 设置,需要新增 workspace 配置 RPC 管道。
  • 阈值 null 语义:必须实现显式 clear 处理,否则清空字段会静默无效。
  • 字符串数组 UI:复用共享列表原语(即使需要小适配器类型),避免一次性列表控件。
  • VS Code memory/indexing 对齐:延迟处理,因为它不是纯配置,且已被 easy-win 标准排除。
  • Checkpoints 页snapshot单独实现,除非产品明确要求与 Context 合并。
  • Changeset:作为用户可见的 JetBrains 设置特性落地时,需按仓库发布指引为kilo-code/JetBrains 添加补丁 changeset。

小结

Context 设置页是“CLI 承担逻辑、客户端只补 UI”这一 parity 策略的典型落地:共享 DTO 提供类型化读写、后端解析器扩展布尔/数字/数组序列化、前端草稿状态用字符串兜住阈值输入、UI 复用BaseSettingsUi与平台组件,测试沿用 fake-RPC + MockCliServer 双端断言模式。对希望为 Kilo JetBrains 插件新增纯配置类设置页的开发者,.kilo/plans/jetbrains-context-settings-page.md 与上述实现文件构成了可直接照搬的七步参考流程。

【免费下载链接】kilocodeKilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kilocode

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询