feat(waiter): daemon模式 + localuse本机外设插件

waiter 新增 --daemon 后台驻留模式 (daemon.go):
  - 维持 homed 连接,TUI实例经 Unix socket 接入
  - 单客户端串行模型:每个TUI独占homed响应,新客户端回放缓冲(256行)
  - 设备桥场景可无 homed 运行(纯设备桥驻留)
  - 设备桥看护循环:WS断开自动重连(3-5s间隔)
  - conn.go 新增 daemonConn 类型,dial() 优先检测 daemon

localuse 插件 (internal/plugins/localuse/):
  - local_screensee / local_camerasue / local_speakeruse
  - local_screensue / local_clipboardsee / local_clipboardsue / local_computeruse
  - 跨平台实现(Linux/macOS/Windows),能力与 waiter device.go 对齐
  - headless服务器上缺依赖工具自动返回安装提示

SDK sync: third_party SetToolBlocks 多模态类型同步
README 补充 daemon 模式使用文档
This commit is contained in:
JianFeeeee
2026-08-27 09:27:15 +08:00
parent 8207ad3385
commit 88934ea98e
7 changed files with 1058 additions and 0 deletions

View File

@ -19,6 +19,12 @@ type Conn interface {
}
func dial(cfg *Config) (Conn, error) {
// 优先连接运行中的 daemon(后台驻留模式)
if daemonIsRunning() {
if c, err := dialDaemon(); err == nil {
return c, nil
}
}
if cfg.Remote != "" {
return dialRemote(cfg.Remote, cfg.APIKey)
}
@ -52,6 +58,39 @@ func dialLocal(socket, apiKey string) (Conn, error) {
return lc, nil
}
// daemonConn 是连接到运行中 waiter daemon 的轻量封装。
// 协议与 localConn 完全一致(行式 \n 分隔),但不做 /auth(daemon 已集中鉴权)。
type daemonConn struct {
conn net.Conn
r *bufio.Reader
}
func dialDaemon() (Conn, error) {
sock := daemonSocketPath()
c, err := net.DialTimeout("unix", sock, 3*time.Second)
if err != nil {
return nil, fmt.Errorf("daemon %s: %w", sock, err)
}
return &daemonConn{conn: c, r: bufio.NewReader(c)}, nil
}
func (c *daemonConn) Send(line string) error {
_, err := fmt.Fprintf(c.conn, "%s\n", line)
return err
}
func (c *daemonConn) ReadLine() (string, error) {
s, err := c.r.ReadString('\n')
if err != nil {
return "", err
}
return strings.TrimSuffix(s, "\n"), nil
}
func (c *daemonConn) Close() error {
return c.conn.Close()
}
type localConn struct {
conn net.Conn
r *bufio.Reader