# 会话管理 + 命令模式 + 原始输出 实施计划

> **Status:** Ready for implementation

## Context

当前 Butler-Shell 只有自然语言模式，缺少以下能力：
1. 无法直接发送原始命令（每次都走 LLM 理解）
2. 无法获取命令的原始输入输出（只有 LLM 总结）
3. 无法管理会话生命周期（新建/清理）
4. LLM 上下文没有持久化，无法清理

## 需求拆解

### 1. `!` 前缀：原始命令模式
- `!ls -la` → 直接执行 `ls -la`，跳过 LLM 理解
- 返回原始文本输出，不做 LLM 总结
- 危险命令检查仍然生效

### 2. `/new` 命令：新建会话
- 创建新的 tmux session（递增编号）
- 清空 LLM 上下文（新会话 = 新上下文）
- 旧会话保留（可选后续清理）

### 3. `/clear` 命令：清理 LLM 上下文
- 不创建新 tmux session
- 清空当前会话的 LLM 对话历史
- Shell session 保持不变

### 4. 原始输入输出
- 所有交互都返回 `command`（实际执行的命令）和 `raw_output`（原始输出）
- LLM 总结放在 `reply` 字段，原始输出放在 `raw_output` 字段
- API 响应结构统一

## 关键设计：会话 = LLM 上下文 + Shell Session 绑定

```
Session = {
    session_id: "butler_user123_2",   # tmux session 名
    user_id: "user123",
    seq: 2,                             # 会话序号，/new 递增
    llm_context: [                       # LLM 对话历史
        {"role": "user", "content": ...},
        {"role": "assistant", "content": ...},
    ]
}
```

- `/new` → `seq += 1`，新建 tmux session，新建 LLM context
- `/clear` → 清空 `llm_context`，tmux session 不变

## 实施步骤

### Step 1: 添加 SessionContext 管理器

**新建文件:** `src/butler/session/context.py`

管理 LLM 对话历史和会话映射：

```python
class SessionContext:
    """会话上下文：LLM 历史 + Shell Session 绑定。"""
    session_id: str          # tmux session 名
    user_id: str
    seq: int                 # 会话序号
    llm_messages: list[dict] # LLM 对话历史

class ContextManager:
    """管理所有用户的会话上下文。"""
    _contexts: dict[str, SessionContext]  # user_id -> context

    def get_or_create(self, user_id, tmux) -> SessionContext
    def new_session(self, user_id, tmux) -> SessionContext
    def clear_context(self, user_id) -> SessionContext
    def add_message(self, user_id, role, content) -> None
```

### Step 2: 改造 Agent 支持多轮对话

**修改文件:** `src/butler/agent/__init__.py`

- `understand()` 接收 `llm_messages` 参数，传入历史上下文
- `summarize()` 将结果追加到 `llm_messages`
- LLM 调用时携带历史消息，实现上下文感知

### Step 3: 改造 _process_message 支持命令路由

**修改文件:** `src/butler/main.py`

消息路由逻辑：

```
输入 content
  ├─ 以 "!" 开头 → 原始命令模式（去掉 "!"，跳过 LLM，返回原始输出）
  ├─ 以 "/" 开头 → 系统命令
  │   ├─ "/new"   → 新建会话
  │   ├─ "/clear" → 清理 LLM 上下文
  │   └─ 其他     → 走 Skill 系统
  └─ 其他 → 自然语言模式（走 LLM 理解 + 总结）
```

响应结构统一：

```python
{
    "reply": "自然语言总结",       # LLM 总结或原始输出
    "mode": "nl|raw|command|error",
    "command": "ls -la",          # 实际执行的命令
    "raw_output": "原始输出...",    # 始终返回
    "session_id": "butler_user123_2"
}
```

### Step 4: 更新 Gateway 回复格式

**修改文件:** `src/butler/main.py` (GatewayManager)

Gateway 回复时用 `reply` 字段。对于原始模式，`reply = raw_output`。

### Step 5: 添加 `/help` 命令 + 使用说明文档

**修改文件:** `src/butler/main.py`

- `/help` 命令返回简要使用说明
- 列出所有可用命令：`!`、`/new`、`/clear`、`/help`

**新建文件:** `docs/usage.md`

- 完整使用说明文档
- 包含：命令列表、模式说明、配置方法

---

## 关键文件变更

| 文件 | 操作 | 说明 |
|------|------|------|
| `src/butler/session/context.py` | 新建 | SessionContext + ContextManager |
| `src/butler/agent/__init__.py` | 修改 | 支持多轮对话历史 |
| `src/butler/main.py` | 修改 | 命令路由 + 统一响应格式 + /help |
| `src/butler/session/wrapper.py` | 修改 | 支持按序号创建 session |
| `docs/usage.md` | 新建 | 使用说明文档 |

## 验证步骤

```bash
# 1. 运行测试
pytest tests/ -v

# 2. 原始命令模式
python scripts/mock_test.py "!ls -la"
# 期望：直接执行 ls -la，返回原始输出

# 3. 自然语言模式
python scripts/mock_test.py 查看当前目录
# 期望：LLM 生成命令，总结输出

# 4. 新建会话
python scripts/mock_test.py /new
# 期望：新建 tmux session，清空上下文

# 5. 清理上下文
python scripts/mock_test.py /clear
# 期望：清空 LLM 历史，shell session 不变

# 6. Telegram 测试
# 发送 "!df -h" → 原始输出
# 发送 "看下磁盘空间" → LLM 总结
# 发送 "/new" → 新建会话
# 发送 "/help" → 显示使用说明

# 7. 检查使用文档
cat docs/usage.md
```
