# KDE 休眠抑制扩展 — Agentic 工程文档

## 目标

在 pi-coding-agent 运行于 KDE 桌面时，于任意 agent 或 subagent 执行期间阻止系统进入休眠/挂起；执行结束后自动释放抑制锁。提供可选配置 flag，在需要时一并阻止息屏/锁屏。

## 范围（MVP）

- 事件驱动加锁/解锁（`agent_start` / `agent_end`）
- 引用计数保证重入安全
- `kde-inhibit` 主路径 + `systemd-inhibit` 回退
- `wakelock-screen` 配置 flag（CLI > 环境变量 > 默认）
- `/wakelock` 状态查询命令
- 优雅降级与进程退出兜底清理

## 核心机制

### 抑制工具选择

| 优先级 | 工具 | 命令示例 |
|--------|------|----------|
| 1 | `kde-inhibit` | `kde-inhibit --power [--screenSaver] sleep infinity` |
| 2 | `systemd-inhibit` | `systemd-inhibit --what=sleep:idle --mode=block ... sleep infinity` |

`kde-inhibit` 直接调用 PowerDevil 的 `PowerManagement.Inhibit`，与 KDE 空闲自动挂起逻辑对齐。`systemd-inhibit` 在 logind 层硬阻断，作为无 `kde-cli-tools` 时的回退。

### 长驻子进程

休眠抑制锁绑定持有它的进程生命周期。一次性 D-Bus 调用或 `pi.exec` 等待命令结束均无法维持锁。扩展通过 `node:child_process.spawn` 启动长驻 `sleep infinity` 子进程，在 `release()` 时 `kill` 释放。

### subagent 覆盖

subagent 运行在父 agent 的 tool 执行窗口内，天然处于顶层 `agent_start…agent_end` 范围，无需单独监听 subagent 事件。

## 配置 flag：息屏/锁屏抑制

- **CLI flag**：`--wakelock-screen`（`pi.registerFlag("wakelock-screen", ...)`）
- **环境变量**：`PI_WAKELOCK_INHIBIT_SCREEN`（`1` / `true` / `yes` 视为开启）
- **优先级**：CLI flag > 环境变量 > 默认 `false`
- **行为**：开启时 `kde-inhibit` 追加 `--screenSaver`
- **回退局限**：`systemd-inhibit` 不支持屏保/锁屏抑制；回退路径下若 flag 开启，仅抑制休眠并一次性提示

## 生命周期

```mermaid
flowchart TD
  agentStart["agent_start 事件"] --> inc["refCount += 1"]
  inc --> checkAcq{"refCount == 1 ?"}
  checkAcq -->|yes| acquire["spawn kde-inhibit 长驻子进程"]
  checkAcq -->|no| skip1["复用现有锁"]
  agentEnd["agent_end 事件"] --> dec["refCount -= 1"]
  dec --> checkRel{"refCount == 0 ?"}
  checkRel -->|yes| release["kill 子进程释放锁"]
  checkRel -->|no| skip2["保持锁"]
  shutdown["session_shutdown / process exit"] --> force["强制 kill 并清零 refCount"]
```

## 文件结构

```
extensions/
  index.ts                 # 扩展入口：flag、事件、/wakelock 命令
  wakelock/
    config.ts              # 常量、resolveInhibitScreen、buildInhibitCommand
    types.ts               # 只读类型定义
    environment.ts           # PATH 探测 kde-inhibit / systemd-inhibit
    inhibitor.ts           # SleepInhibitor：spawn / release / isActive
    manager.ts             # WakelockManager：引用计数与降级告警
```

## 事件装配

| 事件 | 动作 |
|------|------|
| `agent_start` | `manager.onAgentStart()` — refCount++，首次 acquire |
| `agent_end` | `manager.onAgentEnd()` — refCount--，归零 release |
| `session_shutdown` | `manager.dispose()` |
| `process exit / SIGINT / SIGTERM` | `manager.dispose()` 兜底 |

## 健壮性与降级

- 两种抑制工具均不可用时：一次性 `notify`，之后静默
- `spawn` 失败或子进程意外退出：重置状态，不阻塞 agent
- `agent_end` 缺失时由 `session_shutdown` 与进程信号兜底

## 验证

```bash
npm run typecheck && npm run lint

# 加载扩展（无 LLM 调用）
pi -ne -e . --no-session

# 带息屏抑制
pi -ne -e . --no-session --wakelock-screen

# agent 运行期间（另开终端）
pgrep -af "kde-inhibit.*sleep infinity"   # KDE 主路径
loginctl list-inhibitors                   # systemd-inhibit 回退路径
# 或在 pi 会话中执行 /wakelock 查看状态
```

执行中应看到 `kde-inhibit` 长驻进程（主路径）或 `loginctl` 抑制条目（回退路径）；agent 结束后应消失。

## 后续迭代（非 MVP）

- settings.json 持久化配置
- TUI 状态 widget
- RPC 模式自动化验证脚本
