openclaw-xiaoyou 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -0
- package/config.example.json +35 -0
- package/demo-enterprise-server.ts +138 -0
- package/docs/Xiaoyou-SKILL.md +111 -0
- package/docs/communication-flow.md +639 -0
- package/docs/install-xiaoyou.sh +427 -0
- package/docs/publish-and-deploy.md +296 -0
- package/index.ts +70 -0
- package/openclaw.plugin.json +74 -0
- package/package.json +34 -0
- package/setup-entry.ts +18 -0
- package/src/channel.test.ts +140 -0
- package/src/channel.ts +218 -0
- package/src/enterprise-client.ts +190 -0
- package/src/onboarding.ts +76 -0
- package/src/types.ts +86 -0
- package/tsconfig.json +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# openclaw-xiaoyou
|
|
2
|
+
|
|
3
|
+
OpenClaw channel 插件 —— 通过持久 WebSocket 出站连接桥接企业内部服务。
|
|
4
|
+
|
|
5
|
+
## 架构
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌──────────────┐ WebSocket (出站) ┌──────────────────────────┐
|
|
9
|
+
│ │◀══════════════════════▶│ │
|
|
10
|
+
│ 企业 IM │ xiaoyou 插件 │ OpenClaw Gateway │
|
|
11
|
+
│ 服务端 │ (运行在 Gateway 内) │ (port 18789) │
|
|
12
|
+
│ │ │ ├─ xiaoyou plugin │
|
|
13
|
+
└──────────────┘ │ ├─ Agent / LLM │
|
|
14
|
+
▲ │ └─ Tools / Memory │
|
|
15
|
+
│ 用户消息 └──────────────────────────┘
|
|
16
|
+
▼
|
|
17
|
+
企业用户
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
插件安装在 OpenClaw 中,由 Gateway 管理生命周期。企业侧无需暴露公网端口。
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# 从 npm 安装
|
|
26
|
+
openclaw plugins install openclaw-xiaoyou
|
|
27
|
+
openclaw plugins enable openclaw-xiaoyou
|
|
28
|
+
|
|
29
|
+
# 或从本地路径安装
|
|
30
|
+
openclaw plugins install /path/to/openclaw-xiaoyou
|
|
31
|
+
openclaw plugins enable openclaw-xiaoyou
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 配置
|
|
35
|
+
|
|
36
|
+
配置写在 **OpenClaw 的配置文件**中,不是插件目录里的单独文件。
|
|
37
|
+
OpenClaw 启动时会自动加载配置并注入给插件。
|
|
38
|
+
|
|
39
|
+
**配置文件位置**:`~/.openclaw/config.json`
|
|
40
|
+
|
|
41
|
+
### 方式一:命令行交互式向导(推荐)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
openclaw channels add --channel xiaoyou
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
向导会依次提示你填写 `wsUrl`、`authToken` 等,自动写入配置文件。
|
|
48
|
+
|
|
49
|
+
### 方式二:手动编辑配置文件
|
|
50
|
+
|
|
51
|
+
打开 `~/.openclaw/config.json`,在 `channels` 下添加 `xiaoyou` 段:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"channels": {
|
|
56
|
+
"xiaoyou": {
|
|
57
|
+
"enabled": true,
|
|
58
|
+
"wsUrl": "wss://im.corp.example.com/ws",
|
|
59
|
+
"authToken": "your-enterprise-auth-token",
|
|
60
|
+
"dmSecurity": "open",
|
|
61
|
+
"allowFrom": [],
|
|
62
|
+
"reconnectIntervalMs": 3000,
|
|
63
|
+
"maxReconnectAttempts": 0,
|
|
64
|
+
"heartbeatIntervalMs": 30000,
|
|
65
|
+
"heartbeatTimeoutMs": 10000
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
> 插件目录下的 `config.example.json` 是配置模板,可以直接复制其中
|
|
72
|
+
> `channels.xiaoyou` 部分到你的 `~/.openclaw/config.json` 中。
|
|
73
|
+
|
|
74
|
+
### 配置项
|
|
75
|
+
|
|
76
|
+
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|
|
77
|
+
|--------|------|------|--------|------|
|
|
78
|
+
| `enabled` | boolean | 否 | false | 启用/禁用 |
|
|
79
|
+
| `wsUrl` | string | ✅ | — | 企业 WebSocket 服务地址 |
|
|
80
|
+
| `authToken` | string | ✅ | — | 连接企业服务的认证 Token |
|
|
81
|
+
| `dmSecurity` | string | 否 | open | 安全策略:`open` / `allowlist` |
|
|
82
|
+
| `allowFrom` | string[] | 否 | [] | 白名单用户 ID(`allowlist` 时生效) |
|
|
83
|
+
| `reconnectIntervalMs` | number | 否 | 3000 | 重连基础间隔(ms),指数退避 |
|
|
84
|
+
| `maxReconnectAttempts` | number | 否 | 0 | 最大重连次数,0 = 无限 |
|
|
85
|
+
| `heartbeatIntervalMs` | number | 否 | 30000 | 心跳间隔(ms) |
|
|
86
|
+
| `heartbeatTimeoutMs` | number | 否 | 10000 | 心跳超时(ms) |
|
|
87
|
+
|
|
88
|
+
### 多账号
|
|
89
|
+
|
|
90
|
+
同时连接多个企业服务:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"channels": {
|
|
95
|
+
"xiaoyou": {
|
|
96
|
+
"enabled": true,
|
|
97
|
+
"wsUrl": "wss://default.corp.com/ws",
|
|
98
|
+
"authToken": "default-token",
|
|
99
|
+
"accounts": {
|
|
100
|
+
"sales": {
|
|
101
|
+
"wsUrl": "wss://sales.corp.com/ws",
|
|
102
|
+
"authToken": "sales-token"
|
|
103
|
+
},
|
|
104
|
+
"support": {
|
|
105
|
+
"wsUrl": "wss://support.corp.com/ws",
|
|
106
|
+
"authToken": "support-token"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## CLI 命令
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# 查看连接状态
|
|
118
|
+
openclaw xiaoyou status
|
|
119
|
+
|
|
120
|
+
# 发送测试消息
|
|
121
|
+
openclaw xiaoyou test --to <conversationId> --text "Hello"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 本地开发测试
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
cd openclaw-xiaoyou
|
|
128
|
+
|
|
129
|
+
# 安装依赖
|
|
130
|
+
npm install
|
|
131
|
+
|
|
132
|
+
# 终端 1: 启动模拟企业服务
|
|
133
|
+
npm run demo:server
|
|
134
|
+
|
|
135
|
+
# 终端 2: 启动 OpenClaw Gateway(配置 wsUrl 指向 ws://127.0.0.1:9090)
|
|
136
|
+
openclaw gateway
|
|
137
|
+
|
|
138
|
+
# 在终端 1 中输入消息,观察 Agent 回复
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 文件结构
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
openclaw-xiaoyou/
|
|
145
|
+
├── package.json # openclaw.channel 元数据
|
|
146
|
+
├── openclaw.plugin.json # 插件 manifest + 配置 schema
|
|
147
|
+
├── index.ts # 插件入口 (register)
|
|
148
|
+
├── setup-entry.ts # 轻量 setup 入口
|
|
149
|
+
├── config.example.json # 配置模板(供用户参考复制)
|
|
150
|
+
├── demo-enterprise-server.ts # 企业服务端 Mock
|
|
151
|
+
├── docs/
|
|
152
|
+
│ └── communication-flow.md # 通信架构文档
|
|
153
|
+
└── src/
|
|
154
|
+
├── types.ts # 协议类型定义
|
|
155
|
+
├── enterprise-client.ts # 企业 WebSocket 客户端
|
|
156
|
+
├── channel.ts # ChannelPlugin 实现
|
|
157
|
+
├── channel.test.ts # 测试
|
|
158
|
+
└── onboarding.ts # 交互式配置向导
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_说明": "将此文件中的 channels.xiaoyou 部分复制到你的 OpenClaw 配置文件中",
|
|
3
|
+
"_配置文件位置": "~/.openclaw/config.json",
|
|
4
|
+
"_添加方式": "也可以通过命令 openclaw channels add --channel xiaoyou 交互式配置",
|
|
5
|
+
|
|
6
|
+
"channels": {
|
|
7
|
+
"xiaoyou": {
|
|
8
|
+
"enabled": true,
|
|
9
|
+
|
|
10
|
+
"_comment_wsUrl": "【必填】企业 WebSocket 服务地址",
|
|
11
|
+
"wsUrl": "wss://im.corp.example.com/ws",
|
|
12
|
+
|
|
13
|
+
"_comment_authToken": "【必填】连接企业服务的认证 Token",
|
|
14
|
+
"authToken": "your-enterprise-auth-token",
|
|
15
|
+
|
|
16
|
+
"_comment_dmSecurity": "DM 安全策略: open=允许所有人, allowlist=仅白名单",
|
|
17
|
+
"dmSecurity": "open",
|
|
18
|
+
|
|
19
|
+
"_comment_allowFrom": "白名单用户 ID 列表 (dmSecurity=allowlist 时生效)",
|
|
20
|
+
"allowFrom": [],
|
|
21
|
+
|
|
22
|
+
"_comment_reconnect": "重连基础间隔(ms),实际按 3s→6s→12s→...→60s 指数退避",
|
|
23
|
+
"reconnectIntervalMs": 3000,
|
|
24
|
+
|
|
25
|
+
"_comment_maxReconnect": "最大重连次数,0=无限重试",
|
|
26
|
+
"maxReconnectAttempts": 0,
|
|
27
|
+
|
|
28
|
+
"_comment_heartbeat": "心跳间隔(ms),插件定时向企业服务发 ping",
|
|
29
|
+
"heartbeatIntervalMs": 30000,
|
|
30
|
+
|
|
31
|
+
"_comment_heartbeatTimeout": "心跳超时(ms),超时未收到 pong 则断开重连",
|
|
32
|
+
"heartbeatTimeoutMs": 10000
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 企业服务端 Mock —— 模拟企业 IM 的 WebSocket 服务
|
|
3
|
+
*
|
|
4
|
+
* 启动:
|
|
5
|
+
* npx tsx demo-enterprise-server.ts
|
|
6
|
+
* npm run demo:server
|
|
7
|
+
*
|
|
8
|
+
* 它会:
|
|
9
|
+
* 1. 在 ws://127.0.0.1:9090 启动 WebSocket 服务
|
|
10
|
+
* 2. 接受 xiaoyou 插件的连接和认证
|
|
11
|
+
* 3. 提供交互式命令行,手动发送消息
|
|
12
|
+
* 4. 打印收到的 Agent 回复
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
16
|
+
import { createInterface } from "node:readline";
|
|
17
|
+
|
|
18
|
+
const PORT = 9090;
|
|
19
|
+
const EXPECTED_TOKEN = "demo-enterprise-token";
|
|
20
|
+
|
|
21
|
+
const wss = new WebSocketServer({ port: PORT });
|
|
22
|
+
let activeWs: WebSocket | null = null;
|
|
23
|
+
|
|
24
|
+
console.log(`\n╔══════════════════════════════════════════════════╗`);
|
|
25
|
+
console.log(`║ 企业 IM Mock Server ║`);
|
|
26
|
+
console.log(`║ 监听: ws://127.0.0.1:${PORT} ║`);
|
|
27
|
+
console.log(`║ 认证 Token: ${EXPECTED_TOKEN} ║`);
|
|
28
|
+
console.log(`╚══════════════════════════════════════════════════╝\n`);
|
|
29
|
+
console.log(`等待 xiaoyou 插件连接...\n`);
|
|
30
|
+
|
|
31
|
+
wss.on("connection", (ws, req) => {
|
|
32
|
+
console.log(`[server] 新连接: ${req.socket.remoteAddress}`);
|
|
33
|
+
activeWs = ws;
|
|
34
|
+
|
|
35
|
+
ws.on("message", (data) => {
|
|
36
|
+
const raw = data.toString();
|
|
37
|
+
let msg: any;
|
|
38
|
+
try { msg = JSON.parse(raw); } catch { console.log(`[server] 无效 JSON: ${raw.slice(0, 200)}`); return; }
|
|
39
|
+
|
|
40
|
+
switch (msg.type) {
|
|
41
|
+
case "auth": {
|
|
42
|
+
console.log(`[server] 收到认证请求, token=${msg.token?.slice(0, 16)}...`);
|
|
43
|
+
if (msg.token === EXPECTED_TOKEN) {
|
|
44
|
+
ws.send(JSON.stringify({ type: "auth_result", ok: true, sessionId: `sess-${Date.now()}` }));
|
|
45
|
+
console.log("[server] ✓ 认证成功\n");
|
|
46
|
+
console.log("────────────────────────────────────────────");
|
|
47
|
+
console.log(" 现在可以输入消息发送给 Agent:");
|
|
48
|
+
console.log(" 格式: <文本> (默认 conv=demo, user=test-user)");
|
|
49
|
+
console.log(" 格式: /conv <id> <文本> (指定 conversationId)");
|
|
50
|
+
console.log(" 格式: /user <id> <文本> (指定 senderId)");
|
|
51
|
+
console.log(" 格式: /quit (退出)");
|
|
52
|
+
console.log("────────────────────────────────────────────\n");
|
|
53
|
+
} else {
|
|
54
|
+
ws.send(JSON.stringify({ type: "auth_result", ok: false, error: "invalid token" }));
|
|
55
|
+
console.log("[server] ✗ 认证失败\n");
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case "ping": {
|
|
60
|
+
ws.send(JSON.stringify({ type: "pong", seq: msg.seq, ts: Date.now() }));
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case "reply": {
|
|
64
|
+
console.log(`\n${"═".repeat(50)}`);
|
|
65
|
+
console.log(` 🤖 Agent 回复`);
|
|
66
|
+
console.log(` 会话: ${msg.conversationId}`);
|
|
67
|
+
console.log(` 消息ID: ${msg.messageId}`);
|
|
68
|
+
console.log(` 内容: ${msg.text}`);
|
|
69
|
+
if (msg.mediaUrls?.length) console.log(` 媒体: ${JSON.stringify(msg.mediaUrls)}`);
|
|
70
|
+
console.log(` 时间: ${new Date(msg.timestamp).toLocaleString()}`);
|
|
71
|
+
console.log(`${"═".repeat(50)}\n`);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
default:
|
|
75
|
+
console.log(`[server] 未知消息: ${msg.type}`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
ws.on("close", (code, reason) => {
|
|
80
|
+
console.log(`[server] 连接关闭 (code=${code}, reason=${reason.toString()})`);
|
|
81
|
+
if (activeWs === ws) activeWs = null;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
ws.on("error", (err) => {
|
|
85
|
+
console.error(`[server] 错误: ${err.message}`);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// ─── 交互式命令行 ────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
92
|
+
|
|
93
|
+
rl.on("line", (line) => {
|
|
94
|
+
const input = line.trim();
|
|
95
|
+
if (!input) return;
|
|
96
|
+
|
|
97
|
+
if (input === "/quit") {
|
|
98
|
+
console.log("[server] 退出...");
|
|
99
|
+
wss.close();
|
|
100
|
+
rl.close();
|
|
101
|
+
process.exit(0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!activeWs || activeWs.readyState !== WebSocket.OPEN) {
|
|
105
|
+
console.log("[server] 无活跃连接,无法发送");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let conversationId = "demo";
|
|
110
|
+
let senderId = "test-user";
|
|
111
|
+
let senderName = "测试用户";
|
|
112
|
+
let text = input;
|
|
113
|
+
|
|
114
|
+
// /conv <id> <text>
|
|
115
|
+
if (input.startsWith("/conv ")) {
|
|
116
|
+
const parts = input.slice(6).split(" ");
|
|
117
|
+
conversationId = parts[0];
|
|
118
|
+
text = parts.slice(1).join(" ");
|
|
119
|
+
}
|
|
120
|
+
// /user <id> <text>
|
|
121
|
+
else if (input.startsWith("/user ")) {
|
|
122
|
+
const parts = input.slice(6).split(" ");
|
|
123
|
+
senderId = parts[0];
|
|
124
|
+
text = parts.slice(1).join(" ");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const msg = {
|
|
128
|
+
type: "message",
|
|
129
|
+
conversationId,
|
|
130
|
+
senderId,
|
|
131
|
+
senderName,
|
|
132
|
+
text,
|
|
133
|
+
metadata: { source: "enterprise-mock" },
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
activeWs.send(JSON.stringify(msg));
|
|
137
|
+
console.log(`[server] → 已发送: [${senderId}@${conversationId}] ${text}`);
|
|
138
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xiaoyou-install-router
|
|
3
|
+
description: Use when users want to install, upgrade, uninstall, configure, or troubleshoot Xiaoyou (小优) channel integration for OpenClaw. Xiaoyou bridges OpenClaw to enterprise services via persistent WebSocket.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 小优 Channel 安装入口
|
|
7
|
+
|
|
8
|
+
小优 channel 安装、升级、卸载统一使用远程脚本:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
不要把 OpenClaw 的底层安装命令拆散执行。除非远程脚本失败且需要排障,否则直接调用 `install-xiaoyou.sh`。
|
|
15
|
+
|
|
16
|
+
## 触发词
|
|
17
|
+
|
|
18
|
+
- "安装小优" / "小优安装"
|
|
19
|
+
- "小优接入" / "接入小优"
|
|
20
|
+
- "配置 xiaoyou" / "xiaoyou 配置"
|
|
21
|
+
- "升级小优" / "更新小优"
|
|
22
|
+
- "卸载小优" / "移除小优"
|
|
23
|
+
- "我想用小优" / "启用小优"
|
|
24
|
+
- "小优 channel" / "xiaoyou channel"
|
|
25
|
+
|
|
26
|
+
## 标准执行
|
|
27
|
+
|
|
28
|
+
优先直接通过 `curl | bash` 执行远程脚本:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s -- --ws-url wss://im.corp.example.com/ws --token <AccessToken>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 参数说明
|
|
35
|
+
|
|
36
|
+
| 参数 | 必填 | 说明 |
|
|
37
|
+
|------|------|------|
|
|
38
|
+
| `--ws-url <url>` | ✅ 首次安装 | 企业 WebSocket 服务地址 |
|
|
39
|
+
| `--token <token>` | ✅ 首次安装 | 企业服务认证 Token |
|
|
40
|
+
| `--version <ver>` | 否 | 指定 openclaw-xiaoyou 版本,默认 latest |
|
|
41
|
+
| `--check-only` | 否 | 只输出计划,不执行真实改动 |
|
|
42
|
+
| `uninstall` | 否 | 卸载小优 channel |
|
|
43
|
+
|
|
44
|
+
### 首次安装
|
|
45
|
+
|
|
46
|
+
用户必须提供 `--ws-url` 和 `--token`:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s -- --ws-url wss://im.corp.example.com/ws --token my-enterprise-token
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 升级
|
|
53
|
+
|
|
54
|
+
已安装后的升级可以不传参数,脚本会复用现有配置:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s --
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
如果升级时传入 `--ws-url` 或 `--token`,会覆盖现有配置。
|
|
61
|
+
|
|
62
|
+
### 指定版本
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s -- --version 1.0.2 --ws-url wss://im.corp.example.com/ws --token my-token
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 卸载
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s -- uninstall
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
卸载会删除 xiaoyou channel 配置、插件记录和扩展目录。
|
|
75
|
+
|
|
76
|
+
## 预检
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s -- --check-only
|
|
80
|
+
curl -fsSL https://aitest.haiersmarthomes.com/aiservice/claw/install-xiaoyou.sh | bash -s -- uninstall --check-only
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 失败处理
|
|
84
|
+
|
|
85
|
+
如果脚本执行失败,优先让用户提供完整 `[xiaoyou-install]` 日志。常见判断:
|
|
86
|
+
|
|
87
|
+
| 日志现象 | 处理 |
|
|
88
|
+
|----------|------|
|
|
89
|
+
| 缺少 `--ws-url` | 要求用户提供企业 WebSocket 服务地址 |
|
|
90
|
+
| 缺少 `--token` | 要求用户提供企业服务认证 Token |
|
|
91
|
+
| 未检测到 OpenClaw | 提示用户先安装并启动 OpenClaw |
|
|
92
|
+
| npm latest 查询失败 | 可让脚本继续幂等安装,或指定 `--version` |
|
|
93
|
+
| wsUrl 格式不合法 | 地址必须以 `ws://` 或 `wss://` 开头 |
|
|
94
|
+
|
|
95
|
+
## 脚本做了什么
|
|
96
|
+
|
|
97
|
+
1. 检测 OpenClaw 是否已安装并运行
|
|
98
|
+
2. 安装/升级 `openclaw-xiaoyou` 插件(`openclaw plugins install openclaw-xiaoyou@latest`)
|
|
99
|
+
3. 写入 channel 配置到 `~/.openclaw/openclaw.json`:
|
|
100
|
+
- `channels.xiaoyou.enabled = true`
|
|
101
|
+
- `channels.xiaoyou.wsUrl = <用户提供的地址>`
|
|
102
|
+
- `channels.xiaoyou.authToken = <用户提供的 token>`
|
|
103
|
+
- `channels.xiaoyou.dmSecurity = open`
|
|
104
|
+
4. 检查插件状态和 gateway 运行状态
|
|
105
|
+
|
|
106
|
+
## 完成定义
|
|
107
|
+
|
|
108
|
+
- 脚本退出码为 0。
|
|
109
|
+
- 日志显示安装、升级或卸载流程完成。
|
|
110
|
+
- 安装场景下,`openclaw xiaoyou status` 显示 connected。
|
|
111
|
+
- 企业服务端能收到来自 xiaoyou 插件的 WebSocket 连接。
|