npm package: @starops/starops-chat
Description: Chat with Alibaba Cloud digital employees (数字员工) via CMS SDK
Latest version: 0.1.4

# @starops/starops-chat

通过阿里云 CMS SDK 与数字员工（Digital Employee）对话的 CLI 工具与 Node.js 库。

支持 SSE 流式输出、多轮对话、线程管理、工具调用展示等功能，可作为 npm 包直接通过 `npx @starops/starops-chat` 使用，也可作为 OpenClaw Skill 集成。

## 安装

```bash
# 全局安装
npm install -g @starops/starops-chat

# 或直接通过 npx 运行（无需安装）
npx @starops/starops-chat --message "你好"
```

## 环境变量

### 必需

| 变量名 | 说明 | 示例 |
|--------|------|------|
| `STAROPS_AGENT_ACCESS_KEY_ID` | 阿里云 AccessKey ID | `LT...` |
| `STAROPS_AGENT_ACCESS_KEY_SECRET` | 阿里云 AccessKey Secret | `xP...` |
| `STAROPS_AGENT_ENDPOINT` | CMS API 端点 | `cms.cn-hongkong.aliyuncs.com` |
| `STAROPS_AGENT_EMPLOYEE` | 数字员工名称 | `apsara-ops` |
| `STAROPS_AGENT_WORKSPACE` | 工作空间 ID | `default-cms-xxx-cn-hongkong` |

### 可选

| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| `STAROPS_AGENT_REGION` | 地域 | `cn-hongkong` |
| `STAROPS_AGENT_DEBUG` | 调试日志（`1`/`true`/`yes`） | 关闭 |

## CLI 使用

### 基本对话

```bash
npx @starops/starops-chat --message "查一下最近有什么告警"
```

### 指定数字员工

```bash
npx @starops/starops-chat --employee other-worker --message "你好"
```

### 指定工作空间

```bash
npx @starops/starops-chat --workspace "my-workspace-id" --message "检查ECS实例"
```

### JSON 输出

```bash
npx @starops/starops-chat --message "检查ECS实例" --json
```

### 续接对话

```bash
npx @starops/starops-chat --thread-id "thread-xxx" --message "继续上面的问题"
```

### 传递 UserInputParams

支持 `pkg/types/inputs.go` 中 `UserInputParams` 的所有字段：

```bash
npx @starops/starops-chat --message "查询日志" \
  --workspace "my-workspace" \
  --region "cn-hangzhou" \
  --project "my-project" \
  --logstore "my-logstore" \
  --metricstore "my-metricstore" \
  --language "zh" \
  --timezone "Asia/Shanghai" \
  --user-context '[ {"type":"metadata","data":{"fromTime":1700000000,"toTime":1700003600}} ]'
```

### 指定 Skill 形态

通过 `--skill` 可以切换数字员工的能力形态：

| `--skill` 值 | 说明 |
|---|---|
| （不填） | 默认：云监控 2.0 通用数据查询 + 根因定位 |
| `sql_generation` | SLS SQL 生成形态，适合生成日志查询语句 |
| `sop` | SLS SOP 形态，适合按运维手册逐步排查 |

```bash
# SLS SQL 生成形态
npx @starops/starops-chat --skill sql_generation \
  --project "my-project" --logstore "my-logstore" \
  --message "查询最近1小时的错误日志"

# SLS SOP 形态
npx @starops/starops-chat --skill sop \
  --message "服务响应变慢，帮我按 SOP 排查"
```

### 列出对话线程

```bash
npx @starops/starops-chat list-threads
npx @starops/starops-chat list-threads --json
```

### 查看线程历史

```bash
npx @starops/starops-chat get-history --thread-id "thread-xxx"
npx @starops/starops-chat get-history --thread-id "thread-xxx" --json
```

### 原始 SSE 事件输出

```bash
npx @starops/starops-chat --message "你好" --raw
```

### 断线重连

SSE 流式连接在运行 5-10 分钟后可能会自然断开。断开时 CLI 会输出重连提示，你可以使用 `reconnect` 命令恢复：

```bash
# 断开后，使用之前输出的 thread-id 重连
npx @starops/starops-chat reconnect --thread-id "thread-xxx"

# 也支持 --json 和 --raw 输出
npx @starops/starops-chat reconnect --thread-id "thread-xxx" --json
npx @starops/starops-chat reconnect --thread-id "thread-xxx" --raw
```

> 注意：重连后服务端会重放该线程的历史事件，可能包含之前已收到的内容。

