Initial Agentsd project commit
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
164
docs/01-内核系统调用.md
Normal file
164
docs/01-内核系统调用.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# 01 - 内核系统调用
|
||||
|
||||
agentsd 定义 9 个 syscall 接口。类比 Linux 内核 syscall 表——接口稳定,实现可换(由系统插件提供)。
|
||||
|
||||
---
|
||||
|
||||
## 1. Display
|
||||
|
||||
向用户呈现信息。类比: `write(stdout)` / framebuffer / DRM。
|
||||
|
||||
**管**:给人看的输出 | **不管**:文件写入、设备控制
|
||||
|
||||
```
|
||||
display.text(content)
|
||||
display.rich(markup)
|
||||
display.image(data, format)
|
||||
display.clear()
|
||||
display.notify(message)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Audio
|
||||
|
||||
声音播放与采集。类比: `/dev/snd` / ALSA / PipeWire。
|
||||
|
||||
**管**:扬声器输出、麦克风输入 | **不管**:TTS/STT(插件的事)
|
||||
|
||||
```
|
||||
audio.play(data, format)
|
||||
audio.stop()
|
||||
audio.volume(level)
|
||||
audio.record.start(format)
|
||||
audio.record.stop() -> data
|
||||
audio.record.stream(callback)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. FS
|
||||
|
||||
文件系统。类比: `open / read / write / stat / readdir / inotify`。
|
||||
|
||||
**管**:磁盘文件 | **不管**:结构化数据(Memory)
|
||||
|
||||
```
|
||||
fs.read(path) -> data
|
||||
fs.write(path, data)
|
||||
fs.delete(path)
|
||||
fs.rename(from, to)
|
||||
fs.stat(path) -> metadata
|
||||
fs.list(dir) -> entries
|
||||
fs.watch(path, callback)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Memory
|
||||
|
||||
结构化存储。类比: `mmap / shmem`,但面向 KV + 索引。
|
||||
|
||||
**管**:持久数据、查询 | **不管**:文件(FS)
|
||||
|
||||
```
|
||||
memory.read(key) -> value
|
||||
memory.write(key, value)
|
||||
memory.delete(key)
|
||||
memory.list(prefix?) -> keys
|
||||
memory.search(query) -> results
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Network
|
||||
|
||||
远程通信。类比: `socket / connect / bind / listen / send / recv`。
|
||||
|
||||
**管**:对外连接、监听 | **不管**:本地 IPC(内核 gRPC 总线)
|
||||
|
||||
```
|
||||
net.request(url, method, body?) -> response
|
||||
net.connect(addr, protocol) -> conn
|
||||
net.listen(port, protocol) -> listener
|
||||
net.send(conn, data)
|
||||
net.recv(conn) -> data
|
||||
net.close(conn)
|
||||
net.available() -> bool
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Process
|
||||
|
||||
子进程管理。类比: `fork / execve / waitpid / kill / pipe`。
|
||||
|
||||
**管**:子进程生命周期、stdio | **不管**:插件间路由(内核调度)
|
||||
|
||||
```
|
||||
proc.spawn(cmd, args, env?) -> pid
|
||||
proc.kill(pid)
|
||||
proc.wait(pid) -> exitcode
|
||||
proc.stdin(pid, data)
|
||||
proc.stdout(pid) -> data
|
||||
proc.signal(pid, sig)
|
||||
proc.list() -> [pid]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Timer
|
||||
|
||||
定时调度。类比: `timer_create / timerfd_create`。
|
||||
|
||||
**管**:时间触发 | **不管**:用户事件(Input)
|
||||
|
||||
```
|
||||
timer.once(delay, callback) -> id # 到期后通过 PluginBridge.StreamCall 投递事件
|
||||
timer.cron(expr, callback) -> id
|
||||
timer.cancel(id)
|
||||
timer.now() -> timestamp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. HID
|
||||
|
||||
屏幕截取与输入模拟。类比: `/dev/input` + `/dev/fb` + uinput。
|
||||
|
||||
能力可缺失。
|
||||
|
||||
**管**:屏幕读取、输入模拟 | **不管**:向用户展示(Display)、用户主动输入(Input)
|
||||
|
||||
```
|
||||
hid.capture(region?) -> image
|
||||
hid.mouse(x, y, action)
|
||||
hid.keyboard(key, action)
|
||||
hid.ocr(region?) -> text
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Input
|
||||
|
||||
用户主动输入。类比: `read(stdin)` / evdev。
|
||||
|
||||
**管**:用户给的东西 | **不管**:文件读(FS)、录音(Audio)、屏幕读(HID)
|
||||
|
||||
```
|
||||
input.text() -> string
|
||||
input.key() -> keyevent
|
||||
input.clipboard() -> data
|
||||
input.event() -> event
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 设计原则
|
||||
|
||||
1. **接口稳定,实现可换** — syscall 签名不变,系统插件可替换(= 换驱动不改应用)
|
||||
2. **每个独立** — 可单独实现、测试、编译(= 内核模块独立)
|
||||
3. **能力可缺失** — 无声卡则 Audio 不可用,不崩(= Linux 无设备则驱动不加载)
|
||||
4. **权限在此层** — 白名单外的 syscall 拒绝(= seccomp)
|
||||
5. **离线 = Network 不可用** — 其余八个正常(= 拔网线不影响本地)
|
||||
6. **内核不做业务** — TTS/浏览器/Agent 全是插件(= 内核不含 Web 服务器)
|
||||
179
docs/02-插件模型.md
Normal file
179
docs/02-插件模型.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# 02 - 插件模型
|
||||
|
||||
## 三种插件(对标 Linux 三层)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 标准插件 ← 应用服务(nginx、docker) │
|
||||
│ 可依赖基础插件 + 其他标准插件 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ 基础插件 ← 基础 daemon(udevd、resolved) │
|
||||
│ 只依赖 9 个 syscall,无插件依赖 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ 系统插件 ← 内核模块 / 设备驱动(.ko) │
|
||||
│ 注册为 syscall 的实现 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ agentsd ← Linux 内核 + systemd(PID 1) │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 系统插件(= 内核模块 / 驱动)
|
||||
|
||||
为 syscall 提供具体实现。类比 `insmod alsa_driver.ko`。
|
||||
|
||||
```yaml
|
||||
id: alsa-audio
|
||||
type: system
|
||||
provides: audio
|
||||
entry: ./libalsa_audio.so
|
||||
```
|
||||
|
||||
- FFI 加载(.so/.dylib/.dll),零开销
|
||||
- 只限 Rust / C ABI
|
||||
- 同一 syscall 可有多个驱动,同时只激活一个
|
||||
- 无依赖
|
||||
|
||||
---
|
||||
|
||||
### 基础插件(= systemd 基础 unit,无依赖)
|
||||
|
||||
只调 syscall,不调其他插件。类比 `systemd-resolved.service`(只用内核网络栈)。
|
||||
|
||||
```yaml
|
||||
id: tts-edge
|
||||
type: basic
|
||||
syscalls:
|
||||
- audio.play
|
||||
- network.request
|
||||
exports:
|
||||
- name: speak
|
||||
```
|
||||
|
||||
- 独立进程,gRPC/TCP 通信(后续切 UDS/Named Pipe)
|
||||
- 零插件依赖,加载顺序无所谓(= 无 After/Requires)
|
||||
- 任意语言
|
||||
|
||||
---
|
||||
|
||||
### 标准插件(= systemd 应用 unit,有依赖)
|
||||
|
||||
组合其他插件。类比 `nginx.service`(After=network.target, Requires=...)。
|
||||
|
||||
```yaml
|
||||
id: voice-agent
|
||||
type: standard
|
||||
syscalls:
|
||||
- input.text
|
||||
- display.text
|
||||
depends:
|
||||
- tts-edge
|
||||
- stt-whisper
|
||||
- chat-agent
|
||||
exports:
|
||||
- name: voice_chat
|
||||
```
|
||||
|
||||
- 可依赖基础插件 + 其他标准插件
|
||||
- 按依赖拓扑排序加载(= systemd ordering)
|
||||
- 任意语言
|
||||
|
||||
---
|
||||
|
||||
## 通信:gRPC(= D-Bus)
|
||||
|
||||
类比 Linux 的 D-Bus 进程间通信总线,agentsd 用 gRPC。
|
||||
|
||||
### 为什么 gRPC
|
||||
|
||||
- protobuf 二进制,快
|
||||
- 流式 RPC(音频流、文件 watch)
|
||||
- 所有语言都有库
|
||||
- `.proto` = 接口契约 + 代码生成
|
||||
|
||||
### 传输分层
|
||||
|
||||
| 插件类型 | 传输 | 延迟 | Linux 类比 |
|
||||
|---|---|---|---|
|
||||
| 系统插件 | FFI | ~纳秒 | 内核态函数调用 |
|
||||
| 基础/标准(本机,当前) | gRPC/TCP | ~毫秒 | D-Bus over TCP |
|
||||
| 基础/标准(目标) | gRPC/Unix socket / Windows Named Pipe | ~微秒 | D-Bus over UDS |
|
||||
| 远程(可选) | gRPC/TCP | ~毫秒 | D-Bus over TCP |
|
||||
|
||||
### proto 示例
|
||||
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
|
||||
service FS {
|
||||
rpc Read(ReadRequest) returns (ReadResponse);
|
||||
rpc Write(WriteRequest) returns (WriteResponse);
|
||||
rpc Delete(DeleteRequest) returns (DeleteResponse);
|
||||
rpc List(ListRequest) returns (ListResponse);
|
||||
rpc Watch(WatchRequest) returns (stream WatchEvent);
|
||||
}
|
||||
|
||||
service Audio {
|
||||
rpc Play(stream AudioChunk) returns (PlayResponse);
|
||||
rpc Record(RecordRequest) returns (stream AudioChunk);
|
||||
}
|
||||
```
|
||||
|
||||
### 插件间调用(经内核路由)
|
||||
|
||||
```protobuf
|
||||
service PluginBridge {
|
||||
rpc Call(CallRequest) returns (CallResponse);
|
||||
rpc StreamCall(CallRequest) returns (stream CallResponse);
|
||||
}
|
||||
|
||||
message CallRequest {
|
||||
string target = 1;
|
||||
string fn = 2;
|
||||
bytes args = 3;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 生命周期管理(= systemctl)
|
||||
|
||||
| agentsd 命令 | systemd 对标 | 作用 |
|
||||
|---|---|---|
|
||||
| `agentsd start <id>` | `systemctl start` | 启动插件 |
|
||||
| `agentsd stop <id>` | `systemctl stop` | 停止插件 |
|
||||
| `agentsd restart <id>` | `systemctl restart` | 重启 |
|
||||
| `agentsd reload <id>` | `systemctl reload` | 热更新 |
|
||||
| `agentsd status` | `systemctl status` | 状态查询 |
|
||||
| `agentsd list` | `systemctl list-units` | 列出所有插件 |
|
||||
| `agentsd logs <id>` | `journalctl -u` | 查日志 |
|
||||
| `agentsd enable <id>` | `systemctl enable` | 开机自启 |
|
||||
| `agentsd disable <id>` | `systemctl disable` | 取消自启 |
|
||||
|
||||
---
|
||||
|
||||
## 加载顺序(= systemd boot)
|
||||
|
||||
```
|
||||
1. 系统插件(FFI,注册 syscall 实现) ← 类比内核模块加载
|
||||
2. 基础插件(gRPC,任意顺序) ← 类比 basic.target
|
||||
3. 标准插件(gRPC,拓扑排序) ← 类比 multi-user.target
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 看门狗(= Restart=always)
|
||||
|
||||
插件崩溃 → agentsd 自动重启(可配置策略):
|
||||
- `always`:总是重启
|
||||
- `on-failure`:异常退出才重启
|
||||
- `never`:不重启
|
||||
|
||||
---
|
||||
|
||||
## 权限(= seccomp + cgroup)
|
||||
|
||||
- 系统插件:内核信任,无限制
|
||||
- 基础插件:按 `syscalls` 白名单精确到方法(如 `fs.list`)校验,也支持 `fs` / `fs.*` / `*` 授权(= seccomp filter)
|
||||
- 标准插件:syscalls + depends 白名单,未声明的一律拒绝
|
||||
50
docs/03-实施路线.md
Normal file
50
docs/03-实施路线.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 03 - 实施路线
|
||||
|
||||
## 阶段 1:内核骨架(= 跑起来的 PID 1) ✅ 已完成
|
||||
|
||||
- [x] Rust workspace:`agentsd` 主二进制
|
||||
- [x] gRPC server(tonic over TCP,后续切 UDS)
|
||||
- [x] 实现 FS syscall(read/write/delete/rename/stat/list)
|
||||
- [x] 实现 Memory syscall(SQLite KV + FTS5 trigram search,默认写入 data/memory.db)
|
||||
- [x] 实现 Input syscall(stdin)
|
||||
- [x] 实现 Display syscall(stdout)
|
||||
- [x] 实现 Process syscall(spawn/kill/wait/stdin/stdout)
|
||||
- [x] 实现 Timer syscall(once/cancel/now + 回调事件通道)
|
||||
- [x] 实现 Audio syscall(stub,待系统插件)
|
||||
- [x] 实现 HID syscall(stub,待系统插件)
|
||||
- [x] 实现 Network syscall(HTTP via curl,待替换)
|
||||
- [x] Plugin Bridge(注册/调用路由/心跳,注册状态写入 data/plugins.json)
|
||||
- [x] 插件加载:gRPC 握手 + 注册
|
||||
- [x] echo 测试插件(Python)验证基础链路
|
||||
- [x] ai_test 手动验证插件(Python,默认 disabled/autoload false)覆盖 Display/Memory/FS/Process/Timer/权限拒绝
|
||||
- [x] proto 定义:完整 9 个 service + PluginBridge
|
||||
|
||||
**验证结果**:agentsd 启动 → Python 插件通过 gRPC 注册 → ai_test 调用 Display/Memory/FS/Process/Timer syscall 并验证权限拒绝。
|
||||
|
||||
## 阶段 2:完善核心 syscall
|
||||
|
||||
- [ ] Network:替换 curl 为 hyper/reqwest 原生 HTTP client
|
||||
- [ ] FS.Watch:接入 notify-rs 文件监听
|
||||
- [ ] Timer.Cron:接入 cron 表达式解析
|
||||
- [ ] Audio:接入系统音频后端(wasapi/alsa)
|
||||
- [ ] HID:接入屏幕截取(Windows: win32 API)
|
||||
- [ ] Unix socket / Named pipe 传输(替代 TCP)
|
||||
|
||||
## 阶段 3:接入 Agent
|
||||
|
||||
- [ ] Agent 插件:Input → LLM(Network) → Display
|
||||
- [ ] Hermes adapter(Python gRPC 插件)
|
||||
- [ ] 本地模型插件(llama.cpp via Process syscall)
|
||||
|
||||
## 阶段 4:插件管理(= systemctl)
|
||||
|
||||
- [ ] agentsd start / stop / restart / status / list / logs
|
||||
- [ ] 看门狗(崩溃自动重启)
|
||||
- [ ] 依赖解析 + 拓扑排序
|
||||
- [ ] install / uninstall / enable / disable
|
||||
|
||||
## 阶段 5:生态
|
||||
|
||||
- [ ] Web UI 插件(shell)
|
||||
- [ ] 语音交互(Audio + TTS/STT 插件)
|
||||
- [ ] 桌面自动化(HID + computer-use 插件)
|
||||
117
docs/04-项目结构.md
Normal file
117
docs/04-项目结构.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# 04 - 项目结构
|
||||
|
||||
```
|
||||
Agentsd/
|
||||
├── Cargo.toml # workspace 根
|
||||
├── README.md # 设计总览
|
||||
│
|
||||
├── docs/ # 设计文档
|
||||
│ ├── 01-内核系统调用.md
|
||||
│ ├── 02-插件模型.md
|
||||
│ ├── 03-实施路线.md
|
||||
│ └── 04-项目结构.md # 本文件
|
||||
│
|
||||
├── proto/ # 协议定义(单一事实来源)
|
||||
│ └── agentsd.proto # 9 service + PluginBridge
|
||||
│
|
||||
├── core/ # Rust 源码
|
||||
│ ├── proto/ # gRPC 协议 crate
|
||||
│ │ ├── Cargo.toml
|
||||
│ │ ├── build.rs
|
||||
│ │ └── src/lib.rs
|
||||
│ │
|
||||
│ └── agentsd/ # 主二进制 crate
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── main.rs # 入口
|
||||
│ ├── server.rs # gRPC server
|
||||
│ ├── plugin.rs # 插件注册表 + data/plugins.json 持久化
|
||||
│ ├── paths.rs # 程序目录 data/ 路径
|
||||
│ ├── callback.rs # Timer 回调事件通道
|
||||
│ ├── permission.rs # syscall 权限白名单校验
|
||||
│ └── syscall/ # 9 个 syscall 模块
|
||||
│ ├── mod.rs
|
||||
│ ├── display.rs
|
||||
│ ├── audio.rs
|
||||
│ ├── fs.rs
|
||||
│ ├── memory.rs
|
||||
│ ├── network.rs
|
||||
│ ├── process.rs
|
||||
│ ├── timer.rs
|
||||
│ ├── hid.rs
|
||||
│ └── input.rs
|
||||
│
|
||||
├── data/ # 运行时数据(程序启动后自动创建)
|
||||
│ ├── memory.db # Memory syscall SQLite 数据库
|
||||
│ └── plugins.json # 插件注册状态
|
||||
│
|
||||
└── plugins/ # 插件(任意语言)
|
||||
├── _sdk/ # 共享 Python gRPC stub
|
||||
│ ├── __init__.py
|
||||
│ ├── agentsd_pb2.py
|
||||
│ └── agentsd_pb2_grpc.py
|
||||
│
|
||||
├── echo/ # 测试插件
|
||||
│ ├── plugin.yaml
|
||||
│ └── echo_plugin.py
|
||||
│
|
||||
├── ai_test/ # AI 手动验证插件(enabled=false,autoload=false)
|
||||
│ ├── plugin.yaml
|
||||
│ └── ai_test_plugin.py
|
||||
│
|
||||
├── hermes/ # Hermes Agent 桥接(63 tool)
|
||||
│ ├── plugin.yaml
|
||||
│ └── hermes_plugin.py
|
||||
│
|
||||
└── claudecode/ # Claude Code CLI 桥接
|
||||
├── plugin.yaml
|
||||
├── claudecode_plugin.py
|
||||
└── test_chat.py
|
||||
```
|
||||
|
||||
## 布局原则
|
||||
|
||||
| 目录 | 职责 | 规则 |
|
||||
|---|---|---|
|
||||
| `docs/` | 设计文档 | 只放 .md |
|
||||
| `proto/` | 协议定义 | 只放 .proto,单一事实来源 |
|
||||
| `core/` | Rust 代码 | workspace members |
|
||||
| `data/` | 运行时数据 | 默认路径为程序所在目录的 data 文件夹 |
|
||||
| `plugins/` | 所有插件 | 每个插件一个目录,含 plugin.yaml |
|
||||
| `plugins/_sdk/` | 共享 stub | 生成一次,插件 import 引用,不复制 |
|
||||
|
||||
## 构建
|
||||
|
||||
```bash
|
||||
cargo build --release # 约 6.1MB 单二进制
|
||||
```
|
||||
|
||||
## 运行
|
||||
|
||||
```bash
|
||||
# 启动内核
|
||||
./target/release/agentsd.exe
|
||||
|
||||
# 启动插件(各开一个终端)
|
||||
python plugins/hermes/hermes_plugin.py
|
||||
python plugins/claudecode/claudecode_plugin.py
|
||||
```
|
||||
|
||||
## 手动验证插件
|
||||
|
||||
`plugins/ai_test` 是专门给 AI/人工做端到端验证的插件,`plugin.yaml` 中 `enabled: false`、`autoload: false`,默认不应被自动加载。
|
||||
|
||||
```bash
|
||||
RUST_LOG=agentsd=info ./target/release/agentsd.exe
|
||||
python plugins/ai_test/ai_test_plugin.py
|
||||
```
|
||||
|
||||
## 重新生成 SDK
|
||||
|
||||
```bash
|
||||
python -m grpc_tools.protoc \
|
||||
-Iproto \
|
||||
--python_out=plugins/_sdk \
|
||||
--grpc_python_out=plugins/_sdk \
|
||||
proto/agentsd.proto
|
||||
```
|
||||
Reference in New Issue
Block a user