---
name: yanling-skill
description: 言灵 Skill，用于配置和操作 AgentConnect：通过浏览器设备码登录，安全保存凭证，绑定或修复本机 Edge Agent，查看企业机器及会话，打开远程控制台，浏览远程目录，同步企业 Skill，并在用户确认后发布本地 Skill。用户提到言灵 Skill、安装 AgentConnect、绑定机器、远程控制机器、查看机器或会话、同步或发布 Skill 时使用。
---

# 言灵 Skill

帮助用户用一次浏览器授权完成 AgentConnect 配置。后续直接接受自然语言指令，调用 REST API 查看机器和会话、打开网页控制台、同步或发布 Skill。

## 原则

- 直接开始探测和配置，不让用户敲命令或修改配置。
- 仅在浏览器登录/授权、覆盖本地文件、发布云端 Skill、允许安装用户级 Node.js 或购买会员时请求用户操作。
- 不在回复、命令文本或日志中输出 `access_token`、`refresh_token`、`enroll_token`。
- 优先使用系统钥匙串；系统没有可用的安全存储时，明确告知用户后才退化到权限 `0600` 的 `~/.agentconnect/token.json`。
- 远程终端和 Claude/Codex 会话操作通过 AgentConnect 网页控制台完成；REST API 只用于读取状态、会话、历史和目录等已提供能力。
- 发布或覆盖云端 Skill 前必须获得用户确认；云端覆盖本地文件前也必须确认。

## 常量

- Web：`https://yanlin-ai.cn/agentConnect`
- API：`https://yanlin-ai.cn/agentConnect/api`
- OAuth client：`agentconnect_skill`
- 本机 Agent：`~/.agentconnect/agent/`

## 1. 探测并安装本 Skill

探测操作系统、家目录、Node.js 版本、本机 Agent 状态以及当前 AI 客户端的 Skill 根目录。

按优先级识别 Skill 根目录：

1. 当前客户端或运行环境明确提供的 Skill 根目录。
2. Codex：`${CODEX_HOME:-$HOME/.codex}/skills`。
3. Claude：`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills`。
4. 通用 Agent：`$HOME/.agents/skills`。

始终安装到当前客户端实际使用的目录。其他候选目录只有在已经存在、或明确检测到对应客户端时才同步，禁止声称所有客户端都会读取 `~/.claude/skills`。

将当前下载到的完整 `SKILL.md` 写入每个目标目录的 `yanling-skill/SKILL.md`。已有不同版本时先备份为 `SKILL.md.bak-<timestamp>`；首次安装本 Skill 可直接写入，不需要再询问一次。

记录：

- `skill_roots`：实际写入的绝对路径列表。
- `agent_installed`：`~/.agentconnect/agent/agent.js` 是否存在。
- `agent_running`：优先检查对应 launchd/systemd/计划任务，再检查 `.agent.pid`，不要只用 `ps | grep`。

## 2. 登录

### 2.1 读取并验证已有凭证

将 token 集合保存为一个 JSON 对象：

```json
{"access_token":"…","refresh_token":"…","expires_at":"2026-07-27T00:00:00.000Z"}
```

- macOS：Keychain service=`agentconnect`，account=`default`；读取用 `security find-generic-password -s agentconnect -a default -w`，写入用 `security add-generic-password -U -s agentconnect -a default -w '<json>'`。
- Linux：优先 `secret-tool lookup service agentconnect account default` / `secret-tool store --label='AgentConnect' service agentconnect account default`。
- Windows：优先 Windows Credential Manager / PasswordVault；读取 PasswordVault 凭据后调用 `RetrievePassword()` 再取 `Password`。
- 无安全存储：征得用户同意后写 `~/.agentconnect/token.json` 并设置权限 `0600`。

用 access token 调用：

```http
GET /oauth/me
Authorization: Bearer <access_token>
```

- `200`：继续第 3 节。
- `401`：用 refresh token 按第 7 节刷新；刷新失败再发起设备码登录。

### 2.2 设备码登录

申请设备码：

```http
POST /oauth/device/code
Content-Type: application/json

{"client_id":"agentconnect_skill"}
```

立即用系统默认浏览器打开响应中的 `verification_uri_complete`：macOS 用 `open`，Linux 用 `xdg-open`，Windows 用 `Start-Process`。

告诉用户只需在浏览器登录并点“同意授权”。同时按响应中的 `interval` 自动轮询，不要求用户回来再说“好了”：

```http
POST /oauth/token
Content-Type: application/json

{
  "grant_type":"urn:ietf:params:oauth:grant-type:device_code",
  "device_code":"<device_code>",
  "client_id":"agentconnect_skill"
}
```

