RuiZNClaude--S0---CLI设计

📅 2026/7/22 7:25:34
RuiZNClaude--S0---CLI设计
1. 项目分为两个进程p1RuiZN-core (服务端 / Daemon 进程)角色大脑与大脑执行引擎。职责长驻后台运行asyncio 异步事件循环。所有的“重活儿”——调用大模型 (LLM)、跑本地命令、读写文件、管理 Agent 的上下文状态、处理权限控制全都在这个进程里完成p2RuiZN-cli/tui (客户端 / CLI 进程)角色壳子 / 交互界面。职责轻量级。只是一个命令行工具CLI或者将来的终端界面TUI。它不持有任何核心业务状态只负责把用户的输入打包发给 Core然后把 Core 返回的结果渲染显示在屏幕上。一次性命令比如敲完 kama ping运行完就会退出。2. 如何通信它们怎么通信传输协议TCP 127.0.0.1:7437本地 Loopback 套接字连接。数据格式NDJSON (Newline Delimited JSON即按换行符分隔的 JSON 帧)。C 视角每个 Request/Response 都是一个 JSON 结构末尾带一个 \n。Core 端只要逐行 readline() 就能天然解决粘包/拆包问题3. 为什么不先写成单进程后面再拆核心设计哲学如果你先写成单进程比如把所有逻辑写成一个 Python 脚本后期想改成客户端-服务端架构时会面临极度痛苦的重构你需要把所有直接的“函数调用”全部改成“网络通信、对象序列化、异步响应、超时重试”。一开始就强行拆进程的硬好处解耦极佳GUI/CLI 怎么改、崩溃与否完全不影响后台 Agent 的任务执行。多端支持今天用简单的命令行 kama 调 Core明天写 kama-tui 界面后天甚至能写个 Web 前端Core 的代码一行都不用改。迫使规范强制你在第一天就考虑“网络失败”、“序列化/反序列化”、“异步响应”等真实生产环境中必踩的坑。 总结一句话 Core 是真正的核心后台CLI 只是一个发命令的遥控器。两者通过 TCP 套接字用 JSON 聊天。4. 在面试中如果面试官问出“为什么要采用‘协程/异步 多进程’而不是直接用‘多线程’”回答的核心逻辑是结合 Python 的语言特性GIL与 AI Agent 的应用场景特点既有 IO 密集又有 CPU 密集从“解决什么问题”和“收益是什么”两个维度切入。你可以按照以下三分式逻辑进行回答既展现出深刻的语言特性理解又能突出架构设计的能力第一步指出 Python 的核心限制GIL 锁“首先这与 Python 自身的并发机制 密切相关。PythonCPython 解释器存在 GIL全局解释器锁。如果使用多线程threading在处理 CPU 密集型任务如大数据的序列化/反序列化、本地上下文压缩、复杂 Prompt 解析或数值计算时多个线程无法利用多核 CPU 进行真正的并行计算反而会因为线程频繁切换和锁竞争带来额外的性能开销。”第二步解释为什么单个进程内部用“协程/异步asyncio”“对于单进程内部的 IO 任务我们选择了**协程async/await**而不是多线程原因有两个极致的 IO 吞吐与低开销AI Agent 系统充斥着大量的网络 IO等待大模型 API 返回、流式响应、网络请求。协程是用户态的轻量级调度没有 OS 线程上下文切换Context Switch的内核态开销单线程运行 asyncio 事件循环即可轻松支撑高并发的异步 IO。避开线程安全问题多线程并发时共享内存需要大量的互斥锁Mutex来保证数据一致性极易引发死锁和竞态条件Race Condition。而协程基于单线程事件循环天然避免了复杂的锁机制使得 Agent 的状态管理更清晰。”第三步解释为什么整体架构采用“多进程IPC”“为了突破单进程和 GIL 的限制我们采用多进程来隔离不同的职责模块例如 Daemon 后台服务与 CLI/TUI 前端交互或者未来的密集计算节点真正利用多核与 CPU 隔离多进程各自拥有独立的 Python 解释器和内存空间彻底绕过了 GIL 锁能够真正实现多核并行。故障隔离与状态解耦前端 CLI 挂掉或崩溃完全不会影响后台长考Thinking的 Daemon 进程同时强制要求进程间通过标准的网络/管道协议如 TCP NDJSON通信使得‘界面层’与‘业务大脑’强解耦极大地提高了系统的容错性和扩展性。”5. 命令解析器 /cli/main.py主解析器负责捕获 git --version 这种全局标志add_subparsers(destcommand) 负责生成一个名叫 args.command 的变量add_parser(ping) 则是往许可列表里塞入 ping。用户在终端敲下 RuiZN ping 时args.command 就会被赋值为 ping随后驱动 if args.command ping: 分支执行。步骤 1创建主解析器 (parser)parser argparse.ArgumentParser(progRuiZN,descriptionRuiZNClaude CLI)参数解析progRuiZN指定程序在帮助文档Help Message里显示的名字。如果你在终端敲 RuiZN --help第一行就会显示 usage: RuiZN [-h] [--version] ...。description对这个工具的总说明。git 类比这一步相当于你编写了 git 这个主程序的最外层入口。步骤 2添加全局参数 (--version)parser.add_argument(--version, actionstore_true, helpPrint version and exit)参数解析--version以双短横线开头代表这是一个可选的标志Flag。actionstore_true核心默认状态如果不敲 --version解析出来的 args.version 就是 False。触发状态只要用户在终端敲了 --version不需要在后面传任何值不需要写 --version trueargparse 就会自动把 args.version 赋值为 True。git 类比这就完全等同于你在终端敲git --version 此时命令作用于 git 全局直接打印 Git 版本不需要也不跟任何子命令。步骤 3衍生子解析器容器 (subparsers)subparsers parser.add_subparsers(destcommand)参数解析destcommand最灵魂的参数dest 是 Destination目标属性名 的缩写。它的作用是告诉 Python“等会儿不管用户敲了哪个具体的子命令比如 ping、run、status请把这个子命令的名字作为一个字符串存到解析结果 args 的 command 属性里。”git 类比这一步是在为 git 建立子命令目录树。如果你敲 git commitdestcommand 就会让 args.command commit如果你敲 git pushargs.command 就等于 push。步骤 4注册具体的子解析器 (ping)subparsers.add_parser(ping, helpPing the core daemon)参数解析ping注册子命令的具体名称。只有在这里注册过的字符串命令行才认可。help当用户敲 kama --help 或 kama ping --help 时显示的子命令说明。git 类比这就相当于你在 Git 项目里实现了 git status 或 git checkout 这样的具体功能点。