chore: Add Chinese README and refactor NPU backend to use Unix domain sockets

- Introduced a new Chinese version of the README (README_CN.md) to provide localized documentation for AgentOS.
- Refactored the NPU bridge to utilize Unix domain sockets instead of HTTP loopback, enhancing security and performance.
- Updated the NPU backend to include a server socket configuration, ensuring proper communication over Unix sockets.
- Modified the Ntex client to support both network and Unix socket transports, improving flexibility in backend communication.
- Adjusted validation logic to enforce the use of Unix sockets for local model endpoints, rejecting loopback HTTP addresses.
- Enhanced error messages and documentation throughout the codebase to clarify the new socket-based architecture.
This commit is contained in:
emmettlu
2026-08-02 15:48:09 +08:00
parent eee7fed161
commit f863f83960
8 changed files with 1157 additions and 65 deletions
+209
View File
@@ -0,0 +1,209 @@
# AgentOS 工程约定
本文件面向在本仓库内工作的代码代理。修改前先读本文件、根
`Cargo.toml`,再读目标 crate 的源码。不要根据旧 Python 版本、Octos 或
`npu_features/` 中的厂商样例臆测当前行为;`crates/` 才是实现事实来源。
## 项目目标
AgentOS 是运行在裸 Linux 上的 low-level OS agent,而不是 Linux 发行版、
容器沙箱或内核 fork。核心原则是尽量复用 Linux 原生能力:进程 UID/GID、
文件权限、Unix 凭据、pidfd、`no_new_privs`、Btrfs subvolume/snapshot 和设备
ioctl。
当前安全模型是稳定的 `AgentId -> (owner UID, agent UID, agent GID)` 绑定:
- agent 进程不能以 UID 0 或 GID 0 运行;
- 每次执行前必须核对进程的 effective UID/GID
- 一个状态数据库中,agent UID 只能绑定给一个 active `AgentId`
- 不额外构造 namespace、容器或通用 sandbox
- `no_new_privs` 是补充保护,不能替代 UID/GID 和工具策略;
- 模型不能获得任意 shell,更不能直接获得 root shell。
不要把 `owner_uid``agent_uid` 混为一谈。前者表示拥有者,后者才是内核
实际执行主体。新增 daemon 或 broker 时,Unix socket 对端必须用内核提供的
peer credentials 鉴权,不能信任请求体里的 UID。
## 当前成熟度边界
已经可用:
- `agentos` one-shot CLI、doctor 和确定性 fake backend
- OpenAI-compatible Chat Completions / Responses 非流式后端;
- `agentos.chat.v1` 内部协议、严格工具 schema、预算和循环检测;
- 只读 Linux 工具、SQLite 审计/记忆、Btrfs worldline 与 copy fallback
- CALCULET PCIe ABI、Rust ioctl/DMA 包装、Calbin 解析、张量/命令结构;
- Candle/Qwen3 host pipeline、tool-call 模板和 CALRT 张量适配;
- 旧 llama-server UDS bridgeHTTP 消息格式直接承载在 AF_UNIX 上,不经过 TCP。
尚未完成:
- 纯 Rust CALRT 的 CCU relocation、job launch/completion 和设备 KV reset
- 可在真实 NPU 上完成推理的 `npu_candle` backend
- typed mutation broker 和任何变更型系统工具;
- 长驻 AgentOS control daemon、control UDS RPC、服务安装和完整硬件端到端测试。
`ConfiguredRuntime::submit()` 当前必须 fail closed 并返回
`HardwareExecutionUnavailable`。在没有真实板卡证据前,不得把
`npu_candle` 标记为 ready,不得让 `auto` 选择它,也不得用 mock 测试宣称
硬件推理已验证。
## Workspace 与模块所有权
`agentos-cli` 外,`crates/` 下均为 library crate。
| Crate | 职责 |
| --- | --- |
| `agentos-cli` | `agentos``agentos-npu-bridge` 两个 binary;只做参数解析和装配入口 |
| `agentos-runtime` | composition root、环境配置、identity/backend/tool 装配、doctor |
| `agentos-agent` | 有预算的 agent loop、工具调度、循环检测、审计事件 |
| `agentos-protocol` | provider-neutral `agentos.chat.v1` 类型与 `ChatBackend` trait |
| `agentos-inference` | ntex HTTP、OpenAI-compatible、subprocess、fake/scripted backend |
| `agentos-tools` | fail-closed registry、schema 校验、审批契约和 Linux 只读工具 |
| `agentos-core` | ID、principal、execution identity、审计和 worldline 公共类型 |
| `agentos-kernel` | Linux/rustix 边界、凭据、pidfd、文件原子写、Btrfs ioctl |
| `agentos-memory` | SQLite WAL、FTS5、principal 绑定、memory 和 audit event |
| `agentos-worldline` | 类 Git 的 filesystem history、branch/commit/diff/rollback/recovery |
| `agentos-npu` | NPU probe、旧 bridge、Rust Candle NPU backend 装配 |
| `agentos-candle` | Qwen3 模板/tokenizer/sampling 与 Calbin prefill/decode host runner |
| `calculet-pcie-abi` | 驱动 0.9.0 / ABI 1.0.0 的 64-bit Linux ioctl 布局 |
| `calculet-pcie` | 安全的设备、BAR、DMA、MSI、reset 和 board/process API |
| `calculet-calrt` | Calbin、allocator、tensor、command stream、DeviceIo 和 runtime 骨架 |
保持依赖方向从高层向低层:
```text
agentos-cli -> agentos-runtime -> agentos-agent/tools/inference/npu/worldline/memory
agentos-npu -> agentos-candle -> calculet-calrt -> calculet-pcie -> calculet-pcie-abi
agentos-kernel/core/protocol 是底层公共边界
```
不要让底层 crate 反向依赖 CLI 或 runtime。跨 provider 的消息类型放在
`agentos-protocol`Linux syscall/ABI 放在 `agentos-kernel` 或对应的
`calculet-*` cratecomposition 逻辑只放在 `agentos-runtime`
## 不可破坏的设计约束
### Linux 与系统调用
- 项目只支持 Linux;当前 CALCULET ABI 只验证过 64-bit Linux。
- 项目自有的低层 syscall/ioctl 优先走 `rustix`,不要直接新增 `libc` 调用。
- 这不表示最终二进制完全不链接 libc;Rust `std`、OpenSSL 等依赖仍可使用
系统 ABI。
- `unsafe` 仅允许出现在无法避免的 ABI 边界,必须就结构布局、指针生命周期
和 opcode 写英文 `SAFETY` 注释,并在调用前完成长度、对齐和范围校验。
- 不要为了 worldline patch 内核。优先使用现有 Btrfs ioctl;非 Btrfs 环境保留
copy fallback。
### 工具与权限
- registry 必须显式 allowlist;未知工具一律拒绝。
- 所有 tool schema 默认 strictobject、列出全部 required、
`additionalProperties: false`
- 参数和输出必须有字节上限,外部命令必须有 deadline、`kill_on_drop`,并移除
API key 环境变量。
- 只有标记为 `ConcurrencyClass::Safe` 的只读工具可以并行;变更工具必须
exclusive。
- 现有 `ApprovalLedger` 只是进程内、单次、精确参数绑定的契约。实现 mutation
前还必须有 typed broker、内核凭据校验、持久审计和失败恢复,不能把审批 ID
当作任意命令授权。
- 不得增加通用 `shell``exec`、任意路径写入或任意 systemd unit 工具。
### 推理后端
- 内部统一使用 `agentos.chat.v1`provider 差异留在 backend adapter。
- 缺少 NPU 硬件时的 mock 是远程 OpenAI-compatible 模型,不是内置
`FakeBackend`。远程传输可以使用 HTTP 或 HTTPS;使用 HTTPS 时必须验证 peer。
- 本机常驻模型服务必须使用 filesystem Unix domain socket,禁止监听或连接
localhost、loopback 或其他 TCP 地址。纯 Rust Candle in-process 路径不需要 IPC。
- 本机 llama-server 可以保留 OpenAI-compatible HTTP 消息格式,但必须通过
ntex 自定义 connector 承载在 AF_UNIX 上,用户配置只能暴露 socket path,不能
接受本机 URL。
- OpenAI-compatible HTTP 和 UDS HTTP client 使用 `ntex`,不要引入 `reqwest`
- 禁止自动 redirect;响应大小、超时和 retry 必须有界。
- 支持 Chat Completions 与 Responses 两种方言,但不要假设所有兼容服务支持
完全相同的字段。新增兼容逻辑必须有请求构造和响应解析测试。
- subprocess backend 只通过 stdin/stdout 传 JSONstderr 仅用于有界错误信息;
不要把 secret 传给子进程。它只作为显式测试/bridge adapter,不能代表本机
常驻模型传输,也不能进入 `auto`
- `auto` 当前顺序是 UDS legacy NPU、远程 OpenAI-compatible。Fake 和
subprocess 必须显式选择,Rust Candle NPU 在硬件提交完成前不能进入 auto。
### NPU
- `npu_features/` 是忽略提交的厂商源码/部署抓取,仅作逆向参考,不能成为
发布包运行时依赖。
- 原始版本边界是 driver package 0.9.0、driver ABI 1.0.0、CALRT 0.7.6。
- ioctl struct 使用 `repr(C, packed)`,任何改动都必须同步 size/opcode 测试。
- DMA 单次上限 8 MiB,已知 H2C/C2H 各 8 个 channel;不要绕过现有验证。
- Calbin 参数部署会真实写设备。没有用户明确要求和真实硬件测试计划时,不要
默认开启 `deploy_parameters`
- captured Qwen3 fixture 的 logits 是 151936tokenizer vocab 是 151669;额外
267 个 padded logits 必须在采样前屏蔽。
- host-side `MockDevice` 测试只能验证解析、地址、buffer 和命令编码,不能证明
job submission、同步、KV cache 或输出数值正确。远程模型 mock 同样不能证明
NPU 硬件正确。
- legacy llama-server 的默认 socket 是 `/run/agentos/npu.sock`doctor 必须检查
它确实是可写的 Unix socket,不能仅检查路径存在。
### Worldline 与持久化
- Btrfs commit tree 使用 readonly snapshotbranch/current 使用 writable
snapshot。
- copy fallback 用于开发和无 Btrfs 环境,但当前不会提供内核强制的只读
commit tree。不要在文档里把它描述成与 Btrfs 等价的不可变性。
- commit 是内容/元数据哈希标识;rollback 必须创建新 commit,不能改写历史。
- checkout 要保留 transaction journal、目录 fsync 和可恢复的 replaced tree。
- 分支提交必须检查 base HEAD,禁止 stale branch 覆盖新 HEAD。
- SQLite principal 绑定不可静默重绑;schema 变更要考虑已有数据库升级。
## Rust 与依赖规则
- 使用 workspace 的 Rust edition,不添加 MSRV 或 `rust-toolchain.toml`
- 第三方依赖集中写在根 `Cargo.toml``[workspace.dependencies]`
- 版本只写主版本号,例如 `serde = "1"`,不要固定 `1.2.3`
- 内部 crate 统一用 `*.workspace = true`
- 读取依赖源码时,从 `$CARGO_HOME/registry/src` 找实际锁定版本,不靠记忆猜 API。
- 优先复用已有 crate 和抽象,不复制协议类型、HTTP client、schema validator、
runtime probe 或设备 ABI。
- 代码注释默认英文;用户可见文档分别维护英文与中文。
- 不要加入 Python、`reqwest` 或直接 `libc` 依赖。
- 保持开发/测试 profile 的快速编译取向,除非有基准数据,不要随意调高 dev
优化或减少 codegen units。
## 修改流程
1.`rg` 定位实现和调用方,先确认改动属于哪个 crate。
2. 先写清安全边界和失败模式;系统层能力默认 fail closed。
3. 修改公共协议时,同步所有 backend、tool adapter、CLI 和双语 README。
4. 新增环境变量时,同步 `RuntimeConfig::from_env`、doctor 和配置表。
5. 新增 NPU ABI 时,对照 `npu_features/cal-pcie-0.9.0` 或 CALRT 源码,并补布局、
opcode、边界和 mock 测试。
6. 不要改写或删除用户的 `npu_features/` 抓取、模型文件和未提交工作。
完成前至少执行:
```bash
cargo fmt --all --check
cargo test --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
涉及 CLI 时还要实际运行相关命令;涉及 OpenAI-compatible 时至少覆盖两种 API
方言的 serialization/parsing;涉及硬件而本机无板卡时,明确报告未执行的验证。
部分 NPU 测试依赖本地、被 `.gitignore` 忽略的
`npu_features/snapshot_20260801`。fixture 不存在时,应将硬件抓取测试与普通
workspace 测试分层,而不是把模型数据提交进仓库或伪造通过结果。
## 完成标准
一次改动只有在以下条件都满足时才算完成:
- crate 边界和依赖方向没有被破坏;
- 非法输入、权限不足、后端缺失和硬件缺失均 fail closed
- 无 secret 出现在日志、tool output、子进程或 doctor 报告中;
- 单元/集成测试覆盖正常路径与关键拒绝路径;
- fmt、workspace test、严格 clippy 通过;
- README 与实际成熟度一致,未把 host-side `MockDevice` 或远程模型 mock 写成
NPU 硬件验证。