让大模型回答一个代码问题,和让它在真实项目里完成一次修改,中间还有很长一段工程路径。
它需要找到相关文件,理解已有实现,决定调用什么工具;涉及命令和外部服务时,需要处理权限;修改结束后,要留下测试记录和代码差异。任务如果中断,还得知道哪些步骤已经执行,哪些步骤需要先检查结果。
Hikari 就是我围绕这条路径做的一个桌面 AI Agent 工作区。 它把对话、项目工具、任务状态、权限审批和改动审阅放在同一个应用里,也支持不打开项目,直接围绕文档和截图提问。
先放项目地址:
- GitHub:fonghehe/hikari-agent
- 中文文档:Hikari 使用指南
- 英文文档:Hikari Documentation
一、先看界面:对话和项目操作放在一起
Hikari 使用桌面应用形态,界面主要分为三个区域。
左侧是工作区和任务历史,中间是对话与执行过程,右侧按需要打开文件、改动、终端或浏览器。工具面板可以收起,各区域独立滚动,避免查看代码时挤占整个对话区域。
应用支持中文、英文和日文,也提供亮色、暗色及跟随系统的主题设置。语言与主题会保存在本地,重启后继续使用。
我希望这里保留两种自然的使用方式:
- 从问题开始。 不选工作区,直接提问、上传文档或粘贴截图。
- 从项目开始。 打开本地仓库,让 Agent 阅读代码、提出计划、执行修改,再审阅结果。
如果只是想看看交互,不需要先申请 API Key。内置离线演示可以体验提问、计划、任务控制和示例 Diff;连接自己的模型后,才进入真实的分析与执行流程。
二、模型可配置,服务商协议由适配层处理
Hikari 没有把应用绑定到单个模型服务。模型设置支持保存多份配置,按任务选择使用的服务、地址和模型 ID。
目前的配置预设包括 OpenAI、Anthropic、Google Gemini、DeepSeek、Qwen、Kimi、GLM、豆包等服务,也包括 Ollama、LM Studio 和 OpenAI compatible 接口。
这里需要区分两个概念:能填写某个模型,和这个模型能完成项目任务,是两件事。
比如,普通问答主要依赖文本生成;项目任务需要模型支持工具调用;截图分析需要模型接受图片。服务端是否支持流式输出、返回用量、接收推理强度参数,也会影响具体配置。
在实现上,模型差异集中放在 packages/model-provider:Anthropic、Gemini 使用相应协议,其余不少预设走 Chat Completions 兼容接口。任务运行时面向统一的 Provider 契约,不直接散落各服务商的请求逻辑。
这让桌面端、CLI 和后续执行宿主可以复用同一套模型接入逻辑。新增服务时,也能先判断它是已有协议的地址预设,还是需要独立适配。
另一个行为是:真实服务请求失败时会显示错误,不会悄悄换成示例答案。离线模拟有独立标识,避免让用户误以为模型已经完成真实分析。
三、附件问答:文档提取、图片输入与本地 OCR
很多开发任务的起点并不是代码,可能是一份需求文档、一张报错截图,或者产品给出的 PDF。
Hikari 可以通过文件选择、拖放和粘贴截图添加附件,并在发送前预览处理结果。当前主要支持:
| 类型 | 处理方式 |
|---|---|
| 文本、Markdown、CSV、JSON、常见代码文件 | 读取文本,供模型分析与检索 |
| 提取文本,部分扫描页面可进行本地 OCR | |
| DOCX | 提取正文文本 |
| PNG、JPEG、WebP、GIF | 处理图片尺寸,同时尝试提取文字;GIF 使用第一帧 |
单次最多添加 6 个文件,其中最多 3 张图片。文档初始预览有长度限制,较长的提取文本可以继续检索和读取。预览被截断,并不表示保存的全文只剩下预览部分。
图片这条路径也有明确分工:
- 视觉模型可以接收处理后的图片,结合布局和图像细节分析。
- 纯文本模型可以利用成功提取的 OCR 文字,但不能因此获得识图能力。
- 离线演示只展示接收和文本摘录,不会理解图片内容。
例如,可以把错误截图与相关代码一起附上,提出这样的问题:
结合截图中的报错和这段请求代码,解释可能的触发条件。
先列出可以从附件确认的事实,再说明需要到项目中继续检查的位置。
附件处理在本地完成,但连接云端模型后,参与分析的文本和图片仍会发送给配置的模型服务。使用本地模型与关闭外部接口,才可能把这部分推理也留在本机。
四、开发任务:先规划,再执行,最后看证据
打开项目后,Hikari 提供规划和执行两种模式。
规划模式用于阅读项目和整理方案,不修改文件,也不执行命令。适合先了解陌生仓库、分析问题范围,或者确认一项改动会影响哪些模块。
执行模式可以调用项目工具完成修改。工具能力包括文件读取与搜索、补丁修改、命令执行,以及按权限开放的浏览器、MCP 等入口。
比如,一个任务可以这样描述:
定位购物车总价计算异常的原因。
先阅读实现和测试,说明触发条件,再做最小范围修复。
保留现有测试,补充覆盖边界条件的回归用例,并运行相关检查。
相比“帮我优化这个项目”,这样的要求能明确问题、修改边界和交付证据,也更方便人在最后判断结果。
如果任务需要更完整的分工,可以选择“调查 → 规划 → 实施 → 审查”工作流:
| 阶段 | 主要产物 | 执行边界 |
|---|---|---|
| 调查 | 文件证据、问题范围 | 只读 |
| 规划 | 实施步骤、风险、验收方式 | 只读 |
| 实施 | 代码改动和检查记录 | 按授权使用工具 |
| 审查 | 对结果的独立检查 | 使用受限的只读角色 |
工作流使用 LangGraph 表达阶段流转,实施与审查之间可以按审查结果返工。当前最多进行三轮返工。
这里的“独立审查”指独立角色和上下文,并不表示结论一定正确。最终还是要核对引用文件、实际 Diff 和测试记录。
五、验收与预算:把“完成”变成可以检查的条件
Agent 很容易生成一段“已经完成”的文字,但这句话本身不能证明工作完成。
Hikari 允许在运行前设置两类验收条件:
- **文件验收:**检查指定路径是否存在,以及可选的必需文本。
- **测试命令:**指定程序、参数和工作目录,保存实际执行结果。
配置的条件未通过时,执行任务不能标记为完成。默认情况下,修改文件后,测试证据还必须来自最后一次改动之后。
这条约束处理的是一个常见细节:Agent 可能先跑过测试,随后又改了代码。如果继续沿用旧结果,“测试通过”就与最终代码失去了对应关系。
对于不适用测试的文档任务,可以选择只使用配置的验收条件;规划模式不会为了验收而执行命令。
同一面板还可以设置 Token、费用和时长上限。费用根据填写的输入、输出单价与用量计算,是预算参考,实际账单仍以服务商为准。向量检索的费用单独处理,不并入聊天预算。
这些限制让一次任务有了更清楚的结束条件,也减少了长时间尝试而缺少反馈的情况。验收覆盖多大范围,结果就只能证明多大范围。
六、改动审阅与 Git 工作树:保留人的交付环节
上图是离线演示:购物车示例从相加改成相乘,只作用于示例数据,没有修改真实项目,也没有运行真实测试。它用于展示审阅交互。
真实项目里,Hikari 会记录任务改动,并在界面中提供 Diff 查看。文件阅读与差异展示使用 Monaco Editor,终端使用 xterm.js 和 node-pty。
当任务涉及较大范围修改,或者当前工作区已有未提交内容时,可以选择独立 Git 工作树。
工作树起始状态可以使用 HEAD,也可以包含当前未提交的文件。后者会复制已跟踪文件和未被 Git 忽略的未跟踪文件;依赖目录、忽略文件不会一起复制,所以新工作树可能仍需安装依赖。
任务结束后,再通过“预览回写”检查补丁与冲突,将确认过的结果应用到原工作区。如果预览后源文件或工作树发生变化,回写会被阻止,避免继续使用过期的预览。
当前内置回写面向有限规模的 UTF-8 文本改动,一次最多 20 个文件、每个 512 KB。更多文件、二进制或特殊权限变化,需要通过 Git 或外部工具处理。工作树回写后,也应在原工作区重新验证。
这里还需要区分:审阅或接受改动,不等于 Git commit,更不等于 push。 任务完成和代码正式交付仍是不同的动作。
七、任务中断之后,恢复的是执行状态
长任务可能因为退出应用、网络故障或人为中断而停止。如果只保存聊天文字,恢复时很容易丢失工具结果、预算和待回答问题。
Hikari 使用检查点保存执行状态,包括模型消息、工具观察、工作记忆、计划、预算、工作流阶段等。应用重启后,具备有效保存状态的未完成任务会显示为已中断,等待继续。
继续任务沿用原检查点和剩余预算;重试创建新一轮任务;追问则是关联原任务的新对话轮次。这几种操作的含义不同。
恢复过程中最需要谨慎的是副作用。
假设一个工具已经写入文件,但进程在记录成功结果之前退出了。此时“没有成功记录”并不能推导出“操作没有发生”。直接重放可能导致重复写入,外部服务调用还可能产生额外影响。
因此,遇到这种结果未知的中断,系统需要先提示检查实际状态,再继续决定后续步骤。检查点可以提供恢复依据,但无法自动把外部世界回滚到某个时间点。
八、上下文与记忆:让长任务保留目标和来源
随着任务推进,对话、文件内容和工具输出会不断增长。全部原样塞给模型,既昂贵,也可能很快超过上下文窗口。
Hikari 将这部分职责拆开:
| 层次 | 保存什么 | 主要用途 |
|---|---|---|
| 短期上下文 | 模型消息、工具调用、观察结果 | 当前推理与工具选择 |
| 工作记忆 | 目标、计划、摘要、决策、待办 | 维持长任务状态 |
| 长期记忆 | 带来源与过期时间的项目事实 | 为后续任务提供参考 |
长期记忆通过 remember、search_memory 等能力管理,也能在设置里查看、编辑和删除。它不会自动把所有聊天永久变成项目事实,过期记录也不会继续参与召回。
对于很长的工具结果,当前开发版本会保存完整内容,先给模型提供摘要式预览,再通过 read_tool_result 分页读取。这样,模型可以继续检查先前输出,而不必为了重新获得文本再次执行原操作。
检索也有两条路径:
- 代码查找: 使用仓库索引、ripgrep 和
search_code查找文件与相关代码。 - 附件和记忆检索: 默认做关键词匹配,可选接入 Embeddings,结合语义相似度排序。
开启向量检索后,系统缓存文本向量,并通过 Reciprocal Rank Fusion 合并关键词与语义排名。缓存与接口、模型、文本内容关联,文本变化后需要重新计算。
它目前不会自动把整个仓库向量化,也没有宣称具备大型向量数据库的索引能力。当前语义集合有规模限制,向量比较仍会线性遍历候选。
对我来说,这里更有价值的是保留来源和失效规则。记忆可能过期,摘要可能遗漏细节,检索结果也可能不相关;Agent 仍需要回到原始文件和工具证据中确认。
九、MCP 与 Skills:把工具连接和工作方法分开
Hikari 支持接入 HTTP、stdio MCP 服务,也支持导入包含 SKILL.md 的技能目录。
可以把两者理解为两个扩展维度:
- MCP 提供外部工具、资源和提示词的连接入口。
- Skill 描述任务方法、约束和允许使用的工具。
例如,可以在项目里放入一个只读的前端审查 Skill:
---
name: frontend-review
description: Review frontend code without modifying files.
allowed-tools:
- read_file
- list_directory
- glob
- grep
- search_code
- git_status
- git_diff
---
阅读相关代码,以文件路径说明可复现的问题。
提出改进建议,不修改文件。
再要求 Agent 加载它,对指定目录进行审查。Skill 的工具限制持续生效,但不会自动授予命令、联网或外部服务权限。
同样,MCP 返回的内容、仓库文件和文档都应作为参考资料处理,不能因为其中出现指令文本,就覆盖用户要求。
十、技术架构:桌面界面、任务宿主和运行时分层
架构图依据当前本地开发版本整理,其中共享执行宿主和远程执行相关模块属于后续扩展。
项目采用 TypeScript Monorepo,使用 pnpm workspace 管理包,Turborepo 组织构建任务。
核心目录可以按职责阅读:
apps/
desktop/ Electron 主进程、preload、React 界面
cli/ 命令行入口
server/ 可选服务端
packages/
agent-core/ 任务、事件、工具等核心契约
agent-runtime/ 执行循环、上下文、审批、检查点、工作流
agent-host/ CLI 与执行节点的共享宿主(开发版本)
model-provider/ 模型协议与离线演示
tools/ 文件、代码、命令、浏览器等工具
sandbox/ 命令执行边界
git/ Git 与工作树交付
database/ 持久化
mcp/ MCP 接入
skills/ 技能加载与限制
shared/ 跨进程类型与输入校验
ui/ 共享界面组件
桌面端的一次请求大致沿着以下路径流转:
React / Zustand
→ window.hikari
→ preload / contextBridge
→ IPC Router 与领域处理器
→ TaskHost
→ AgentRunner
→ 模型适配器与已授权工具
→ 事件、检查点、任务记录
→ 界面更新
renderer 不直接访问数据库和 Node 文件 API,preload 只暴露明确列出的能力。IPC 层负责来源检查和参数校验,再把业务交给对应服务。
当前开发版本将 IPC 按工作区、模型、任务、服务和平台能力拆分,减少入口文件中的职责堆积。共享类型提供编译时约束,运行时输入仍要通过 schema 校验。
窗口启用了 contextIsolation 与 renderer sandbox,并关闭 nodeIntegration。不过,Electron 窗口隔离和 Agent 命令沙箱属于不同边界,不能相互替代。
任务命令默认使用系统沙箱:macOS 使用原生沙箱,Linux 依赖 bubblewrap,Windows 使用 Docker 方案。沙箱不可用时会报错,不会自动降级到主机权限。交互式终端则直接运行在宿主账户下。
本地数据主要保存在 SQLite,桌面基本使用不要求先部署 PostgreSQL 或 Redis。任务、事件、改动、检查点、记忆和模型配置分别保存;模型密钥在系统安全存储可用时加密,不可用时只留在当前会话。整个任务数据库并不是全库加密。
还有一个当前架构限制:AgentRunner 仍运行在 Electron 主进程,附件解析使用 Worker。同步数据库、部分索引和检索计算仍可能占用主进程,后续需要根据实际测量继续拆分。
十一、本地开发进展:从单机任务走向自动化与协作
下面这部分来自本地开发版本,尚未全部进入公开仓库。它们已经有对应实现与文档,但具体环境仍需要独立验收。
1. 动态子 Agent
主任务可以委派独立调查,汇总结果。每个子 Agent 有独立上下文,并继承工具限制;默认只读,需要写入时使用独立工作树,改动不会自动回写主工作区。
当前限制同时最多三个子 Agent、每轮运行总共委派十二次,不支持嵌套委派。子任务实际用量计入主任务预算,避免将并发变成无限扩张。
2. Hooks、LSP 与插件包
生命周期 Hooks 支持 SessionStart、PreToolUse、PostToolUse 和 Stop,用于在指定事件执行批准的命令。Hook 失败可以阻止流程,但已经发生的工具副作用不能因此自动撤销。
LSP 提供定义、引用、悬浮信息和诊断入口,需要用户自行安装并配置语言服务器。诊断结果依赖服务器和项目配置,仍需编译器与测试提供验证。
插件包进一步组合 Skills、Hooks、角色、LSP 和 MCP,支持摘要校验和自行分发的插件目录。当前没有项目方托管的在线插件市场。
3. 定时任务与持续目标
定时任务支持重复执行和单次执行,可按变化或失败决定是否通知。桌面调度需要电脑和应用保持运行,命令仍遵循原有授权。
持续目标则把目标、续跑次数和预算保存到检查点。模型答复结束但目标尚未完成时,可以在限制范围内继续处理;暂停、取消、外部阻塞和资源上限仍然会停止执行。
4. VS Code、远程控制与自托管执行
VS Code 扩展可以携带当前选区、路径和诊断创建任务,也能查看结果、处理审批和打开差异。
远程控制提供浏览器入口,控制原执行电脑上的任务。自托管执行则由服务端和 Worker 配合,让仍在运行的服务器或执行节点继续工作。
两者都需要明确的执行环境:项目、依赖、模型和沙箱由使用者准备。它们不会自动提供公共云机器,也不会在电脑关闭后凭空继续运行本地任务。
跨进程执行使用工作区占用记录,避免桌面端、CLI 和 Worker 同时操作同一目录;Worker 的领取与状态更新使用请求标识和租约,处理响应丢失与断线重连。这些机制解决的是具体执行路径,不能扩展解释成任意分布式环境中的强一致保证。
此外,本地版本还加入了 GitHub/CI 只读审查和对话、代码历史恢复。历史恢复有文件范围、大小和冲突限制,外部副作用不会回退,仍需要 Git 提交与备份保存长期历史。
十二、怎样运行起来
1. 从源码启动
准备 Node.js 24 和 pnpm 11,然后执行:
git clone https://github.com/fonghehe/hikari-agent.git
cd hikari-agent
pnpm install
pnpm dev
具体 pnpm 版本以仓库 package.json 中的 packageManager 为准。
真实项目工具需要 Git 和 ripgrep。使用浏览器工具前,还需要安装 Chromium:
pnpm exec playwright install chromium
启动后可以先使用离线演示,确认界面与流程,再连接模型和本地项目。
2. 推荐的第一次真实任务
先选一个熟悉的小项目,使用规划模式提出范围有限的问题:
阅读当前项目的入口、路由和请求封装。
用文件路径说明一次页面请求如何到达接口。
先给分析结果,不修改文件、不执行命令。
确认分析与代码一致后,再切换执行模式,处理一个容易验证的小问题。能解释结果、看懂 Diff、重现检查记录,比第一次就交给 Agent 一个大型重构更容易建立信任。
3. CLI 和文档
也可以在源码目录体验 CLI:
AGENT_PROVIDER=demo pnpm agent run "你好"
AGENT_PROVIDER=demo AGENT_MODE=plan pnpm agent run "分析示例项目"
本地文档启动方式:
pnpm docs:dev --port 5174
GitHub Pages 提供使用文档,桌面应用需要在本地运行。公开仓库的可用命令以对应版本的脚本和文档为准。
十三、怎样验证一个 Agent 项目
Agent 项目的验证至少有两层。
第一层是软件本身:任务状态是否正确、审批是否生效、工具是否真实执行、重启后能否恢复、修改后会不会误用旧测试结果。
第二层是模型完成任务的质量:选用某个服务与模型后,在真实项目里是否找对问题、是否修复成功、用了多少 Token、失败发生在哪里。
Hikari 使用 Vitest 覆盖运行时和服务逻辑,使用 Playwright 驱动 Electron 与文档页面。受控模型响应可以让测试稳定地覆盖审批、中断、恢复和界面连接,但不能据此得出线上模型成功率。
当前开发版本还提供固定提交的仓库评测:在临时副本中执行任务,检查允许修改的路径、必须保留的文件,再运行独立验收,避免 Agent 通过改掉测试获得成功结果。
比较不同模型或工作流时,需要固定仓库版本、任务和验收方式,保留失败记录,再统计成功率、延迟和用量。单个演示成功,或者测试替身全部通过,都不足以证明普遍的开发能力。
仓库提供类型检查、lint、单元测试、桌面构建和 E2E 等验证入口。它们分别覆盖不同层次,真实模型、实际 IDE 宿主、系统安装包和远程部署仍需在对应环境验证。
写在最后
做 Hikari 的过程中,我越来越关注模型回答之外的部分:工具执行前有没有权限边界,修改后有没有有效证据,中断时能不能保留状态,以及用户能不能清楚地审阅最终结果。
这些机制不会让模型永远正确,但可以让一次任务更容易检查,也让出错之后有明确的处理路径。
如果你对 Electron、React、TypeScript 或 AI Agent 工程感兴趣,可以从桌面请求链路、AgentRunner、模型适配器和工作流几个入口开始阅读。也欢迎带着具体使用场景和可复现的问题交流。