【免费下载链接】OpenSquirrelFor people who get distracted by agents. A native Rust/GPUI control plane for running Claude Code, Codex, Cursor, and OpenCode side by side — because if youre going to be squirrely, you might as well optimize for it.项目地址https://gitcode.com/gh_mirrors/ope/OpenSquirrel点击查看免费下载OpenSquirrel 是一个基于 Rust GPUI 的原生 AI Agent 控制台,可以把 Claude Code、Codex、Cursor Agent、OpenCode 等 5 种 Agent CLI 并排运行在同一窗口中。这篇文章带你拆解它最核心的工程难题:如何解析 5 种 Agent CLI 的 JSON 输出流,以及如何实现跨 CLI 的多轮会话——全部集中在 src/runtime.rs 这一个文件里完成。为什么 Agent CLI 输出流解析这么棘手每种 AI 编码 CLI 的方言都不一样:有的输出纯文本(直接给人看的 TUI 内容);有的输出一行一条 JSON 事件(stream-json 协议);有的事件里文本是增量片段(delta),有的则是完整段落;Token 统计、会话 ID、错误信息藏的事件类型也各不相同。OpenSquirrel 的做法很直接:为每种 CLI 写一个适配器解析函数,把方言翻译成统一的消息模型。5 种 CLI 输出流速览:谁用 JSON,谁用纯文本RuntimeCLI 命令输出模式解析函数Claude Codeclaudestream-json(JSON 流)parse_claude_jsonCodexcodexJSON 事件流parse_codex_jsonCursor Agentcursor agentJSON 流parse_cursor_jsonOpenCodeopencodeJSON 流parse_opencode_jsonGemini CLIgemini纯文本(无 JSON)逐行直接透传前 4 种走 JSON 流(is_json_mode),Gemini 则按纯文本逐行输出——这也是 README.md 中运行时对照表的核心内容。JSON 流解析核心:逐行读取 事件分发逐行解析,失败即跳过所有解析函数签名几乎一致:输入一行文本,输出本轮是否结束的布尔值。核心套路三步走:serde_json::from_str尝试把整行解析为 JSON;读取顶层type字段判断事件类型;match分发到对应的处理分支。解析失败就静默跳过——这一点对抗CLI 输出的杂音行非常关键。Claude:parse_claude_json(src/runtime.rs)Codex:parse_codex_json(src/runtime.rs)OpenCode:parse_opencode_json(src/runtime.rs)Cursor:parse_cursor_json(src/runtime.rs)四类事件:文本增量、工具调用、Token 统计、错误以 Claude Code 为例,stream-json流里最重要的事件只有 4 类:事件类型含义OpenSquirrel 的处理content_block_delta文本/思考的增量片段追加进缓冲,拼出完整行再上屏assistant助手消息块只提取tool_use(避免文本重复)result本轮结束,附带 usage 与费用解析 Token 统计、成本、session_id,返回 true 结束本轮error出错转发AgentMsg::Error一个典型的result事件长这样(节选):{ type: result, session_id: abc-123, total_cost_usd: 0.012, usage: { input_tokens: 820, output_tokens: 140 } }增量拼行:line_buf 小缓冲的巧思流式输出里,一个词的增量可能被拆成好几个 delta,甚至把一行的前半段单独发出来。OpenSquirrel 在解析函数外维护一个line_buf字符串缓冲:每收到一段text增量就push_str进缓冲;缓冲里一旦出现\n,就把完整的一行drain出去发送;遇到content_block_stop/result时,把缓冲区剩余的最后半行冲刷上屏。这个十几行的机制,解决了流式文本截半行显示的常见毛刺问题。统一消息模型:一切皆 AgentMsg解析器不直接碰 UI,而是往一个async_channel里投递事件。UI 侧在 src/app.rs 定义的AgentMsg枚举中只关心 7 种消息:OutputLine/StderrLine:输出行 / 错误行ToolCall:工具调用(如 Bash、Read、Edit)TokenUpdate:Token 与成本统计Error:错误信息Done { session_id }:本轮结束,并带回会话 IDRemoteCursor:远程 tmux 轮询游标解析(生产者)与渲染(消费者)彻底解耦——换任何一种 CLI,UI 代码都不用动。多轮会话实现:持久进程 vs 一次性续接这是 src/runtime.rs 中agent_thread主循环最精彩的部分:5 种 CLI 用两种不同的策略实现多轮。策略一:claude 的持久多轮模式Claude Code 支持--input-format stream-json --output-format stream-json --verbose全双工流式模式。OpenSquirrel 在 src/lib.rs 的build_persistent_runtime_args中规范化这些参数,然后走专用的agent_thread_claude_persistent(src/runtime.rs):进程只启动一次,stdin 保持打开;每收到一条新提示词,就往 stdin 写一行 JSON:{ type: user, message: { role: user, content: 你的提示词 } }stdout 线程持续跑parse_claude_json,直到result事件才发出Done { session_id };下一轮继续写 stdin,上下文完全保留,无需重启进程。策略二:one-shot CLI 的会话续接Codex、Cursor、OpenCode 是一发一答模式:每轮都要重新起进程,靠会话 ID 续接上下文:OpenCode:追加--session id --continueCursor:追加--resume id会话 ID 从上一轮Done消息带回,存在应用状态里UI 层则用SESSION:id\n提示词的私有前缀把两者打包传递,由 src/lib.rs 的parse_session_prompt统一拆解。值得借鉴的 3 个设计点适配器模式拉平方言差异:4 个解析函数签名完全一致,主循环里一个if/else就能切换 CLI,新增第 6 种 Agent 只需再写一个parse_xxx_json;bool返回值作为轮次结束信号:解析到终止事件就返回true,主循环立即break,不依赖进程退出;解析逻辑在本地与远程复用:SSH 到远端机器跑 Agent 时,OpenSquirrel 用 tmux 快照轮询屏幕,但喂给解析器的函数与本地完全相同(src/runtime.rs)——一套方言翻译,两处使用。项目已归档,作者的经验是终端已经赢了——但 SPEC.md 与这套流式解析代码,依旧是理解多 Agent 编排的好教材。赞分享【免费下载链接】OpenSquirrelFor people who get distracted by agents. A native Rust/GPUI control plane for running Claude Code, Codex, Cursor, and OpenCode side by side — because if youre going to be squirrely, you might as well optimize for it.项目地址https://gitcode.com/gh_mirrors/ope/OpenSquirrel点击查看免费下载相关推荐A2A 流式输出与多轮对话实战基于 LangGraph 的 Currency Agent 深度解析A2A 流式输出与多轮对话实战基于 LangGraph 的 Currency Agent 深度解析 本篇技术指南聚焦 Agent2Agent A2A 协议中人工智能AI AgentAPI设计gpt-computer-assistantUpsonicChat 会话层深度解析多轮会话编排、流式/HITL 与成本观测gpt computer assistantUpsonicChat 会话层深度解析多轮会话编排、流式/HITL 与成本观测 Upsonic 框架的 ups人工智能大模型AI AgentAgent 框架自主智能体工具调用RAGAgent 记忆Agent 编排temporal-ai-agent多轮对话AI Agent与Temporal工作流temporal ai agent多轮对话AI Agent与Temporal工作流 Temporal AI Agent 是一个开源项目通过展示AI Agen创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考