All Classes and Interfaces
Class
Description
Agent 核心类 - 实现 ReAct 循环
Agent 循环的退出预算。
设计目标是把"是否继续下一轮"的主导权交给 LLM 自己——只要它返回 content 不再调用工具,
循环就退出。本类只承担三种"保险阀"职责,避免模型在异常情况下无限重复同一动作:
1.
Agent 间通信消息 - Multi-Agent 协作的基本通信单元
消息类型说明:
- TASK: 主控分配给子代理的任务
- RESULT: 子代理返回的执行结果
- FEEDBACK: 检查者对结果的反馈(可能包含改进建议)
- APPROVAL: 检查者认可结果
- REJECTION: 检查者拒绝结果,需要重新执行
- ERROR: 子代理在执行过程中遭遇系统级错误(例如 LLM 调用失败),调用方需识别并优雅处理
Agent 编排器 - Multi-Agent 系统的"主"
负责管理团队、分配任务、路由消息、解决冲突。
采用主从架构:编排器是主,子代理是从。
协作流程:
1.
Agent 角色定义 - Multi-Agent 系统中的角色分工
原生 ANSI 控制序列常量与工具方法。
终端 ANSI 样式辅助。
危险操作识别策略 - 基于静态规则判断哪些工具调用需要人工确认
设计原则:
- 读取类操作(read_file、list_dir、glob_files、grep_code、search_code)不需要确认,无副作用
- 写入/执行类操作(write_file、execute_command)需要确认,有潜在破坏性
- create_project 属于写入操作,默认需要确认
- revert_turn 会批量回写工作区文件,默认需要确认
- MCP 工具来自外部 server,默认都需要确认
审批请求 - 描述一次待确认的工具调用
包含工具调用的完整信息,用于向用户展示"即将执行什么操作"。
审批结果 - 用户对一次工具调用审批的决策
决策类型:
- APPROVED: 批准执行,使用原始参数
- APPROVED_ALL: 批准本次会话所有后续同类工具操作(批量模式)
- APPROVED_ALL_BY_SERVER: 批准本次会话同一 MCP server 的后续操作
- REJECTED: 拒绝执行,Agent 收到拒绝通知后可重新规划
- MODIFIED: 修改参数后执行(用户可以调整命令或文件内容)
- SKIPPED: 跳过本步骤,继续后续操作
危险工具调用的结构化审计日志。
落盘策略:
- 一行一条 JSON(JSONL 格式),按天分文件 audit-YYYY-MM-DD.jsonl
- 默认目录 ~/.yapcli/audit,可通过 -Dyapcli.audit.dir 或 YAPCLI_AUDIT_DIR 覆盖
- 写入失败只在 stderr 提示,不抛出,避免审计故障影响主流程
设计意图:
- 把 Agent 的"实际副作用"变成可回放的事实流
- 行为评估、差错复盘、监控告警的统一数据源
接入点:
-
allow:危险工具执行成功
- deny:被 HITL 拒绝 / 跳过,或被策略层拦截
- error:工具执行抛异常或超时活动
FoldableBlock 注册表。JLine 托管的底部 dock。
当前 YapCLI 浏览器会话状态。
由 Main 持有并注入 ToolRegistry,避免做全局单例污染测试与多会话运行。
中央对话流面板。
代码分析器:基于 JavaParser AST 构建代码关系图谱
代码块数据模型
代码分块器:将代码文件切分为适合 Embedding 的粒度
代码高亮器(基于正则表达式的轻量级实现)。
代码索引管理器:负责将代码库分块、向量化并持久化到 VectorStore
代码关系数据模型(用于构建代码关系图谱)
代码检索器:语义检索 + 图谱检索的统一入口
命令快速拒绝:在 execute_command 进入 HITL 审批 / 真正调用 ProcessBuilder 之前的黑名单 fast-fail。
定位:辅助 HITL 而非主防线。黑名单是出名的反模式(永远列不全),但能拦住 LLM 容易踩的明显破坏性命令,
减少 HITL 弹窗骚扰。真正的安全责任在 HITL 审批和用户判断。
设计取舍:
- 不做完整 shell 解析,只做正则模式匹配,够覆盖明显破坏性命令即可
- 命令替换段 $(...) 和反引号内的内容仍以原文存在,正则会一并扫描,不需要单独展开
- curl / git / 网络命令默认放行,只拦真正破坏性的(rm -rf 全盘、sudo、mkfs 等)
上下文压缩器 - 当对话过长时,自动压缩旧消息
压缩策略:
1.
上下文策略配置。
**设计原则**:没有"长 / 短 / 平衡"模式分档。所有参数都是 maxContextWindow 的简单函数,
全模型走同一套行为,只是 window 大小不同导致触发时机和容量不同。
全局常量:
- 压缩触发阈值:预留摘要输出空间后,再保留 13k token 自动压缩缓冲
按 window 派生:
- 短期记忆预算 = window × 0.45
- 注入到 system prompt 的相关记忆 token 上限 = window × 0.005,封顶 5000
- MCP resource 索引注入:window ≥ 32k 才有意义(再小就挤)
压缩 ReAct 主循环里的
conversationHistory(即 List<LlmClient.Message>)。
与 ContextCompressor 的区别:
- ContextCompressor 压的是 ConversationMemory(YapCLI 的短期记忆条目)
- 本类压的是 Agent 实际发给 LLM 的消息列表
第 3 期 Memory 设计假设"LLM 调用从 shortTermMemory 重建消息",但实际 Agent 直接维护
conversationHistory,与 shortTermMemory 并行。两个度量错位导致旧版压缩从未真正缩短
即将发给 LLM 的 token——本类是在 Agent.run 主循环里"调 LLM 前评估并压缩"的补丁。
算法:
1.短期记忆 - 管理当前对话的上下文
职责:
1.
对话历史快照(TUI 专用)。
消息记录。
会话元数据。
Embedding 客户端,支持 Ollama 本地模型和 OpenAI 兼容的远程 API
执行计划 - 包含一组有依赖关系的任务
web_fetch 的结构化结果。
FetchResult.markdown 为空 / FetchResult.bodyEmpty = true 时,意味着抓到了 HTML 但提取不出正文,
常见原因是 SPA / 防爬墙。LLM 应该意识到这是已知边界,不要反复重试。
FetchResult.truncated = true 表示 markdown 已被截断到调用方指定的最大字符数。
左侧文件树面板。
行内可折叠块。
HITL 审批交互接口 - 定义人工审批的交互契约
实现类负责与用户交互,收集用户对危险操作的审批决策。
当前仓库提供基于终端的实现(TerminalHitlHandler)。
设计约定:
- 审批是同步阻塞操作,实现类需等待用户输入后才返回
- 实现类不负责判断"是否需要审批",该判断由 ApprovalPolicy 负责
- 实现类只负责"展示请求 + 收集决策"
HITL 工具注册表 - 在危险工具调用前插入人工审批
继承自 ToolRegistry,覆写 executeTool 方法,在执行危险操作之前
通过 HitlHandler 向用户请求审批。
如果 HITL 未启用,行为与父类完全相同,无额外开销。
HITL 拒绝 / 跳过路径会写一行 audit(approver=hitl),HITL 通过后由父类 ToolRegistry 写
allow / policy-deny / error,HITL 审批与策略拦截共用同一份 ~/.yapcli/audit/ 文件。
极简版 readability:HTML → 主正文 Markdown。
思路(按优先级):
清理噪声标签:script、style、nav、aside、footer、header、form、iframe、广告 class
找主语义容器:<article>、<main>、role="main"
都没有则给所有 block 元素打分(文本长度 - 链接占比惩罚),选最高分
再把选中容器递归转成 Markdown
不追求与 Mozilla Readability 完全对齐,目标是覆盖博客 / 文档 / 官网这类
SSR 页面的常见结构。SPA 渲染后的空 HTML 会得到空字符串,由调用方提示边界。
Inline 形态的 HITL 审批提示。
行内 diff 渲染:红减、绿加、青色 hunk header。
Inline 流式渲染器:默认形态。
底部输入栏。
jieba-analysis 在首次加载词典时会直接向 stdout 打印初始化信息。
这里在构造分词器时临时静默标准输出,避免污染 CLI 用户界面。
Lanterna 全屏 TUI 形态的
Renderer 适配器。Lanterna 窗口管理器。
Diagnostic logging for model-side traces that are otherwise only streamed to
the terminal.
长期记忆 - 跨对话持久化的关键信息
职责:
1.
YapCLI v16.1.0 - Terminal-First Agent IDE
支持 ReAct、Plan-and-Execute、Memory、RAG、Multi-Agent、HITL、并行工具调用、多模型切换、MCP、CDP 会话复用
第 15 期新增:Skill 系统(三层加载 + load_skill 工具 + SkillContextBuffer 注入)、内置 web-access skill
第 16 期新增:TUI 界面(Lanterna 3)、文件树浏览、代码高亮、对话历史可视化、配置管理面板
第 16.1 期形态修正:抽出 Renderer 接口 + 三个实现(inline/lanterna/plain),默认形态切换为 inline 流式 TUI(Claude Code 风格)
- inline 流式:prompt 下方 inline 状态区、行内可折叠工具块、行内 git diff、单字符 HITL 提示、命令 palette
- lanterna:保留 phase-16 全屏窗口(向后兼容 YAPCLI_TUI=true)
- plain:纯 println 兜底
HITL 增强:路径围栏(PathGuard)、命令快速拒绝(CommandGuard)、操作审计链(AuditLog)—— 见 com.yapcli.policy
Memory 接口 - 记忆系统的统一抽象
分为短期记忆(ShortTermMemory)和长期记忆(LongTermMemory):
- 短期记忆:当前对话的上下文,包括消息历史和工具结果
- 长期记忆:跨对话持久化的关键信息,如用户偏好、项目事实
记忆条目 - Memory 系统的基础数据单元
Memory 管理器 - Memory 系统的门面类
统一管理短期记忆、长期记忆、上下文压缩和检索,
为 Agent 提供简洁的记忆存取接口。
记忆检索器 - 根据查询从短期记忆和长期记忆中检索最相关的信息
检索策略:
1.
网络访问策略。
scheme 白名单:仅允许 http / https
主机黑名单:屏蔽 loopback、site-local、link-local、未指定地址(防 SSRF)
简易 token bucket 限流:每 60 秒最多 30 次请求
当前是基础围栏,覆盖常见 SSRF 场景;面向严苛企业环境时还需补 DNS rebinding 防护、
完整 CIDR 黑白名单、证书校验加固等。
路由 server → client 的通知到注册的 handler。
**关键约束**:handler 在独立 daemon executor 里执行,**不在 transport 的 stdout reader 线程里同步执行**。
否则 handler 内部如果要发 JSON-RPC 请求并等响应,自己等自己的响应,stdout reader 被阻塞读不到响应 → 死锁。
典型场景:server-everything 启动后立即推送 tools/list_changed,handler 调 tools/list 重拉,
stdout reader 线程被挂在 handler.apply 里,tools/list 响应进 buffer 但没人读,最终请求超时。
路径围栏:所有文件类工具调用必须先经过它。
定位:HITL 之前的 LLM 输入合法性检查,不是沙箱(不提供进程隔离)。
解决三类越界场景:
1.
Plain 渲染器:纯 println 模式,等价 phase-15 行为,无折叠、无状态栏。
Plan-and-Execute Agent - 先规划后执行
规划器 - 使用LLM将复杂任务分解为执行计划
安全策略拦截时抛出。
调用方通常在工具执行体里 catch 后转成用户可见的错误字符串。
策略拦截相当于 LLM 的"硬规则失败",不要让它静默通过,也不要让 LLM 重试同样的违规请求。
Loads YapCLI project memory files that are intended to be versioned and
injected into the system prompt at session start.
终端渲染器抽象。
启动时根据环境变量选择渲染器形态。
与
Renderer 协作的 HITL 处理器:
状态(启用开关、全部放行集合)由本类维护,
实际审批 UI 委托给 Renderer.promptApproval(ApprovalRequest)。根面板容器,实现三栏布局。
搜索引擎抽象。
当前实现:
-
SerpApiSearchProvider:商业聚合 API,需 API Key,开箱即用
- SearxngSearchProvider:开源元搜索引擎,需要本地或可访问的 SearXNG 实例,免费
让用户根据成本 / 数据合规 / 离线需求自由切换 provider。
后续如果新增 Brave / Tavily / Exa 等实现,只要继续实现这个接口,无需改动调用方。按环境变量 / .env / 系统属性选择 SearchProvider 实现。
自动选择优先级(未显式 SEARCH_PROVIDER 时):
有
GLM_API_KEY → zhipu(智谱 Web Search,与 GLM 推理共用 Key,国内首选)
有 SERPAPI_KEY → serpapi(国际通用,付费即开即用)
有 SEARXNG_URL → searxng(开源自托管,免费)
都没有 → 占位 zhipu provider,isReady() 为 false,由调用方提示用户
显式 SEARCH_PROVIDER(zhipu / serpapi / searxng)会跳过自动判断。
这里不做单例缓存,由调用方按需缓存(如 ToolRegistry 的 webSearchProvider 字段)。一条搜索结果。
字段顺序与位置(
SearchResult.position)从 1 开始,便于 LLM 按编号引用。
source 是从 url 解析出的域名(host),用于快速识别一手来源。检索结果展示格式化。
保持实现简单:不额外调用 LLM,只根据查询和 Top 结果生成简短摘要,
让 /search 更像“可读搜索结果”,而不是只打印原始代码片段。
SearXNG 搜索 provider。
SearXNG 是开源的元搜索引擎(github.com/searxng/searxng),自己不爬取互联网,
而是把请求转发到 Google / Bing / DuckDuckGo / Brave 等几十个引擎,再聚合返回。
推荐用法:本地 docker 起一个实例
SerpAPI 搜索 provider。
商业聚合服务,帮我们绕过 Google 反爬。需在环境变量或 .env 中配置 SERPAPI_KEY。
一个 Skill 是 YapCLI 沉淀决策与经验的复用单元。
由 SKILL.md 文件解析得到:frontmatter 决定索引段元数据,body 在 LLM 调用 load_skill
时通过 SkillContextBuffer 注入下一轮 user message。
source 标记加载来源,用于 /skill list 展示与三层覆盖的可观测性。
把 jar 内 resources/skills/<name>/ 解压到 ~/.yapcli/skills-cache/<name>/。
解压策略:通过 .version 文件标记当前 jar 内置版本。版本一致跳过;不一致或缺失则覆盖整个目录。
内置 skill 文件清单为硬编码(避免 jar 内 resource walk 的跨平台问题),
当前覆盖:web-access skill 的 SKILL.md / cdp-cheatsheet.md / 6 个 site-patterns。
单 Agent 实例的 skill 注入缓冲区。
生命周期:LLM 调 load_skill → push 到 buffer → 下一轮构造 user message 时 drain → 拼到原内容前。
关键约束:
- drain 是一次性消费(防止跨轮重复注入)
- 同一会话内最多保留 3 个 skill body(上限 3 个,超出 LRU 淘汰最旧)
- 同一 skill 重复 push 会替换旧 body 并刷新到末尾,避免重复
- /clear 命令调 clear() 复位
三个 SubAgent 角色(Planner / Worker / Reviewer)+ 主 Agent 各持一个独立实例,
不共享 buffer,避免角色间提示词污染。
SKILL.md frontmatter 解析器(极简 YAML 子集,不引入 SnakeYAML)。
支持的语法(覆盖 95% 实际写法):
- 单行 key: value
- 多行 key: |\n line1\n line2(以首行缩进推断)
- 行内数组 key: [a, b, c]
不支持(命中即 warnings 报错并跳过该字段,不阻塞整个 skill 加载):
- 嵌套对象 key: { nested: ...
把启用 skill 渲染成 system prompt 索引段。
预算约束(命中即截断 + stderr 警告):
- 单条 description ≤ 500 codepoint
- 启用 skill 数 ≤ 20(按 name 字典序保留前 20)
- 总段大小 ≤ 4096 字符
注入位置:每个 Agent / SubAgent 的 system prompt 末尾,独立段。
Skill 加载与运行时维护。
三层目录扫描顺序(后者整体覆盖前者同名 skill):
1.
Skill 启用状态持久化。
设计:仅持久化 disabled 列表,启用为隐式默认——这样新加的 skill 不会被遗漏。
文件不存在或解析失败一律视为空 disabled,并在 stderr 警告,不阻塞主流程。
临时浮起的命令选择列表。
渲染器状态栏数据载体。
右侧状态栏面板。
子代理 - 可配置角色的轻量 Agent
每个 SubAgent 有独立的角色、系统提示词和对话历史,
但共享 LLM 客户端和工具注册表。
Delegates HITL interaction to the currently active UI implementation.
任务节点 - 表示一个可执行的任务单元
终端能力探测:决定 inline 渲染器的各项特性是否可启用。
终端 HITL 审批处理器
在终端展示审批请求,等待用户键盘输入后返回决策。
支持的交互选项:
y / Enter - 批准本次操作
a - 批准本次会话所有后续同类危险操作(工具维度;MCP 支持 server 维度)
n - 拒绝本次操作
s - 跳过本步骤(SKIPPED)
m - 修改参数后执行(进入参数输入模式)
并发安全:
requestApproval 方法整体 synchronized,确保多 Agent 并行场景下同一时刻只有一个
审批提示活跃,避免 stdout 串扰与 stdin 争抢。
轻量终端 Markdown 渲染器。
目标不是完整支持所有 Markdown 语法,而是把常见的标题、列表、表格、引用和代码块
渲染成更适合 CLI 终端阅读的纯文本布局。
Token 预算管理器 - 确保对话不会超出模型的上下文窗口
策略:
1.
把一组工具调用渲染成
FoldableBlock。工具注册表 - 管理所有可用工具
TUI 入口与降级检测。
TUI 配置面板。
TUI 模式下的 HITL 审批处理器。
Bridges TUI input to the existing Agent runtime.
SQLite 向量存储 + 代码关系图谱持久化
带向量的代码块条目
索引统计
检索结果
基础 HTTP 抓取器:拿 URL → 字节流 → 字符串。
边界:
5MB 响应体上限,超出截断(流式读,避免 OOM)
30s 整体超时(OkHttp callTimeout)
不处理 JS 渲染、不处理登录态 —— 那是第 13/14 期的事
遇到 4xx/5xx 直接抛 IOException,由调用方决定如何向用户呈现
字符集解析:优先 Content-Type charset,其次 HTML meta(Jsoup 会兜底处理),
全失败用 UTF-8。这里只负责拿到字符串,meta 嗅探在
HtmlExtractor 里做。智谱 Web Search provider。