- `authorization_pending`：等待 `interval` 秒继续，禁止高频轮询。
- `200`：立即安全保存新 token，调用 `/oauth/me` 验证并自动继续。
- `access_denied`：停止并说明用户拒绝授权。
- `expired_token`：重新申请设备码。
- 当前工具不能持续等待时，保留 `device_code`；用户回来后立即继续兑换，不重新做已完成步骤。

## 3. 绑定或修复本机 Agent

### 3.1 获取会员和绑定信息

调用：

```http
GET /auth/me
Authorization: Bearer <access_token>
```

- `subscription` 非 `null` 且 `enterprise.enroll_token` 存在：继续。
- `subscription` 为 `null` 且 `expired_subscription` 非 `null`：打开 Web，引导续费。
- 两者都为 `null`：打开 Web，引导购买会员。

不要把 `enroll_token` 输出到对话或拼进可见命令。把它只保存在当前进程变量中。

### 3.2 验证是否已绑定当前账号

“Agent 正在运行”不等于“已绑定当前账号”。调用 `GET /machines`，结合本机 hostname、Agent 日志和机器 ID 判断本机是否出现在当前账号机器列表中。

- 已在当前账号且在线：不重装，继续第 4 节。
- Agent 在运行但未出现在当前账号：说明可能绑定旧账号，使用当前账号 token 重新执行安装器以更新服务环境。
- 已安装但离线：先重启对应系统服务并检查 `~/.agentconnect/agent/agent.log`；失败再重装。
- 未安装：继续安装。

### 3.3 安装

本机 Agent 要求 Node.js 18+。若未安装或版本过低，先向用户说明将从阿里云镜像下载 Node.js 24 LTS 到 `~/.agentconnect/node/`，不会使用 `sudo`、不会调用系统包管理器、不会覆盖系统 Node；获得同意后由 AI 直接继续运行 AgentConnect 安装器，不要让用户自己安装或复制命令。

安装器必须从 `https://mirrors.aliyun.com/nodejs-release/` 下载对应系统与 CPU 架构的官方 Node.js 二进制包，并使用同目录 `SHASUMS256.txt` 校验 SHA-256。校验失败立即停止，不运行未验证的文件。若系统已有 Node.js 18+，直接复用，不另行安装。

安装地址：

- macOS/Linux：`https://yanlin-ai.cn/agentConnect/install.sh`
- Windows：`https://yanlin-ai.cn/agentConnect/install.ps1`

先从安全存储读取 access token，在脚本内部调用 `/auth/me` 取得 `enroll_token`，再以子进程环境变量 `AGENTCONNECT_ENROLL_TOKEN` 启动安装器。命令文本和工具参数中不得出现 token 字面量；禁止把带 token 的完整安装命令展示给用户。

安装器会写入 `~/.agentconnect/agent/`、安装运行依赖并注册 launchd/systemd/Windows 计划任务。安装后最多等待 30 秒，并通过以下两项共同验证：

1. `GET /machines` 中本机为 `online`。
2. `~/.agentconnect/agent/agent.log` 没有“Hub 拒绝注册”。

若会员机器数已满或机器属于其他账号，原样解释 Hub 返回的错误，不循环重装。

## 4. 机器操作

每次请求先解析用户给出的机器名。使用 `display_name`、`hostname` 和 `machine_id` 匹配；有多个候选时让用户选择，禁止猜测。

### 列出机器

```http
GET /machines
Authorization: Bearer <access_token>
```

展示名称、系统、在线状态、最后在线时间和只读标记。不要显示完整机器 ID，除非用户要求或排障需要。

### 查看会话

```http
GET /machines/<machine_id>/sessions
Authorization: Bearer <access_token>
```

仅在线机器可实时获取。展示 provider、标题、更新时间和 session ID 的短前缀。

### 查看实时状态

```http
GET /machines/<machine_id>/live
Authorization: Bearer <access_token>
```

将 `asking`、`busy`、`active` 转成易懂中文。

### 查看历史

```http
GET /machines/<machine_id>/history?provider=<provider>&session_id=<session_id>
Authorization: Bearer <access_token>
```

默认摘要最近几轮；用户明确要求时再展示更多，避免泄露不相关会话内容。

### 浏览目录

```http
GET /machines/<machine_id>/browse?path=<urlencoded-path>
Authorization: Bearer <access_token>
```

必须对路径编码。只读取用户要求的目录，不递归扫描无关文件。

### 打开控制台

打开 `https://yanlin-ai.cn/agentConnect`，告诉用户选择目标机器后可开终端、续聊 Claude/Codex 会话或进入远程桌面。不要声称 REST API 能直接执行任意远程命令。

### 管理本机 Agent

