Kaku终端AI引擎源码剖析:Agent循环、流式事件与提示词缓存完整指南
【免费下载链接】Kaku🎃 A fast, out-of-the-box terminal built for AI coding.项目地址: https://gitcode.com/gh_mirrors/kaku5/Kaku
Kaku 是一款为 AI 编码打造的极速终端(A fast, out-of-the-box terminal built for AI coding),内置了完整的 AI 聊天引擎:按Cmd+L呼出 AI 助手,它能读文件、跑命令、搜代码,还能自动续写任务。本文带你从源码层面拆解 Kaku 终端 AI 引擎的三大核心设计——Agent 循环、流式事件系统与提示词缓存,帮你理解一个生产级终端 AI 助手是怎么做出来的 🎃
一、先认识引擎:三个文件看懂整体架构
Kaku 的 AI 引擎代码高度集中,入门只需盯住三个地方:
| 模块 | 路径 | 职责 |
|---|---|---|
| 共享聊天引擎 | ai_chat_engine/mod.rs | Agent 循环、流式事件、系统提示词组装 |
| API 客户端 | ai_client.rs | OpenAI 兼容 / Responses 双协议流式请求 |
| 工具注册表 | ai_tools/registry.rs | 暴露给模型的全部函数工具与 JSON Schema |
这个引擎同时服务于两个入口:GUI 里Cmd+L弹出的覆盖层,以及独立的k命令行聊天(见 cli_chat/mod.rs)。注释里写得很清楚:引擎"不含任何 GUI 依赖",纯 Rust 类型 + 消息通道,这正是它能在两个表面复用且行为一致的原因。
二、Agent循环:让模型自主干满25轮的run_agent
打开 mod.rs,run_agent函数就是整个引擎的心脏。它在独立后台线程上运行,核心逻辑是一个简单的for循环:
调用模型(chat_step) → 有工具调用? ├─ 没有 → 发送 Done,本轮结束 └─ 有 → 逐个执行工具 → 结果回灌 messages → 进入下一轮每轮开始前有三道"防御性"动作,是源码里最值得抄的设计:
- 微压缩(micro_compact):调用 compact.rs 对上一轮的工具输出瘦身——
fs_read只留前 300 行、grep_search只留前 100 行、shell_exec留头 100 行 + 尾 40 行,超过 16KB 的超长输出只保留"头 12KB + 尾 3KB"并插入[N bytes elided]标记。 - 摘要折叠:历史接近 120KB 预算时,优先用更便宜的 fast_model做一次原地摘要,而不是硬截断;摘要失败会进入 3 轮冷却,避免每轮都发一次阻塞请求。
- 软警告:第 20 轮(
SOFT_ROUND_WARN)时向消息历史注入一条"只剩 5 轮,请收尾"的提醒,引导模型自己总结收尾,而不是硬生生砍在任务中间。
循环上限是MAX_AGENT_ROUNDS = 25。触发上限时不会静默失败,而是发送一条明确的错误事件,告诉用户"任务可能只做了一半,可以继续追问"。
审批门:写操作必须经人点头
工具执行前有一道安全关卡(见 approval.rs):凡是变更类操作(如fs_write、fs_delete、fs_patch),Agent 线程会发出ApprovalRequired事件并阻塞等待——渲染端弹出确认框,用户点"允许"后通过SyncSender<bool>回复,最长等待 600 秒,超时视为拒绝。模型还会收到一条"用户拒绝了该操作"的工具错误,从而自我纠正而不是死循环重试。
三、流式事件:10个StreamMsg消息撑起整个界面
Agent 线程和渲染线程之间只靠一个mpsc::Sender<StreamMsg>通道通信,事件定义极其干净:
| 事件 | 触发时机 |
|---|---|
AssistantStart | 模型即将输出文本,渲染端插入空占位气泡 |
Token/Reasoning | 正文 token / 隐藏的推理内容(分开存储、分开渲染) |
ToolStart/ToolDone/ToolFailed | 工具开始 / 完成(带结果预览)/ 失败 |
ApprovalRequired | 需要同步审批(携带回复通道) |
ResponsesState | Responses 协议的无状态转录快照 |
Done/Err | 结束 / 出错 |
两个细节很见功力:
- 结果预览按工具定制:
fs_read显示"共 N 行"、grep_search显示"N 条匹配"、web_fetch显示"抓取 N 字节"(tool_result_preview函数),UI 状态栏因此紧凑可读。 - 输出总量硬预算:整轮用户对话最多向 UI 推送 480KB 的文本/推理内容(
MAX_STREAMED_OUTPUT_BYTES)。超出即显式报错"本轮是部分完成",绝不把没执行完的工具轮次当成成功——这个"宁错勿假"的取舍是新手最容易忽略的健壮性设计。
另外,ai_client.rs 对 SSE 流也设置了层层熔断:单行 1MB、事件数 65536、工具调用 32 次……防的是"失控循环的流",而不是限制正常长回答。
四、提示词缓存设计:三个省钱的隐藏技巧
这是全文最精妙的一节。LLM 计费里,系统提示词每轮都要重新发送,如果前缀逐字节稳定,就能命中 Anthropic 等厂商的提示词缓存折扣。Kaku 为此做了三层设计:
技巧1:静态系统提示词 = 6个片段按固定顺序拼接
build_system_prompt()用include_str!编译期内联 assets/prompts/chat/ 下的 6 个片段:
- voice.txt:人格与文风("禁止 emoji、禁止列表、禁止 filler 套话")
- safety.txt:安全边界
- output_format.txt:输出格式
- tool_discipline.txt:工具调用纪律
- root_cause.txt:根因分析要求
- external_helpers.txt:外部工具使用
固定顺序 + 每轮字节完全一致 = 缓存前缀天然稳定。每个片段开头还有<!-- name: ... kakuVersion: 0.12.0 -->元数据块,由strip_prompt_metadata在运行时剥掉——这样文件可以版本化 diff,注入的提示词却保持纯净。
技巧2:动态信息全部挪到"环境消息"
日期、当前目录、locale、终端尺寸这些每轮都在变的字段,坚决不放进系统提示词,而是由build_environment_message()组装成一条独立的 user 消息排在提示词之后。源码注释直言其动机:"让静态系统提示词能命中 Anthropic 的 prompt-cache 折扣"。
技巧3:MEMORY.md 故意避开缓存前缀
Kaku 支持 Soul 机制(SOUL/STYLE/SKILL/MEMORY 四个身份文件,见 soul.rs)。其中:
- SOUL/STYLE/SKILL(用户手写的稳定身份)→ 追加在系统提示词末尾;
- MEMORY.md(后台"管家"模型自动改写的滚动记忆)→ 放进环境消息,注释写着:"避免管家改写记忆时每一轮都打爆提示词缓存"。
稳定内容前置、易变内容后置,三条规则贯穿始终——这就是提示词缓存设计的全部心法 💡
五、工具注册表:模型能做什么由代码说了算
registry.rs 中的all_tools()一次性声明了全部工具:fs_read / fs_list / fs_write / fs_patch / fs_delete、shell_exec / shell_bg / shell_poll、grep_search / symbol_search、project_summary / file_tree、web_fetch / web_search、memory_read / soul_read、http_request。每个工具都是"名称 + 描述 + JSON Schema"三件套。
Agent 循环执行前会做白名单校验:模型只准调用"本轮实际宣告"的工具。若模型模仿历史对话里的旧工具名(比如切换搜索引擎前的web_search记录),系统不杀轮次,而是回一条"该工具不可用"的错误工具结果让模型自我纠正——错误信息也是上下文的一部分,这比直接崩溃优雅得多。
六、新手能带走的3个设计要点
- Agent 循环本质是"带预算的 while":轮数(25)、历史字节(120KB)、输出字节(480KB)三道预算 + 摘要降级 + 软警告收尾,缺一不可。
- 事件驱动比回调简单十倍:一个枚举 + 一条 mpsc 通道,就能把"模型思考中 → 工具运行中 → 等待审批"的复杂状态干净地推给 UI。
- 提示词是产品也是工程:静态化、分段化、版本化、易变内容后置——省的是真金白银的 token 费用。
想继续深挖,推荐阅读顺序:mod.rs(Agent 循环)→ compact.rs(上下文瘦身)→ ai_client.rs(流式协议)→ assets/prompts/(提示词全文)。看完你会发现,一个优秀的终端 AI 引擎,靠的不是魔法,而是每一处都写清楚的取舍。
【免费下载链接】Kaku🎃 A fast, out-of-the-box terminal built for AI coding.项目地址: https://gitcode.com/gh_mirrors/kaku5/Kaku
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考