@openclawline/clawline-setup 0.2.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 +49 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +82 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/setup-skill.d.ts +17 -0
- package/dist/setup-skill.d.ts.map +1 -0
- package/dist/setup-skill.js +201 -0
- package/dist/setup-skill.js.map +1 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @openclawline/clawline-setup
|
|
2
|
+
|
|
3
|
+
> ClawLine 的 Bootstrapper Skill,让你通过对话完成 ClawLine 的安装和配置。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
openclaw plugins install @openclawline/clawline-setup
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
安装后,在任意能与 OpenClaw 对话的渠道(飞书、Telegram 等)说:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
帮我安装 ClawLine
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
OpenClaw 会自动:
|
|
20
|
+
1. 检查并安装 `@openclawline/clawline` Channel Plugin
|
|
21
|
+
2. 引导你从 ClawLine App 获取 UUID
|
|
22
|
+
|
|
23
|
+
## 绑定手机
|
|
24
|
+
|
|
25
|
+
告诉 OpenClaw 你的 UUID:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
ClawLine 的 UUID 是 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
随时可以更换 UUID 重新绑定,无需任何其他操作。
|
|
32
|
+
|
|
33
|
+
## 常用指令
|
|
34
|
+
|
|
35
|
+
| 说什么 | 效果 |
|
|
36
|
+
|--------|------|
|
|
37
|
+
| 帮我安装 ClawLine | 检查并安装 Channel Plugin |
|
|
38
|
+
| ClawLine 的 UUID 是 xxxx | 设置/更新连接 UUID 并重启网关 |
|
|
39
|
+
| ClawLine 的连接状态 | 查看当前配置和连接状态 |
|
|
40
|
+
| 断开 ClawLine | 清除配对信息 |
|
|
41
|
+
|
|
42
|
+
## 与 Channel Plugin 的关系
|
|
43
|
+
|
|
44
|
+
| 包 | 职责 |
|
|
45
|
+
|----|------|
|
|
46
|
+
| `@openclawline/clawline-setup`(本包)| 对话式安装引导,零依赖,极轻量 |
|
|
47
|
+
| `@openclawline/clawline` | 实际 Channel Plugin,维持 WebSocket 长连接、转发消息 |
|
|
48
|
+
|
|
49
|
+
本包负责"装好",Channel Plugin 负责"用"。
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ClawLineConfig {
|
|
2
|
+
serverUrl: string;
|
|
3
|
+
connectUuid?: string;
|
|
4
|
+
instanceId?: string;
|
|
5
|
+
instanceToken?: string;
|
|
6
|
+
instanceName?: string;
|
|
7
|
+
pairedAt?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadConfig(): ClawLineConfig;
|
|
10
|
+
export declare function saveConfig(patch: Partial<ClawLineConfig>): void;
|
|
11
|
+
export declare function clearConfig(): void;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,UAAU,IAAI,cAAc,CAe3C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAY/D;AAED,wBAAgB,WAAW,IAAI,IAAI,CAQlC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadConfig = loadConfig;
|
|
37
|
+
exports.saveConfig = saveConfig;
|
|
38
|
+
exports.clearConfig = clearConfig;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
// 与 @openclawline/clawline Channel Plugin 共享同一份配置文件路径,保证两者读写一致
|
|
43
|
+
const CONFIG_PATH = path.join(os.homedir(), '.openclaw', 'channels', 'clawline.json');
|
|
44
|
+
const DEFAULT_SERVER_URL = 'wss://ws.openclawline.com';
|
|
45
|
+
function loadConfig() {
|
|
46
|
+
try {
|
|
47
|
+
const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
48
|
+
const data = JSON.parse(raw);
|
|
49
|
+
return {
|
|
50
|
+
serverUrl: data.serverUrl ?? DEFAULT_SERVER_URL,
|
|
51
|
+
connectUuid: data.connectUuid,
|
|
52
|
+
instanceId: data.instanceId,
|
|
53
|
+
instanceToken: data.instanceToken,
|
|
54
|
+
instanceName: data.instanceName,
|
|
55
|
+
pairedAt: data.pairedAt,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return { serverUrl: DEFAULT_SERVER_URL };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function saveConfig(patch) {
|
|
63
|
+
const existing = loadConfig();
|
|
64
|
+
const merged = { ...existing, ...patch };
|
|
65
|
+
// 值为 undefined 的字段不写入 JSON
|
|
66
|
+
const cleaned = Object.fromEntries(Object.entries(merged).filter(([, v]) => v !== undefined));
|
|
67
|
+
const dir = path.dirname(CONFIG_PATH);
|
|
68
|
+
if (!fs.existsSync(dir)) {
|
|
69
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(cleaned, null, 2), 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
function clearConfig() {
|
|
74
|
+
saveConfig({
|
|
75
|
+
connectUuid: undefined,
|
|
76
|
+
instanceId: undefined,
|
|
77
|
+
instanceToken: undefined,
|
|
78
|
+
instanceName: undefined,
|
|
79
|
+
pairedAt: undefined,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,gCAeC;AAED,gCAYC;AAED,kCAQC;AAzDD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAEzB,+DAA+D;AAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAWtF,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;AAEvD,SAAgB,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QACxD,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,kBAAkB;YAC/C,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,KAA8B;IACvD,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;IACzC,2BAA2B;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAChC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAC7B,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3E,CAAC;AAED,SAAgB,WAAW;IACzB,UAAU,CAAC;QACT,WAAW,EAAE,SAAS;QACtB,UAAU,EAAE,SAAS;QACrB,aAAa,EAAE,SAAS;QACxB,YAAY,EAAE,SAAS;QACvB,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openclawline/clawline-setup
|
|
3
|
+
*
|
|
4
|
+
* ClawLine Bootstrapper Skill for OpenClaw.
|
|
5
|
+
* 这是一个极轻量的 Setup Skill,帮助用户通过对话完成 ClawLine 的安装和配置。
|
|
6
|
+
*
|
|
7
|
+
* 安装:
|
|
8
|
+
* openclaw plugins install @openclawline/clawline-setup
|
|
9
|
+
*
|
|
10
|
+
* 安装后,只需在任意聊天窗口对 OpenClaw 说:
|
|
11
|
+
* "帮我安装 ClawLine"
|
|
12
|
+
*
|
|
13
|
+
* @see https://github.com/qtx0213/clawline
|
|
14
|
+
*/
|
|
15
|
+
export { clawlineSetupSkills as default } from './setup-skill';
|
|
16
|
+
export { clawlineSetupSkills } from './setup-skill';
|
|
17
|
+
export type { SkillDefinition, SkillParameter } from './setup-skill';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,mBAAmB,IAAI,OAAO,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @openclawline/clawline-setup
|
|
4
|
+
*
|
|
5
|
+
* ClawLine Bootstrapper Skill for OpenClaw.
|
|
6
|
+
* 这是一个极轻量的 Setup Skill,帮助用户通过对话完成 ClawLine 的安装和配置。
|
|
7
|
+
*
|
|
8
|
+
* 安装:
|
|
9
|
+
* openclaw plugins install @openclawline/clawline-setup
|
|
10
|
+
*
|
|
11
|
+
* 安装后,只需在任意聊天窗口对 OpenClaw 说:
|
|
12
|
+
* "帮我安装 ClawLine"
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/qtx0213/clawline
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.clawlineSetupSkills = exports.default = void 0;
|
|
18
|
+
var setup_skill_1 = require("./setup-skill");
|
|
19
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return setup_skill_1.clawlineSetupSkills; } });
|
|
20
|
+
var setup_skill_2 = require("./setup-skill");
|
|
21
|
+
Object.defineProperty(exports, "clawlineSetupSkills", { enumerable: true, get: function () { return setup_skill_2.clawlineSetupSkills; } });
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAEH,6CAA+D;AAAtD,sGAAA,mBAAmB,OAAW;AACvC,6CAAoD;AAA3C,kHAAA,mBAAmB,OAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface SkillParameter {
|
|
2
|
+
type: 'string' | 'number' | 'boolean';
|
|
3
|
+
description: string;
|
|
4
|
+
enum?: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface SkillDefinition {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
parameters: {
|
|
10
|
+
type: 'object';
|
|
11
|
+
properties: Record<string, SkillParameter>;
|
|
12
|
+
required?: string[];
|
|
13
|
+
};
|
|
14
|
+
execute(params: Record<string, unknown>): Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
export declare const clawlineSetupSkills: SkillDefinition[];
|
|
17
|
+
//# sourceMappingURL=setup-skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-skill.d.ts","sourceRoot":"","sources":["../src/setup-skill.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAC3C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3D;AA4CD,eAAO,MAAM,mBAAmB,EAAE,eAAe,EAwMhD,CAAC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clawlineSetupSkills = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const config_1 = require("./config");
|
|
6
|
+
// ─── 工具函数 ──────────────────────────────────────────────────────────────────
|
|
7
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
|
+
/** 检查 @openclawline/clawline Channel Plugin 是否已安装 */
|
|
9
|
+
function isChannelPluginInstalled() {
|
|
10
|
+
const result = (0, child_process_1.spawnSync)('openclaw', ['plugins', 'list'], {
|
|
11
|
+
encoding: 'utf-8',
|
|
12
|
+
shell: true,
|
|
13
|
+
});
|
|
14
|
+
const output = (result.stdout ?? '') + (result.stderr ?? '');
|
|
15
|
+
return /clawline/i.test(output);
|
|
16
|
+
}
|
|
17
|
+
/** 安装 @openclawline/clawline Channel Plugin,返回 [成功, 消息] */
|
|
18
|
+
function installChannelPlugin() {
|
|
19
|
+
const result = (0, child_process_1.spawnSync)('openclaw', ['plugins', 'install', '@openclawline/clawline'], { encoding: 'utf-8', shell: true, timeout: 60000 });
|
|
20
|
+
if (result.status !== 0) {
|
|
21
|
+
const errMsg = ((result.stderr ?? '') + (result.stdout ?? '')).trim();
|
|
22
|
+
return [false, errMsg || '未知错误,请检查网络或 npm 权限'];
|
|
23
|
+
}
|
|
24
|
+
return [true, ''];
|
|
25
|
+
}
|
|
26
|
+
/** 重启 OpenClaw 网关,让 Channel Plugin 以新配置启动 */
|
|
27
|
+
function restartGateway() {
|
|
28
|
+
const result = (0, child_process_1.spawnSync)('openclaw', ['gateway', 'restart'], {
|
|
29
|
+
encoding: 'utf-8',
|
|
30
|
+
shell: true,
|
|
31
|
+
timeout: 15000,
|
|
32
|
+
});
|
|
33
|
+
if (result.status !== 0) {
|
|
34
|
+
return '(网关重启失败,请手动执行 `openclaw gateway restart`)';
|
|
35
|
+
}
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
// ─── Skill 定义集合 ─────────────────────────────────────────────────────────────
|
|
39
|
+
exports.clawlineSetupSkills = [
|
|
40
|
+
// ── 1. 安装 + 可选配 UUID ───────────────────────────────────────────────────
|
|
41
|
+
{
|
|
42
|
+
name: 'clawline_install',
|
|
43
|
+
description: '检查并安装 ClawLine Channel Plugin,使 OpenClaw 能连接到 ClawLine 手机 App。' +
|
|
44
|
+
'当用户说"帮我安装 ClawLine"、"帮我装好 ClawLine"、"安装 ClawLine 插件"等时调用。' +
|
|
45
|
+
'若用户在同一句话中已提供了 UUID(如"帮我安装 ClawLine,UUID 是 xxxx"),' +
|
|
46
|
+
'可同时传入 uuid 参数,安装完成后直接写入配置并重启网关;' +
|
|
47
|
+
'若未提供 UUID,安装完成后引导用户去 App 获取。',
|
|
48
|
+
parameters: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
uuid: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: '可选。用户提供的连接 UUID(从 ClawLine App 的"添加实例"页面获取)。',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: [],
|
|
57
|
+
},
|
|
58
|
+
async execute(params) {
|
|
59
|
+
// ── 1. 检查 / 安装 Plugin ─────────────────────────────────────────────
|
|
60
|
+
let installMsg;
|
|
61
|
+
if (isChannelPluginInstalled()) {
|
|
62
|
+
installMsg = '✅ ClawLine Channel Plugin 已安装。';
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const [ok, errMsg] = installChannelPlugin();
|
|
66
|
+
if (!ok) {
|
|
67
|
+
return (`安装 ClawLine Channel Plugin 失败:\n${errMsg}\n\n` +
|
|
68
|
+
`你也可以手动执行:\n openclaw plugins install @openclawline/clawline`);
|
|
69
|
+
}
|
|
70
|
+
installMsg = '✅ ClawLine Channel Plugin 安装成功。';
|
|
71
|
+
}
|
|
72
|
+
// ── 2. 处理 UUID ──────────────────────────────────────────────────────
|
|
73
|
+
const uuid = params['uuid']?.trim();
|
|
74
|
+
if (!uuid) {
|
|
75
|
+
return (`${installMsg}\n\n` +
|
|
76
|
+
`下一步需要绑定你的手机:\n\n` +
|
|
77
|
+
`1. 打开 ClawLine App\n` +
|
|
78
|
+
`2. 进入"添加实例"页面\n` +
|
|
79
|
+
`3. 给实例命名(如"我的电脑")\n` +
|
|
80
|
+
`4. 复制页面显示的 UUID\n\n` +
|
|
81
|
+
`复制后直接告诉我,例如:\n "ClawLine 的 UUID 是 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"`);
|
|
82
|
+
}
|
|
83
|
+
if (!UUID_PATTERN.test(uuid)) {
|
|
84
|
+
return `${installMsg}\n\n"${uuid}" 不是合法的 UUID 格式,请重新从 App 复制。`;
|
|
85
|
+
}
|
|
86
|
+
// ── 3. 写入配置并重启网关 ─────────────────────────────────────────────
|
|
87
|
+
const cfg = (0, config_1.loadConfig)();
|
|
88
|
+
const oldName = cfg.instanceName ?? cfg.instanceId;
|
|
89
|
+
(0, config_1.saveConfig)({
|
|
90
|
+
connectUuid: uuid,
|
|
91
|
+
serverUrl: cfg.serverUrl,
|
|
92
|
+
instanceId: undefined,
|
|
93
|
+
instanceToken: undefined,
|
|
94
|
+
instanceName: undefined,
|
|
95
|
+
pairedAt: undefined,
|
|
96
|
+
});
|
|
97
|
+
const restartNote = restartGateway();
|
|
98
|
+
const rebindNote = oldName ? `已断开与"${oldName}"的旧连接。\n` : '';
|
|
99
|
+
return (`${installMsg}\n${rebindNote}\n` +
|
|
100
|
+
`✅ UUID 已写入配置。\n` +
|
|
101
|
+
`${restartNote}\n` +
|
|
102
|
+
`网关重启后,ClawLine Channel Plugin 将自动向 App 发起配对请求。\n` +
|
|
103
|
+
`请在 App 的"实例管理"→ 待确认列表中点击确认即可完成绑定。`).replace(/\n{3,}/g, '\n\n');
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
// ── 2. 随时更新 UUID(对话中说出 UUID 时触发)──────────────────────────────
|
|
107
|
+
{
|
|
108
|
+
name: 'clawline_set_uuid',
|
|
109
|
+
description: '设置或更新 ClawLine 连接 UUID,并重启网关完成绑定。' +
|
|
110
|
+
'当用户说"ClawLine 的 UUID 是 xxxx"、"我的 UUID 是 xxxx"、' +
|
|
111
|
+
'"重新绑定 ClawLine,UUID:xxxx" 等时调用。',
|
|
112
|
+
parameters: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
uuid: {
|
|
116
|
+
type: 'string',
|
|
117
|
+
description: '从 ClawLine App"添加实例"页面复制的连接 UUID,格式为 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
required: ['uuid'],
|
|
121
|
+
},
|
|
122
|
+
async execute(params) {
|
|
123
|
+
const uuid = params['uuid'].trim();
|
|
124
|
+
if (!UUID_PATTERN.test(uuid)) {
|
|
125
|
+
return `"${uuid}" 不是合法的 UUID 格式。\n请重新从 App 复制,格式应为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`;
|
|
126
|
+
}
|
|
127
|
+
// 检查 Channel Plugin 是否已安装
|
|
128
|
+
if (!isChannelPluginInstalled()) {
|
|
129
|
+
return (`尚未安装 ClawLine Channel Plugin。\n` +
|
|
130
|
+
`请先说"帮我安装 ClawLine",安装完成后再提供 UUID。`);
|
|
131
|
+
}
|
|
132
|
+
const cfg = (0, config_1.loadConfig)();
|
|
133
|
+
const oldName = cfg.instanceName ?? cfg.instanceId;
|
|
134
|
+
(0, config_1.saveConfig)({
|
|
135
|
+
connectUuid: uuid,
|
|
136
|
+
serverUrl: cfg.serverUrl,
|
|
137
|
+
instanceId: undefined,
|
|
138
|
+
instanceToken: undefined,
|
|
139
|
+
instanceName: undefined,
|
|
140
|
+
pairedAt: undefined,
|
|
141
|
+
});
|
|
142
|
+
const restartNote = restartGateway();
|
|
143
|
+
const rebindNote = oldName ? `已断开与"${oldName}"的旧连接。\n` : '';
|
|
144
|
+
return (`${rebindNote}` +
|
|
145
|
+
`✅ UUID 已更新。\n` +
|
|
146
|
+
`${restartNote}\n` +
|
|
147
|
+
`网关重启后,请在 App 的"实例管理"→ 待确认列表中确认配对即可。`).replace(/\n{3,}/g, '\n\n');
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
// ── 3. 查询连接状态 ─────────────────────────────────────────────────────────
|
|
151
|
+
{
|
|
152
|
+
name: 'clawline_status',
|
|
153
|
+
description: '查询 ClawLine 连接状态,包括是否已安装 Plugin、是否已配对、实例名称等。',
|
|
154
|
+
parameters: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
properties: {},
|
|
157
|
+
required: [],
|
|
158
|
+
},
|
|
159
|
+
async execute(_params) {
|
|
160
|
+
const installed = isChannelPluginInstalled();
|
|
161
|
+
const cfg = (0, config_1.loadConfig)();
|
|
162
|
+
const lines = [
|
|
163
|
+
`ClawLine Channel Plugin:${installed ? '已安装 ✅' : '未安装 ❌'}`,
|
|
164
|
+
];
|
|
165
|
+
if (cfg.instanceId) {
|
|
166
|
+
const pairedAt = cfg.pairedAt
|
|
167
|
+
? new Date(cfg.pairedAt).toLocaleString('zh-CN')
|
|
168
|
+
: '未知';
|
|
169
|
+
lines.push(`连接状态:已配对 ✅`, `实例名称:${cfg.instanceName ?? '未知'}`, `实例 ID:${cfg.instanceId}`, `配对时间:${pairedAt}`, `服务地址:${cfg.serverUrl}`);
|
|
170
|
+
}
|
|
171
|
+
else if (cfg.connectUuid) {
|
|
172
|
+
lines.push(`连接状态:等待配对 ⏳`, `UUID:${cfg.connectUuid}`, `请在 App 的"实例管理"→ 待确认列表中确认配对。`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
lines.push(`连接状态:未配对 ❌`, `说"帮我安装 ClawLine"开始配置,或直接说"ClawLine 的 UUID 是 xxxx"。`);
|
|
176
|
+
}
|
|
177
|
+
return lines.join('\n');
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
// ── 4. 断开连接 ─────────────────────────────────────────────────────────────
|
|
181
|
+
{
|
|
182
|
+
name: 'clawline_disconnect',
|
|
183
|
+
description: '断开并清除 ClawLine 配对信息,通常在需要重新绑定其他设备时使用。',
|
|
184
|
+
parameters: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: {},
|
|
187
|
+
required: [],
|
|
188
|
+
},
|
|
189
|
+
async execute(_params) {
|
|
190
|
+
const cfg = (0, config_1.loadConfig)();
|
|
191
|
+
if (!cfg.instanceId && !cfg.connectUuid) {
|
|
192
|
+
return '当前没有 ClawLine 配对信息,无需断开。';
|
|
193
|
+
}
|
|
194
|
+
const name = cfg.instanceName ?? cfg.instanceId ?? '未知';
|
|
195
|
+
(0, config_1.clearConfig)();
|
|
196
|
+
return (`已断开与"${name}"的连接,配对信息已清除。\n` +
|
|
197
|
+
`如需重新绑定,直接说"ClawLine 的 UUID 是 xxxx"即可。`);
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
];
|
|
201
|
+
//# sourceMappingURL=setup-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-skill.js","sourceRoot":"","sources":["../src/setup-skill.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openclawline/clawline-setup",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "ClawLine Setup Skill for OpenClaw - bootstrapper that installs and configures the ClawLine Channel Plugin via conversation",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18.0.0"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": ["openclaw", "clawline", "skill", "setup", "install"],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/qtx0213/clawline.git",
|
|
24
|
+
"directory": "plugin-setup"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.0.0",
|
|
29
|
+
"typescript": "^5.4.0"
|
|
30
|
+
}
|
|
31
|
+
}
|