优先使用系统服务：

- macOS：`launchctl kickstart -k gui/$(id -u)/com.agentconnect.edge.installed`
- Linux：`systemctl --user restart agentconnect-edge`；系统级安装则使用 `sudo systemctl restart agentconnect-edge`
- Windows：`schtasks /Run /TN AgentConnectEdge`

停止前说明守护服务可能自动拉起；若用户要求停止，先停止服务再终止残留进程。

## 5. 同步企业 Skill

拉取完整文件：

```http
GET /skills?client=skill&include_files=1
Authorization: Bearer <access_token>
```

对每个 Skill 校验：

- `name` 必须符合安全目录名，不允许 `/`、`\\`、`..` 或绝对路径。
- 每个 `files[].path` 必须是 Skill 目录内的相对路径；拒绝路径穿越。
- `SKILL.md` 用响应的 `sha256` 对比；附属文件使用各自 `sha256`（若接口返回）或内容摘要对比。

将 Skill 写入第 1 节识别出的所有 `skill_roots/<name>/`：

- 本地不存在：直接安装。
- 内容相同：跳过。
- 内容不同：让用户选择“备份后覆盖 / 保留本地 / 查看差异”。
- 覆盖时先备份整个本地目录，而不是只备份 `SKILL.md`。
- 文件模式统一解析为八进制；脚本仅在云端 mode 包含执行位时设为可执行。

完成后列出实际安装目录的绝对路径，并提醒部分客户端需要新开会话才能发现新 Skill。

## 6. 发布本地 Skill

用户指定 Skill 后：

1. 在已识别的 `skill_roots` 中定位，存在多个不同副本时先让用户选择。
2. 读取 YAML frontmatter，校验 `name` 与目录名、`description` 和 `SKILL.md`。
3. 排除 `.git`、缓存、构建产物、凭证文件、`.env*`、私钥、token 和超大二进制文件。
4. 检测疑似密钥；发现后停止并告知具体相对路径，不上传。
5. 展示名称、文件数、总大小和将覆盖的云端版本，明确请求确认。
6. 用户确认后调用：

```http
POST /skills/push
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "name":"<name>",
  "description":"<description>",
  "files":[{"path":"SKILL.md","content":"…","mode":"0644"}]
}
```

路径使用 `/` 分隔，mode 使用四位八进制字符串。失败时展示服务端错误；`401` 只刷新并重试一次。

## 7. Token 维护和退出

任意 API 返回 `401` 时，用安全存储中的 refresh token 调用：

```http
POST /oauth/token
Content-Type: application/json

{"grant_type":"refresh_token","refresh_token":"<refresh_token>","client_id":"agentconnect_skill"}
```

成功后原子替换整个凭证 JSON，并重试原请求一次。刷新失败则重新走设备码登录，不无限重试。

用户要求退出时删除本地凭证。不要默认卸载本机 Agent 或删除已安装 Skill；分别询问是否执行。

## 8. 完成后的用户提示

完成登录、绑定或修复后，只有同时满足以下条件才可告诉用户“配置完成”：

1. `/oauth/me` 已验证当前账号。
2. `GET /machines` 中已找到本机，且状态为 `online`。
3. 本轮用户要求的 Skill 安装或同步操作已经完成，或已明确说明跳过原因。

最终回复不得只说“已完成”。必须说明本机名称和在线状态，提供可点击的 Web 地址，并明确告诉用户可以换一台设备继续使用。使用以下话术，按实际机器名调整：

> 配置完成，`<机器名称>` 已在线。现在你可以在手机、电脑或其他任何能打开浏览器的终端访问：
>
> https://yanlin-ai.cn/agentConnect
>
> 登录当前账号并选择 `<机器名称>`，即可与这台机器上的 Claude/Codex Agent 对话，也可以打开终端或远程桌面。

如果本机尚未出现在机器列表、仍然离线，或用户跳过了绑定，不得使用上述成功话术。应准确说明未完成项和下一步；仍可提供 Web 地址，但要明确当前还不能通过它与本机 Agent 对话。

## API 速查

- `POST /oauth/device/code`：申请设备码。
- `POST /oauth/token`：设备码换 token 或刷新 token。
- `GET /oauth/me`：验证 token 和账号。
- `GET /auth/me`：账号、会员、`enroll_token`。
- `GET /machines`：机器列表。
- `GET /machines/<id>/sessions`：会话列表。
- `GET /machines/<id>/live`：实时会话状态。
- `GET /machines/<id>/history`：会话历史。
- `GET /machines/<id>/browse`：目录列表。
- `GET /skills?client=skill&include_files=1`：企业 Skill 全量文件。
- `POST /skills/push`：覆盖发布 Skill。
