# dws-chat — 安装 & 部署

> 主流程见 `../SKILL.md`；隔离原理见 `isolation.md`。本文件给一次性 / 跨机部署清单。

## 前置依赖

| 项 | 要求 | 检查 |
|----|------|------|
| `dws` CLI | **≥ v1.0.30** | `dws --version` |
| Python | ≥ 3.9 | `python3 --version` |
| Workspace 路径 | macOS/Linux: `~/.openclaw/workspace-<id>/`；Windows: `%USERPROFILE%\.openclaw\workspace` 或 `workspace-<id>` | `cd` 到该目录 |
| Python 命令 | macOS/Linux: `python3`；Windows: `py -3` 或 `python` | — |

**版本要求**：dws 必须 **≥ v1.0.30**。v1.0.29 对 `DWS_DISABLE_KEYCHAIN` 支持不完整、会导致 token 串库。

## 安装 dws

### Windows（PowerShell，在**本机**执行一次）

以**管理员或普通用户 PowerShell** 运行（不要用 `install.sh`，那是 macOS/Linux）：

```powershell
irm https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.ps1 | iex
```

安装器会下载 `dws-windows-amd64.zip`（或 arm64），放到 `%USERPROFILE%\.local\bin\dws.exe`，并尝试写入用户 PATH。

**验证**（新开一个 PowerShell 窗口）：

```powershell
dws --version
cd $env:USERPROFILE\.openclaw\workspace
py -3 skills\dws-chat\scripts\dws_agent.py auth status -f json
```

stderr 应含 `[dws-chat] platform=windows`、`DWS_CONFIG_DIR` 指向当前 workspace。

**可选：装到 workspace 内（便于 OpenClaw 沙盒或未配 PATH）**

```powershell
$env:DWS_INSTALL_DIR = "$env:USERPROFILE\.openclaw\workspace\.local\bin"
New-Item -ItemType Directory -Force -Path $env:DWS_INSTALL_DIR | Out-Null
irm https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.ps1 | iex
```

### macOS / Linux（非沙盒 exec）

```bash
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh | sh
source ~/.zshrc 2>/dev/null || true
dws --version
```

### OpenClaw 沙盒（推荐）

在沙盒 exec 内执行（cwd 为 workspace 根）：

```bash
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh | sh
export PATH="/workspace/.local/bin:/workspace/.dws/bin:$PATH"
dws --version
```

`dws_agent.py auth status` 的 stderr 含 `sandbox=yes` 即识别成功。

## 一次性清理（首次启用本机制 / 历史污染）

### macOS / Linux

```bash
rm -rf "$HOME/Library/Application Support/dws-cli"
security delete-generic-password -s dws-cli -a dek 2>/dev/null || true
rm -f {workspace}/.dws/{app.json,identity.json,.data,.data.lock}
rm -rf {workspace}/.dws_home
python3 skills/dws-chat/scripts/get_device_auth_link.py
```

### Windows（PowerShell）

```powershell
Remove-Item -Recurse -Force "$env:APPDATA\dws-cli" -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force "{workspace}\.dws_home" -ErrorAction SilentlyContinue
Remove-Item -Force "{workspace}\.dws\app.json","{workspace}\.dws\identity.json" -ErrorAction SilentlyContinue
py -3 skills\dws-chat\scripts\get_device_auth_link.py
```

## 部署到新 workspace / 新机器

```bash
# 1. 复制 skill 目录
cp -r {源 workspace}/skills/dws-chat {目标 workspace}/skills/

# 2. （仅旧机器/有过裸 dws 历史时）执行上面「一次性清理」

# 3. 设备授权（每 agent 各走一次）
cd {目标 workspace}
python3 skills/dws-chat/scripts/get_device_auth_link.py

# 4. 验证隔离
python3 skills/dws-chat/scripts/dws_agent.py auth status -f json
# stderr 必须打印 HOME/DWS_CONFIG_DIR 指向本 workspace
```

## 平台支持矩阵

| 平台 | 状态 | 说明 |
|------|------|------|
| **macOS** | ✅ 完全验证 | 绕开 Keychain + 绕开 `~/Library/...` 硬编码 |
| **OpenClaw 沙盒** | ✅ 推荐 | 容器内安装；凭证落挂载目录，天然 per-agent |
| **Linux** | ⚠️ 兼容未实测 | 注入 `HOME` 同样把 token 隔到 `{workspace}/.dws_home/.dws` |
| **Windows** | ✅ 支持 | `install.ps1` 安装 `dws.exe`；`dws_agent.py` 注入 `APPDATA`/`USERPROFILE` 到 `{workspace}\.dws_home` |

## 常见陷阱

1. **dws < v1.0.30** → token 仍串库；用 `install.sh` 升级
2. **直接装 `extensions/dingtalk-connector/skills/dws-cli/`** → 该 skill 通用裸调 dws，**不带** HOME 注入，会复现串库；新 agent 必须装本 `workspace-*/skills/dws-chat/` 版本
3. **跨机器迁移 token** → 不支持（OAuth 设计如此）；换机器请重新 `get_device_auth_link.py`
4. **沙盒内找不到 dws** → 在沙盒 exec 内跑 `install.sh`，勿让用户去宿主机 `~/.dws/bin` 授权
5. **Windows 报 dws 未安装** → 在本机 PowerShell 跑 `install.ps1`，**不要**用 `curl | sh`；OpenClaw agent 在 Windows 上通常**直接 exec 本机**，不需要 WSL/Docker

## 与 dws-cli 的关系

| Skill | 位置 | 用途 |
|-------|------|------|
| **dws-chat**（本 skill） | `{workspace}/skills/dws-chat/` | 群聊消息；带 per-agent 隔离 |
| `dws-cli` | `extensions/dingtalk-connector/skills/dws-cli/` | 全产品 dws；**不带**隔离，勿改其脚本 |

同一 agent 下若两者都调用 dws，应统一走本 workspace 的 `scripts/dws_agent.py`（或保证 cwd 为本 workspace）。**禁止**裸 `dws` 或 `~/.dws`。