## 作为 Node.js 库使用

```typescript
import { AgentClient, loadConfigFromEnv, validateConfig } from '@starops/starops-chat';

const config = loadConfigFromEnv();
validateConfig(config);

const client = new AgentClient(config);

// 创建线程
const threadId = await client.createThread();

// 流式对话
for await (const event of client.chat(threadId, '查一下最近告警')) {
  if (event.error) throw event.error;
  // 处理 event.messages
}

// 一次性获取完整回复
const { text, events } = await client.chatAll(threadId, '服务器状态');
console.log(text);

// 列出线程
const threads = await client.listThreads();

// 获取历史
const history = await client.getThreadHistory(threadId);

// 断线重连（SSE 流断开后恢复）
for await (const event of client.reconnect(threadId)) {
  if (event.error) throw event.error;
  // 处理 event.messages
}
```

### 传递 UserInputParams

```typescript
const params = {
  workspace: 'my-workspace',
  region: 'cn-hangzhou',
  project: 'my-project',
  logstore: 'my-logstore',
  language: 'zh',
  timeZone: 'Asia/Shanghai',
  userContext: JSON.stringify([
    { type: 'metadata', data: { fromTime: 1700000000, toTime: 1700003600 } }
  ]),
  // 可选：'sql_generation' | 'sop' | 不填（默认云监控通用）
  skill: 'sql_generation',
};

for await (const event of client.chat(threadId, '查询日志', params)) {
  // ...
}
```

## SSE 事件处理

每个 `ChatEvent` 包含 `messages` 数组，每个 `MessageItem` 对应 SSE 协议中的一条消息：

| 字段 | 说明 |
|------|------|
| `contents` | 文本内容（text/spin_text/image） |
| `tools` | 工具调用（start/success/fail 状态） |
| `agents` | 子 Agent 调用 |
| `events` | 系统事件（thinking/error/task_finished/interactive） |
| `artifacts` | 最终结果产物（A2A 协议） |

使用 `convertChatEventToMarkdownEvents()` 可将原始事件转为友好的 Markdown 输出事件。

## 项目结构

```
@starops/starops-chat/
├── package.json        # npm 包定义
├── tsconfig.json       # TypeScript 配置
├── SKILL.md            # OpenClaw Skill 定义
├── README.md           # 本文件
└── src/
    ├── index.ts        # 库入口
    ├── cli.ts          # CLI 入口（bin: @starops/starops-chat）
    ├── client.ts       # CMS SDK 封装（AgentClient）
    ├── types.ts        # 类型定义
    ├── printer.ts      # 事件格式化输出
    └── config.ts       # 配置加载
```

## OpenClaw 集成

作为 OpenClaw Skill 使用时，在 `~/.openclaw/openclaw.json` 中配置：

```json5
{
  "skills": {
    "entries": {
      "@starops/starops-chat": {
        "env": {
          "STAROPS_AGENT_ACCESS_KEY_ID": "your-key-id",
          "STAROPS_AGENT_ACCESS_KEY_SECRET": "your-key-secret",
          "STAROPS_AGENT_ENDPOINT": "cms.cn-hongkong.aliyuncs.com",
          "STAROPS_AGENT_EMPLOYEE": "apsara-ops",
          "STAROPS_AGENT_WORKSPACE": "your-workspace-id"
        }
      }
    }
  }
}
```

Skill 内部通过 `npx @starops/starops-chat` 调用，无需额外安装 Python 或管理虚拟环境。

## 开发

```bash
cd @starops/starops-chat
npm install
npm run build

# 直接运行（开发模式）
npx ts-node src/cli.ts --message "你好"

# 调试模式
STAROPS_AGENT_DEBUG=1 npx ts-node src/cli.ts --message "你好"
```

## 发布到 npm

> 发布前请确保已通过 `npm login` 登录 npm 账号。

```bash
cd @starops/starops-chat

# 发布（会自动先执行 build）
npm run release
```

发布流程说明：
1. `npm run release` 触发 `prepublishOnly` 钩子，自动执行 `npm run build` 编译 TypeScript。
2. 编译产物（`dist/`）以及 `README.md` 会被打包发布，`src/` 源码**不会**被发布。
3. 发布内容由 `package.json` 中的 `files` 字段控制。

升级版本号后再发布：

```bash
# 升级补丁版本 1.0.0 -> 1.0.1
npm version patch

# 或升级次版本 1.0.0 -> 1.1.0
npm version minor

# 再发布
npm run release
```

## License

Apache-2.0