适配器体系
wesgine 的外设适配器(Adapter)体系提供 Cell 与外部世界的连接能力。所有适配器通过 CellSpec 声明式装配,按 Cell 物理隔离,生命周期由引擎统一管理。
概览
CellSpec 声明
│
▼
Cell Boot
│
├── Channel Adapters IM 渠道(企业微信/飞书/钉钉/...)
├── Email Adapter 邮件收发
├── MCP Adapters MCP Server 连接
├── Cron Adapter 定时任务
├── HeadlessBrowser 服务端匿名浏览器
├── Playwright 用户浏览器自动化
├── Desktop 桌面自动化 Device Agent
├── STT Adapter 语音转写(Whisper)
└── Plugin Runtime JSON-RPC 子进程插件
适配器分类
Channel(IM 渠道)
支持多平台即时通讯渠道接入:
spec := wesgine.CellSpec{
ID: "dept-legal",
Channels: []channel.ChannelConfig{
{
Platform: "wecom",
Account: "legal-bot",
Config: map[string]string{
"corp_id": "wx123456",
"agent_id": "1000001",
},
SecretRef: config.SecretRef{Source: "env", Value: "WECOM_SECRET"},
},
{
Platform: "feishu",
Account: "legal-feishu",
// ...
},
},
}
支持的平台: 企业微信、飞书、钉钉、Telegram、Discord、Slack 等。
Cell 隔离: 不同 Cell 使用不同的 bot 凭证,消息物理隔离。
Email(邮件)
spec := wesgine.CellSpec{
ID: "dept-legal",
Email: []email.Config{
{
Address: "ai@legal.example.com",
IMAP: email.IMAPConfig{Host: "imap.example.com", Port: 993},
SMTP: email.SMTPConfig{Host: "smtp.example.com", Port: 587},
Password: config.SecretRef{Source: "env", Value: "EMAIL_PASSWORD"},
},
},
}
IMAP 轮询: Cell 处于 Warm 状态时自动轮询新邮件。
MCP(Model Context Protocol)
spec := wesgine.CellSpec{
ID: "dept-legal",
MCPs: []mcp.ServerConfig{
{
Name: "legal-mcp",
Transport: "stdio",
Command: []string{"/opt/mcp/legal-server"},
},
{
Name: "crm-mcp",
Transport: "sse",
URL: "http://crm-service:8080/mcp",
},
},
}
运行时管理:
// 动态注册/更新
cell.MCPs().Upsert(ctx, mcp.ServerConfig{Name: "new-mcp", ...})
// 连接探测
cell.MCPs().Probe(ctx, "legal-mcp")
// 连接/断开
cell.MCPs().Connect(ctx, "legal-mcp")
cell.MCPs().Disconnect(ctx, "legal-mcp")
Cron(定时任务)
spec := wesgine.CellSpec{
ID: "dept-legal",
Cron: []cron.JobConfig{
{
Name: "weekly-report",
Schedule: "0 9 * * 1", // 每周一 9:00
AgentID: "reporter",
Prompt: "生成本周法务工作汇报",
},
},
}
INV-SEED-01:CellSpec.Cron 是出生声明,只在 Cell 首次 boot 播种进 wes_cron_jobs,此后存储是唯一权威。运行时增删改通过 cell.Cron() Handle。
HeadlessBrowser(无头浏览器)
服务端匿名抓取,使用 chromedp:
spec := wesgine.CellSpec{
ID: "my-cell",
HeadlessBrowser: &wesgine.HeadlessBrowserConfig{
// CellSpec 非 nil 即启用
},
}
Playwright(用户浏览器自动化)
服务端 subprocess + 用户浏览器扩展:
spec := wesgine.CellSpec{
ID: "my-cell",
Playwright: &wesgine.PlaywrightConfig{
// 管理 Playwright MCP 子进程
},
}
两种模式:
sandbox:服务端 Playwright 管理的浏览器实例user:用户已登录的浏览器(通过扩展连接)
Desktop(桌面自动化)
客户端二进制,通过 MCP 协议连接:
spec := wesgine.CellSpec{
ID: "my-cell",
Desktop: &wesgine.DesktopConfig{
Command: "/path/to/device-agent",
Transport: "stdio", // 本地 stdio
// 或 Transport: "sse", URL: "..." // 远程 SSE
},
}
AX-5 物理边界: Desktop Agent 二进制运行在客户端,代码由 wesgine 提供(adapter/desktop/),消费应用编译/分发。
STT(语音转写)
spec := wesgine.CellSpec{
ID: "my-cell",
STT: &wesgine.STTConfig{
// CellSpec.STT 非 nil 即启用
// 使用 Whisper 转写
},
}
Plugin(JSON-RPC 子进程插件)
spec := wesgine.CellSpec{
ID: "my-cell",
Plugins: []wesgine.PluginDir{
"/opt/plugins/my-plugin", // 含 manifest.yaml + 可执行文件
},
}
Boot 时 Manager 扫描目录、启动子进程、桥接 Tools 到 Cell ToolRegistry。受 CellQuotas.MaxPlugins 限制。
声明式装配
装配原则
所有适配器通过 CellSpec 声明式装配,遵循以下原则:
- CellSpec 是声明:描述 Cell 应该具有什么能力
- 装配发生在 Cell Boot:声明转化为运行时实例
- 播种语义:Cron/Email 是出生声明,首次 boot 后存储是权威(INV-SEED-01)
- 覆盖语义:Channels/MCPs 的声明就是唯一副本(无运行时存储)
两类适配器的差异
| Cron / Email | Channels / MCPs | |
|---|---|---|
| 运行时存储 | 有(wes_cron_jobs / wes_email_configs) | 无(spec 就是副本) |
| 声明语义 | 出生声明,首次播种 | 覆盖声明,每次 boot 生效 |
| 运行时修改 | 通过 Handle API | 通过 UpdateSpec |
| INV-SEED-01 | 适用 | 不适用 |
配额限制(INV-QUOTA-05)
每类适配器有数量上限,在唯一增长点判定:
| 适配器 | 配额字段 | 判定位置 |
|---|---|---|
| IM Channels | MaxIMChannels | UpdateSpec 的 append 路径 |
| MCP Servers | MaxMCPServers | UpdateSpec 的 append 路径 |
| Cron Jobs | MaxCronJobs | cron.Scheduler.Add |
| Email Accounts | MaxEmailAccounts | email.Store.PutAccount |
| Skills | MaxSkillsInstalled | 技能安装的唯一入口 |
运行时生命周期
Cell 温度与适配器
| 温度 | 适配器状态 |
|---|---|
| Hot | 全部活跃 |
| Warm | goroutine 运行(Cron tick、IMAP 轮询) |
| Cool | 停止,首请求自动 WarmUp |
| Cold | Stopped,需显式启动 |
外设需 Warm:有活跃 Cron 任务或 IMAP 轮询的 Cell 无法降到 Cool。
生命周期回调
Cell.Start()
│
├── adapters.seedSpecOnce() 播种 Cron/Email(首次)
├── channel.Start() 启动 IM 渠道
├── email.StartPolling() 启动邮件轮询
├── mcp.ConnectAll() 连接所有 MCP
├── cron.Start() 启动定时调度器
├── headlessBrowser.Init() 初始化无头浏览器
├── playwright.Start() 启动 Playwright
├── desktop.Connect() 连接桌面代理
├── stt.Init() 初始化语音转写
└── plugin.Manager.Start() 启动所有插件
│
▼
Cell 运行中
│
▼
Cell.Stop()
│
├── plugin.Manager.Drain() 关闭所有插件
├── cron.Stop()
├── email.StopPolling()
├── mcp.DisconnectAll()
└── ...
自定义适配器开发
新适配器检查清单
- 在
adapter/<name>/下实现 - 不加 engine 级
AttachXxx()— 使用声明式装配 - Cell 声明
CellSpec.Xxx+cell.Xxx().Add/Remove/List - 实现 Start/Stop 生命周期
- 实现配额检查(如需)
- 添加到 CellSpec 嵌入的
CellAdapterSpec
判断树
新能力 X →
├── 引擎机制? → Tier E / Hypervisor
├── 业务技能? → Tier C / Cell(Skill)
├── 用户浏览器? → CellSpec.Playwright
├── 桌面/剪贴板? → CellSpec.Desktop
├── 服务端匿名爬取? → CellSpec.HeadlessBrowser
├── 其他客户端硬件? → AX-5:消费应用自建 + cell.MCPs()
└── 新外设协议? → adapter/ + Cell 声明式装配
相关 Handle API
| Handle | 说明 |
|---|---|
cell.Channels() | IM 渠道管理 |
cell.Email() | 邮件管理 |
cell.MCPs() | MCP Server 管理 |
cell.Cron() | 定时任务管理 |
cell.HeadlessBrowser() | 无头浏览器状态 |
cell.Playwright() | Playwright 状态 |
cell.Desktop() | Desktop Agent 状态 |
cell.Skills() | 技能管理(Tier C) |