开发文档 ifu 团队 2026-08-05 · 9 分钟

ifu Agent 模块架构与扩展指南

开发者视角:核心模块划分、无 cgo 依赖,以及如何新增一个命令

ifu Agent 模块架构与扩展指南

本文面向想了解 ifu Agent 内部实现、或希望为其扩展能力的开发者。它采用清晰的模块化架构,全部依赖为无 cgo 库,支持 CGO_ENABLED=0 交叉编译。

1. 架构总览

cmd/main.go                    入口:参数解析、运行模式选择(前台/服务)、功能自检打印
├── internal/service/          服务管理:Windows SCM / Linux systemd + ServerManager(三协议服务器生命周期)
│   └── internal/server/       HTTP (:42000) / TCP (:42001) / UDP (:42002) 服务器
│       ├── internal/power/    命令分发核心:电源策略 + 扩展控制命令路由
│       │   ├── internal/control/      桌面控制实现(音量/屏幕/键盘/鼠标/剪贴板)
│       │   └── internal/capability/   功能可用性检测
│       └── internal/discovery/        UDP 设备发现
└── pkg/
    ├── types/                 协议结构(PowerCommand/CommandResponse)、常量
    └── logger/                日志(按日切分 + 10MB 大小轮转)

命令流转:HTTP/TCP/UDP 服务器 → PowerController.ExecuteCommand → MAC 验证 → 电源命令 | 扩展控制命令

2. 模块接口

2.1 pkg/types — 协议类型

  • PowerCommand:命令请求,Cmd/MAC + 扩展参数 Value/Text/Key/Mods/X/Y/Button/Scroll
  • CommandResponse:命令响应,Status/Message + 查询返回值 Data
  • PowerController:电源控制器接口(ExecuteCommand/GetLocalMAC/GetMACByIP/ValidateMAC
  • Server / ServerManager / ServiceManager / DiscoveryService / Logger:服务器、服务、发现、日志接口

命令常量定义在 pkg/types/constants.goCmd* 系列,与命令协议文档一致)。

2.2 internal/control — 桌面控制

四个控制器接口:

type VolumeController interface {
    GetVolume() (int, error)                 // 0-100
    SetVolume(volume int) error              // 0-100,越界报错
    GetMuted() (bool, error)
    SetMuted(muted bool) error
}

type ScreenController interface {
    TurnOff() error
    TurnOn() error
}

type InputController interface {             // 键盘 + 鼠标
    KeyTap(key string, mods []string) error
    KeyType(text string) error               // Unicode 文本
    MouseMoveTo(x, y int) error
    MouseClick(button string) error          // left/right/middle
    MouseWheel(detents int) error
}

type ClipboardController interface {
    Read() (string, error)
    Write(text string) error
}

平台实现通过 build tag 拆分,无 cgo 交叉编译验证通过:

文件 构建标签 实现
volume_windows.go windows go-wca(Core Audio COM,纯 Go)
volume_linux.go linux pactl 命令(PulseAudio/PipeWire-pulse)
screen_windows.go windows user32 SC_MONITORPOWER(syscall)
screen_linux.go linux xset dpms(仅 X11)
input.go 全部 makc(Windows SendInput / Linux uinput / macOS CGEvent)
clipboard.go 全部 atotto/clipboard(Linux 需 xclip/xsel/wl-copy)

2.3 internal/capability — 功能自检

type Feature struct {
    Name      string `json:"name"`
    Available bool   `json:"available"`
    Reason    string `json:"reason,omitempty"`
}
type Capabilities struct {
    Features []Feature  // 固定顺序: power, volume, screen, keyboard, mouse, clipboard
}
func Check() *Capabilities
func (c *Capabilities) Available(name string) bool
func (c *Capabilities) Reason(name string) string
  • Windows 检测:ProcessIdToSessionId 判断交互会话(Session 0 = 服务模式,交互类功能不可用)
  • Linux 检测:euid(电源)、pactl(音量)、DISPLAY+xset/Wayland(屏幕)、/dev/uinput 写权限(键盘/鼠标)、xclip/xsel/wl-copy(剪贴板)
  • 不变量:Available=trueReason 为空;falseReason 必须说明原因

使用位置:前台启动打印、Windows 服务启动日志、GET /capabilities、命令失败提示。

2.4 internal/power — 命令分发

  • NewPowerController():工厂创建,注入音量/屏幕/剪贴板控制器;输入控制器初始化失败仅告警不致命(命令执行时返回不可用原因)
  • ExecuteCommand(cmd):MAC 验证(懒加载,sync.Once 并发安全)→ 扩展命令路由 → 电源策略(Windows shutdown / Linux 多命令回退 + D-Bus)

3. 扩展指南

3.1 新增一个命令(以 brightness_set 为例)

  1. 常量pkg/types/constants.go 添加 CmdBrightnessSet = "brightness_set"
  2. 参数:若需要新参数类型,在 PowerCommand 添加字段(含 json:"...,omitempty"
  3. 处理器internal/power/controller.goexecuteControlCommand 添加 case,实现 handleBrightnessSet(参考 handleVolumeSet:nil 控制器走 controlUnavailable
  4. 控制器internal/control/control.go 定义接口(如 BrightnessController),平台文件实现,NewPowerController 注入
  5. 能力检测internal/capability 添加 checkBrightness()FeatureBrightness 常量
  6. 测试internal/power/controller_test.go 添加分发与错误用例;control 包添加解析函数单测
  7. 文档:命令协议文档命令表 + README 命令表同步

3.2 新增一个平台实现

  • 新文件加 //go:build windows//go:build linux(含 +build 兼容行)
  • 工厂函数在平台文件内定义,跨平台文件只引用接口
  • 交叉编译验证:CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ./cmd

4. 测试

测试文件 覆盖内容
pkg/types types_test.go JSON 编解码、omitempty、Data 字段、命令常量一致性
internal/control input_test.go 按键/修饰键/鼠标按钮名称解析、keyMap 完整性
internal/control volume_test.go pactl 音量输出解析(含异常格式)
internal/capability capability_test.go 结构完整性、顺序稳定、Available/Reason 不变量
internal/power controller_test.go 命令分发路由、nil 控制器错误提示、查询类 Data 返回、MAC 验证路径

运行:go test ./...

真实设备注入(按键/鼠标落到桌面)、真实音量/剪贴板修改不纳入单元测试(会干扰本机桌面),由手工冒烟测试覆盖。

5. 已知限制

功能 限制
键盘/鼠标 需要交互桌面会话(服务模式 Session 0 不可用);Linux 需 root 或 /dev/uinput 权限
剪贴板 Linux 运行时依赖 xclip/xsel(X11)或 wl-copy/wl-paste(Wayland)
屏幕开关 Linux 仅 X11(Wayland 不支持 xset dpms)
音量 作用于默认播放设备(Linux 为 @DEFAULT_SINK@)
电源 前台模式需关机权限(Linux 需 root);服务模式天然具备

继续阅读

关联工具

想看更多?订阅我们的 RSS

第一时间获取 ifu 团队的文章与工具更新