KZAgent 是一个用 Kotlin/JVM + Compose Desktop 构建的轻量级 AI 编程助手。它支持 DeepSeek 与 OpenRouter 的 OpenAI-compatible Chat Completions API,结合本地文件、命令执行和静态网页获取工具,提供可按会话切换 Provider/模型的桌面聊天界面,并保留 ask / chat 命令行模式及 app 桌面启动命令。
KZAgent 的核心思想是让大语言模型(LLM)通过工具调用(Tool Calling)与本地开发环境交互:
- 用户提问 → 桌面端或 CLI 将问题发送给当前会话选择的模型
- 模型推理 → 模型决定直接回答或调用工具
- 工具执行 → Agent 在本地执行模型选择的工具(读文件、搜索、编辑等)
- 结果反馈 → 工具执行结果返回给模型,继续推理
- 输出答案 → 模型给出最终回答
工具调用采用**积分配额(Tool Quota)**控制:每个工具消耗不同积分(本地只读操作 1 分、apply_patch 2 分、run_command / fetch_web_page 5 分、ask_user 每题 1 分),初始配额 100 分;
配额偏低时模型会收到警告并自动扩容 50 分,不限扩容次数,从而灵活限制资源消耗而无需硬编码轮数上限。
方式一(推荐):通过桌面应用内置设置面板配置。 首次启动桌面应用时如未检测到任何 Provider API Key,将自动打开设置面板;你也可以随时通过侧边栏的「⚙ 设置」按钮进入。你可以添加一个或多个任意类型的 OpenAI 兼容 Provider(内置 DeepSeek / OpenRouter 模板,也支持自定义端点),并选择其中一个作为默认。保存后可在对话顶部从在线目录搜索和切换模型。
方式二:手动创建配置文件 kzagent/config.json:
- Windows:
%APPDATA%\kzagent\config.json - macOS:
~/Library/Application Support/kzagent/config.json - Linux:
$XDG_CONFIG_HOME/kzagent/config.json,未设置时使用~/.config/kzagent/config.json
{
"providers": [
{
"id": "deepseek",
"name": "DeepSeek",
"kind": "DEEPSEEK",
"apiKey": "sk-xxxxxxxxxxxxxxxx",
"baseUrl": "https://api.deepseek.com"
},
{
"id": "custom",
"name": "My Provider",
"kind": "OPENAI_COMPATIBLE",
"apiKey": "sk-xxxxxxxxxxxxxxxx",
"baseUrl": "https://api.example.com/v1"
}
],
"defaultModel": {
"provider": "deepseek",
"modelId": "deepseek-v4-pro"
}
}kind 支持 DEEPSEEK、OPENROUTER、MIMOCODE(小米 MiMo Code,默认端点 https://api.xiaomimimo.com/v1)以及 OPENAI_COMPATIBLE(任意 OpenAI 兼容端点,通过 GET {baseUrl}/models 获取模型列表)。id 是每个 Provider 的唯一标识,用于持久化会话的模型选择。
也可以通过环境变量提供,且当 JSON 中未配置对应 Provider 时生效:
export DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx
export OPENROUTER_API_KEY=sk-or-xxxxxxxxxxxxxxxx
export MIMOCODE_API_KEY=sk-mimo-xxxxxxxxxxxxxxxxconfig.json 顶层还支持以下可选字段:
| 字段 | 默认值 | 说明 |
|---|---|---|
sensitivePathProtection |
false |
敏感路径保护开关。开启后拦截对 local.properties、.env 等本地敏感配置文件的访问 |
contextWindowSize |
1000000 |
模型目录未返回上下文长度时的回退值 |
approvalMode |
AUTO |
审批模式:AUTO、MANUAL 或 FULL |
userPrompt |
"" |
附加在系统提示词之后的自定义规则 |
旧版
config.properties自动迁移: 首次启动时若只存在旧的config.properties(deepseek.*/openrouter.*key)而没有config.json,KZAgent 会自动读取并迁移为config.json,无需手动转换。
项目使用 Gradle 和 JVM 17+。如果系统默认 Java 不是 17+,请先设置 JAVA_HOME。
# 交互式多轮对话(等同于 chat)
./gradlew run
# 启动桌面应用,在当前目录创建新会话
./gradlew run --args="app"
# 单次提问
./gradlew run --args="ask \"列出当前项目文件\""
# 显式启动交互式多轮对话
./gradlew run --args="chat"
# 携带初始问题的交互式对话
./gradlew run --args="chat \"分析一下项目架构\""Windows 安装包使用固定的升级 UUID,并允许新构建的相同版本覆盖已安装版本:
.\gradlew.bat packageReleaseExe产物位于 build/compose/binaries/main-release/exe/。packageReleaseExe 生成的是安装器;安装后的应用程序位于安装目录中的 KZAgent.exe。发布新版本时仍应同步提升 build.gradle.kts 中的 windowsPackageVersion,相同版本覆盖仅用于修复构建或重复安装。
使用 app 参数从命令行启动桌面窗口:
./gradlew run --args="app"命令行启动 GUI 时会创建一个空白新会话,并把命令的启动目录设为该会话的工作区。从操作系统桌面图标启动已安装应用时则保持原有行为,加载历史并激活最近会话。桌面 GUI 在同一用户下只运行一个实例;已有窗口时再次执行 kza app,新进程会把当前目录转发给原窗口并退出,原窗口恢复到前台并创建对应的新会话。通过桌面图标或 Dock 无参数重复启动时只恢复原窗口,不创建会话。
桌面端支持:
- 使用 Compose Fluent + Material 3 双主题桥接的 Fluent UI 桌面界面;弹出确认、会话重命名/删除、Todo 和人工审批统一使用 Fluent ContentDialog,完整 NavigationView 会在宽屏显示固定左栏、窄屏切换为紧凑浮层,并支持亮/暗主题
- 命令行启动 GUI 时使用启动目录作为新会话工作区;已有 GUI 时会把目录转发给原窗口并始终创建新会话,即使该目录与当前工作区相同;手动切换到其他目录时也会创建独立的新会话,原工作区会话及历史保持不变
- 加载最新
.kagent/sessions/历史用于续聊,支持多会话管理 - 会话列表、消息历史、设置和审批详情等滚动区域均提供可拖拽的桌面滚动条;切换会话时消息历史自动定位到底部,聊天区还提供顶部/底部快捷跳转按钮
- Markdown 超宽表格提供独立、可拖拽的横向滚动条,单元格内容会换行完整展示
- NavigationView 底部提供设置面板入口;展开侧栏时,每个会话右侧直接提供重命名和删除按钮
- 设置面板可将
kza安装为当前用户的全局命令;应用只维护用户级命令目录和 PATH,不修改系统级 PATH - 主聊天页顶部提供常驻的审批模式下拉菜单,可立即切换自动、手动或全部放行模式
- 启动时自动检测配置:如未设置 API Key 将默认跳转到设置界面
- 配置、历史会话和本地文件工具均在后台 IO 调度器中读写,加载或搜索大型工作区时不会阻塞桌面 UI
- 在状态栏显示模型请求、工具执行和审批状态
- 复杂任务可由模型维护与会话绑定的多层 Todo;宽内容区显示常驻只读进度面板,窄内容区通过顶部 Todo 进度按钮打开,并实时反映工具更新
- 支持自动、手动和全部放行三种审批模式;高风险人工审批使用单独的警告弹窗
- 输入框使用
Enter发送;macOS 使用Command + Enter换行,Windows 和 Linux 使用Ctrl + Enter换行 - macOS 上关闭主窗口后应用会继续驻留;再次点击 Dock 图标可恢复原窗口和会话,使用
Command + Q可完全退出 - 点击终止会取消正在进行的 Retrofit 模型请求;若正在执行命令,还会终止对应进程树
在已安装桌面应用的设置页点击「安装 kza 命令」。macOS 和 Linux 默认安装到 ~/.local/bin/kza,Windows 默认安装到 %LOCALAPPDATA%\KZAgent\bin\kza.cmd;如果目录尚未加入 PATH,应用会为当前 shell 或 Windows 用户 PATH 添加配置,新打开的终端生效。
Windows 上的 CLI 子命令使用安装包内的控制台 Java 启动器,以保持 PowerShell/CMD 的标准输入输出;kza app 仍使用桌面启动器异步发起请求。如果 GUI 已经运行,该请求只会把当前目录转发给现有实例,不会保留第二个桌面进程。
kza # 等同于 kza chat
kza ask "分析当前项目" # 单次提问
kza chat # 交互式对话并恢复最近会话
kza app # 在当前目录创建新会话并启动 GUI应用可以幂等更新自己安装的命令。若 PATH 中已经存在其他来源的 kza,为避免覆盖用户文件,安装会停止并显示冲突路径。
执行一次提问,模型经过多轮工具调用后只输出最终答案,然后退出。
./gradlew run --args="ask \"搜索所有包含 TODO 的文件\""无参数启动等同于 chat。进入持续对话界面后可以连续追问,并支持以下功能:
- 断点续聊:启动时自动加载最近一次会话历史
- 多轮追问:每次回答后可输入新的问题
- 退出:输入空行或
exit/quit结束对话
$ ./gradlew run --args="chat"
You: 介绍一下这个项目
Assistant:
...
You (empty to exit): 帮我优化一下代码
Assistant:
...
You (empty to exit):
Chat ended.
KZAgent 支持使用工作区中的 AGENTS.md 为 Agent 提供持久的项目约定:
- 每个 session 创建时读取工作区根目录的
AGENTS.md,并将完整内容固化到基础系统提示词中。根指令不会受上下文压缩影响,session 中途修改后需新建或重建 session 才会生效。 - 当
read_file成功读取工作区子目录中的文件时,从工作区根目录下一层到目标文件父目录逐层发现AGENTS.md,按浅到深顺序加载;越接近目标文件的规则优先级越高。经审批读取的工作区外文件不会触发外部AGENTS.md加载。 - 空的
AGENTS.md会被忽略。KZAgent 不限制单个指令文件大小,也不会截断或自动压缩文件内容。 - 同一份非空子目录指令在两次上下文压缩之间只加载一次。压缩成功后会开启新的加载周期,再次读取相应目录时允许重新加载,即使旧指令仍在最近消息窗口中。
- 子目录指令会记录到 session JSONL,并作为系统消息发送给模型,但不会显示在桌面对话列表中。落入压缩摘要区的子目录指令会被丢弃。
- 当前仅识别规范文件名
AGENTS.md,不读取全局指令、AGENTS.override.md或其他备用文件名。
示例:
workspace/
├── AGENTS.md # 整个 session 始终生效
└── src/
├── AGENTS.md # 读取 src/ 下文件后加载
└── feature/
├── AGENTS.md # 读取此目录文件后在 src/ 规则之后加载
└── Feature.kt
用户输入
│
▼
┌──────────────────┐
│ CodingAgent │ ◄── 核心循环(积分配额制,自动扩容)
│ 运行推理 → 检查 │
│ 工具调用 → 执行 │
│ 结果 → 继续推理 │
└──────────────────┘
│
├── OpenAiCompatibleClient ──► DeepSeek / OpenRouter
│
└── LocalTools
├── list_files (只读,无需审批)
├── read_file (工作区内只读;外部或敏感文件按策略审批)
├── search_text (只读,无需审批)
├── apply_patch (Git 补丁编辑,无需审批)
├── run_command (按自动 / 手动 / 全部放行策略审批)
├── fetch_web_page (公开静态网页获取,无需审批)
├── ask_user (向用户发起澄清提问,每题 1 积分)
├── todo_read (查看会话 Todo,零积分)
└── todo_write (原子更新会话 Todo,零积分)
| 组件 | 文件 | 职责 |
|---|---|---|
| CodingAgent | agent/CodingAgent.kt |
Agent 核心循环:调度模型推理与工具执行 |
| AgentsInstructionsLoader | agent/AgentsInstructionsLoader.kt |
加载根目录与子目录 AGENTS.md 项目指令 |
| PromptBuilder | agent/PromptBuilder.kt |
构建系统提示词(定义 Agent 行为规则) |
| OpenAiCompatibleClient | llm/DeepSeekClient.kt |
通过 OkHttp 调用不同 Provider 的流式 Chat Completions API,支持工具调用、错误解析与协程取消 |
| ModelCatalogService | llm/ModelCatalogService.kt |
在线加载并规范化 DeepSeek/OpenRouter 模型目录与能力元数据 |
| SessionWriter | agent/SessionWriter.kt |
以 JSONL 格式将消息流写入会话文件 |
| SessionReader | agent/SessionReader.kt |
从会话文件读取历史消息,恢复对话上下文 |
| DesktopApp | desktop/DesktopApp.kt |
Compose Desktop 桌面聊天界面 |
| SessionManager | desktop/SessionManager.kt |
桌面端多会话管理:新建、切换、重命名、删除 |
| AppConfigLoader | config/AppConfig.kt |
从用户配置文件 / 环境变量加载配置 |
| LocalTools | tools/LocalTools.kt |
本地及网页工具的统一注册 |
| WebPageService | tools/WebPageService.kt |
公网静态页面请求、SSRF 防护、解析与正文提取子代理 |
| TodoStore / TodoTools | todo/TodoStore.kt / tools/TodoTools.kt |
会话 Todo 的分层状态、原子持久化、提醒计数和模型工具 |
| PathGuard | tools/PathGuard.kt |
路径解析与工作区边界判断 |
| ApprovalPolicy | tools/Approval.kt |
通用审批策略、风险分析与专用审批 Agent |
Agent 可以通过以下工具与工作区和公开网页交互:
| 工具名称 | 需要审批 | 功能描述 |
|---|---|---|
list_files |
❌ | 列出工作区目录结构(深度 1–8,最多 500 项) |
read_file |
条件 | 工作区内直接读取;外部或受保护文件按审批模式处理 |
search_text |
❌ | 在文本文件中大小写不敏感搜索子串(最多 200 个结果) |
apply_patch |
❌ | 用单个 Git unified diff 更新、创建或删除多个文件 |
run_command |
✅ | 按全局审批模式执行带执行超时限制的 shell 命令 |
fetch_web_page |
❌ | 获取公开静态 HTTP(S) 页面,返回请求元数据、Markdown 正文和最多 20 个关键链接 |
ask_user |
❌ | 向用户顺序提出澄清问题;每题最多 3 个预置选项,可自由输入或跳过,每题消耗 1 积分 |
todo_read |
❌ | 读取当前 session 的完整分层 Todo 和叶子任务进度,消耗 0 积分 |
todo_write |
❌ | 以原子批次创建、修改、完成/重开或删除 Todo,消耗 0 积分 |
- 只读工具中
list_files/search_text严格限制在工作区;read_file可在审批后读取单个工作区外文件 - 文件编辑工具(
apply_patch)不要求审批,使用单个patch参数传递标准 Git unified diff- 可在一次调用中更新、创建或删除多个文件
- 自动识别 UTF-8(含 BOM)、UTF-16、UTF-32、GB18030/GBK 和 Windows-1252
- 编辑已有文件时保留原编码、BOM 与换行符风格
- 命令执行(
run_command)统一经过当前审批模式;风险分析用于决定自动判断或人工确认,不再直接剥夺用户授权执行的能力- 输出按原始字节累积,先尝试 UTF-8 严格解码,失败再回退到平台默认 charset 与 GB18030/GBK,避免 Windows 中文系统下 GBK 命令输出(如
cmd.exe错误信息)在 UTF-8 环境中乱码
- 输出按原始字节累积,先尝试 UTF-8 严格解码,失败再回退到平台默认 charset 与 GB18030/GBK,避免 Windows 中文系统下 GBK 命令输出(如
- 网页获取(
fetch_web_page)仅接受单个公开 HTTP(S) URL。HTML 会先清理脚本、样式、表单和页面框架,再由一次无工具、无历史的专用子代理提取正文;完整 HTML 不会返回主 Agent - Todo 工具不访问工作区,也不需要审批。
todo_write的operations按顺序执行并整体提交,支持create、update、set_status、delete;任一操作失败时不会保存整批修改 - 用户提问(
ask_user)在桌面端逐题显示 Fluent 弹窗,在 CLI 逐题提示输入;每题默认等待 5 分钟,超时、取消或空输入会跳过当前题并继续后续问题。- Todo 使用唯一
id和可选parent_id组成多层结构;完成/重开父项会级联整棵子树,父项状态也会根据直接子项自动汇总 - 持久化状态只有
pending和completed;工具输入中的in_progress会兼容归一化为pending - 模型应在每个阶段完成后及时更新对应项目,不使用重复的
pending表示“开始执行”;无实际变化的批次返回changed:false且不增加 revision - 模型在跨多个步骤、文件或工具轮次的复杂任务中会优先建立 Todo;简单单步任务无需创建
- 存在未完成项且连续 7 次模型回复未调用 Todo 工具时,下一次请求会加入 reminder;后续只有距离上次 reminder 已超过 3 次模型回复时才会再次提醒。任一 Todo 工具调用或全部完成都会重置计数
- 主 Agent 输出不再调用工具的最终回复时,如果 Todo 非空且所有项目均已完成,运行时会自动清空列表;未完成项目会保留到后续对话
- Todo 使用唯一
fetch_web_page 只处理服务器直接返回的 HTML、纯文本、JSON、XML、RSS 和 Atom 内容。它不会执行 JavaScript,也不支持点击、滚动、Cookie、登录态、验证码、自定义请求头、二进制下载或内网页面。遇到 SPA 空壳或要求启用 JavaScript 的页面时,结果会包含能力限制警告。
所有写操作、目录枚举和批量搜索路径都会被归一化和校验,确保不会逃逸出工作区根目录。read_file 是唯一例外:绝对路径、../ 或符号链接指向的工作区外普通文件会进入统一审批流程;批准后只读取本次指定的行范围。
启用敏感路径保护后,以下文件会从直接读取改为按审批模式处理:
.env、local.properties(历史本地敏感配置文件)- 密钥文件、密码文件等
run_command 执行前会识别危险程序、多行脚本、Shell 组合语法、路径逃逸和敏感引用,并按审批模式处理:
- 自动审批(默认):明确安全的常见只读、构建和测试命令由静态规则放行;其他普通命令由无工具、无会话历史的专用审批 Agent 判断;高风险命令或 Agent 无法判断时转人工。
- 手动审批:所有命令和受保护读取都由用户逐次确认。
- 全部放行:视为持续授权,不再调用审批 Agent 或人工弹窗,并以当前应用用户权限执行。
- 命令执行超时:命令进程启动后默认最多运行 30 秒,可配置为 1–120 秒;这不是审批等待超时。
fetch_web_page 在建立连接时检查 DNS 解析结果,拒绝 localhost、环回、私网、链路本地、组播和保留地址;每次重定向都会重新校验。请求最多跟随 5 次重定向、总耗时最多 30 秒,解压后的响应体最多 2 MiB,并拒绝二进制内容。网页内容始终视为不可信数据,正文提取子代理不能调用任何工具。
桌面端高风险审批必须点击“仍然执行”,Enter 不会批准;CLI 必须输入完整的 yes。
所有错误消息中的 API Key 都会被自动替换为 ***REDACTED***,防止密钥在日志或终端中泄露。
每次交互通过 SessionWriter 自动以 JSONL 格式(每行一条 JSON)写入会话文件,保存在平台应用数据目录中,按工作区隔离:
{AppDataDir}/
└── sessions/
├── {workspace1}-{sha256hash}/
│ ├── session-{uuid}.jsonl
│ ├── session-{uuid}.jsonl.name # 用户自定义会话名
│ ├── session-{uuid}.jsonl.workspace # 对应的工作区路径
│ └── session-{uuid}.jsonl.todos.json # Todo、revision 和提醒状态
└── {workspace2}-{sha256hash}/
└── ...
每条记录格式:
| 字段 | 说明 |
|---|---|
time |
ISO-8601 时间戳,记录消息写入时间 |
role |
消息角色:system、user、assistant、tool、summary、context_snapshot 等 |
content |
消息正文 |
tool_calls |
(仅 assistant)模型请求的工具调用列表,含 id、name、arguments |
tool_call_id / name / is_error |
(仅 tool)工具执行结果对应的调用 ID、工具名和错误标记 |
context_tokens |
(仅 assistant / context_snapshot)写入时的累计上下文 token 数 |
启动恢复行为:
| 模式 | 行为 |
|---|---|
| 桌面图标启动 | 自动加载所有历史会话,按最近修改排序,默认激活最新会话;支持侧边栏多会话管理(新建、切换、重命名、删除) |
CLI app |
自动创建一个空白会话,以启动目录作为工作区,并保留全部历史会话 |
CLI chat |
无初始问题时加载最近一次会话历史,实现断点续聊;带初始问题时从空白上下文开始 |
CLI ask |
不加载历史,每次独立执行 |
上下文压缩: 桌面端与 CLI 共用 CodingAgent 中的压缩策略。每次请求前会计算系统提示、历史和新问题的上下文占用;当占用超过窗口大小的 80% 时,旧消息由 LLM 总结并以 context_snapshot 行写入会话文件。恢复时以此行为界,清空之前的消息并替换为摘要。token 统计优先采用 API 返回的 total_tokens,API 未返回 usage 时使用本地估算,避免压缩判断失效。
Todo 持久化: Todo 不作为对话消息写入 JSONL,而是保存在同 session 的 .todos.json 侧车中,因此上下文压缩不会丢失任务进度。写入使用临时文件和原子替换;侧车损坏或 schema 不兼容时保留原文件并只禁用该 session 的 Todo 能力,不影响普通聊天。删除 session 时会一起删除 Todo 侧车。
会话元数据: 每个 .jsonl 文件旁可存在 .name(用户自定义会话名)、.workspace(所属工作区路径)和 .todos.json 辅助文件;前两者由桌面端 SessionManager 管理,Todo 文件由 CLI 与桌面端共享运行时读写。
src/main/kotlin/com/kzagent/kagent/
├── agent/
│ ├── AgentsInstructionsLoader.kt # 分层 AGENTS.md 加载
│ ├── CodingAgent.kt # Agent 核心循环
│ ├── PromptBuilder.kt # 系统提示词构建
│ ├── SessionReader.kt # 会话历史读取
│ └── SessionWriter.kt # 会话历史写入
├── cli/
│ └── Main.kt # CLI:ask / chat 命令
├── desktop/
│ ├── DesktopApp.kt # 桌面应用 UI(主界面、侧边栏、消息列表、审批弹窗)
│ ├── SessionManager.kt # 多会话管理(新建、切换、改名、删除)
│ ├── SessionRepository.kt # 后台 IO 会话存储
│ ├── SettingsPanel.kt # 设置面板(API Key、模型、URL、命令安装)
│ └── UserCommandInstaller.kt # 当前用户的 kza 命令与 PATH 安装
├── todo/
│ └── TodoStore.kt # 分层 Todo、提醒状态和 session 侧车持久化
├── Main.kt # 根入口:无参数 chat;app 桌面;ask/chat CLI
├── AgentRuntimeFactory.kt # 共享运行时创建
├── config/
│ └── AppConfig.kt # 配置加载(AppConfigLoader)、保存(ConfigWriter)与密钥脱敏
├── llm/
│ ├── DeepSeekClient.kt # OpenAI-compatible 多 Provider API 客户端
│ ├── ModelCatalogService.kt # DeepSeek / OpenRouter 模型目录
│ ├── DeepSeekApi.kt # Retrofit 接口与 OkHttp 客户端工厂
│ └── Messages.kt # 消息模型定义
└── tools/
├── Tool.kt # 工具定义、注册表、JSON Schema 构建
├── LocalTools.kt # 本地及网页工具注册
├── Approval.kt # 通用审批模式、风险分析、静态规则与审批 Agent
├── PathGuard.kt # 路径安全守卫
├── TextFileCodec.kt # 多编码文本文件读写(UTF-8/16/32、GBK、Windows-1252)
├── UnifiedPatch.kt # Git unified diff 解析与应用引擎
├── ToolQuota.kt # 工具调用配额系统(含自动扩容)
└── WebPageService.kt # 静态网页请求、解析、安全校验与正文提取
{
"providers": [
{
"id": "deepseek",
"name": "DeepSeek",
"kind": "DEEPSEEK",
"apiKey": "sk-xxxxxxxxxxxxxxxx",
"baseUrl": "https://api.deepseek.com"
},
{
"id": "openrouter",
"name": "OpenRouter",
"kind": "OPENROUTER",
"apiKey": "sk-or-xxxxxxxxxxxxxxxx",
"baseUrl": "https://openrouter.ai/api/v1"
},
{
"id": "mimocode",
"name": "MiMo Code",
"kind": "MIMOCODE",
"apiKey": "sk-mimo-xxxxxxxxxxxxxxxx",
"baseUrl": "https://api.xiaomimimo.com/v1"
},
{
"id": "custom",
"name": "自定义",
"kind": "OPENAI_COMPATIBLE",
"apiKey": "sk-xxxxxxxxxxxxxxxx",
"baseUrl": "https://api.example.com/v1"
}
],
"defaultModel": {
"provider": "deepseek",
"modelId": "deepseek-v4-pro"
},
"sensitivePathProtection": false,
"contextWindowSize": 1000000,
"approvalMode": "AUTO"
}providers 列表可以包含任意数量的 provider,kind 取 DEEPSEEK / OPENROUTER /
MIMOCODE / OPENAI_COMPATIBLE。旧版 config.properties 会自动迁移为上述 JSON 格式。
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx # JSON 中未配置 DeepSeek 时生效
OPENROUTER_API_KEY=sk-or-xxxxxxxxxxxx # JSON 中未配置 OpenRouter 时生效
MIMOCODE_API_KEY=sk-mimo-xxxxxxxxxxxx # JSON 中未配置 MiMo Code 时生效| 技术 | 用途 |
|---|---|
| Kotlin 2.4.0 + JVM 17+ | 开发语言与运行时 |
| Compose Desktop 1.11.1 | 桌面应用 UI 与原生打包 |
| Gradle | 构建工具 |
| kotlinx-coroutines | 异步编程(协程) |
| kotlinx-serialization | JSON 序列化/反序列化 |
| OkHttp 4.12.0 | Provider API 与静态网页的可取消网络请求、受控重定向和压缩传输 |
| Jsoup 1.22.2 | HTML/XML 解析、清理和链接解析 |
| DeepSeek / OpenRouter API (OpenAI 兼容) | 可切换的 LLM 推理后端与模型目录 |
# 构建项目
./gradlew build
# 运行测试
./gradlew test
# 运行(需先配置 API Key)
./gradlew run --args="ask \"你好\""本项目为开源工具。