@tencent-weixin/openclaw-weixin-cli 2.0.1 → 2.1.2
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 +12 -47
- package/cli.mjs +84 -10
- package/lib/compat.mjs +1 -3
- package/lib/version-check.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,10 +19,10 @@ npx -y @tencent-weixin/openclaw-weixin-cli install
|
|
|
19
19
|
|
|
20
20
|
## 兼容矩阵
|
|
21
21
|
|
|
22
|
-
| openclaw-weixin | 支持的 OpenClaw
|
|
23
|
-
|
|
24
|
-
| 1.0.x | >=2026.3.0 <2026.3.22 | `
|
|
25
|
-
|
|
|
22
|
+
| openclaw-weixin | 支持的 OpenClaw | dist-tag | 说明 |
|
|
23
|
+
|-----------------|-----------------------|---------------------------------------|----------------------|
|
|
24
|
+
| 1.0.x | >=2026.3.0 <2026.3.22 | `compat-host-gte2026.3.0-lt2026.3.22` | 兼容轨道 |
|
|
25
|
+
| v2 主线 | >=2026.3.22 | `latest` | 当前推荐 |
|
|
26
26
|
|
|
27
27
|
> 从 2.0.0 开始,插件采用独立 semver 版本号,不再对齐宿主 OpenClaw 版本号。
|
|
28
28
|
|
|
@@ -34,11 +34,11 @@ npx -y @tencent-weixin/openclaw-weixin-cli install
|
|
|
34
34
|
# 查看当前 OpenClaw 版本
|
|
35
35
|
openclaw --version
|
|
36
36
|
|
|
37
|
-
#
|
|
37
|
+
# 当前推荐主线 (>=2026.3.22)
|
|
38
38
|
openclaw plugins install @tencent/openclaw-weixin@latest
|
|
39
39
|
|
|
40
|
-
#
|
|
41
|
-
openclaw plugins install @tencent/openclaw-weixin@
|
|
40
|
+
# 兼容轨道 (<2026.3.22)
|
|
41
|
+
openclaw plugins install @tencent/openclaw-weixin@compat-host-gte2026.3.0-lt2026.3.22
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
## 运行时版本校验
|
|
@@ -49,7 +49,7 @@ openclaw plugins install @tencent/openclaw-weixin@legacy
|
|
|
49
49
|
[openclaw-weixin] 宿主版本不兼容!
|
|
50
50
|
当前 OpenClaw 版本: 2026.3.10
|
|
51
51
|
当前插件支持范围: >=2026.3.22
|
|
52
|
-
请安装 openclaw-weixin@
|
|
52
|
+
请安装 openclaw-weixin@compat-host-gte2026.3.0-lt2026.3.22
|
|
53
53
|
或运行: npx @tencent-weixin/openclaw-weixin-cli install (自动选择兼容版本)
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -68,16 +68,6 @@ openclaw --version
|
|
|
68
68
|
npx -y @tencent-weixin/openclaw-weixin-cli install
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
### 如何安装 legacy 线
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
# 方式一:统一安装器(自动判断)
|
|
75
|
-
npx -y @tencent-weixin/openclaw-weixin-cli install
|
|
76
|
-
|
|
77
|
-
# 方式二:手动指定 dist-tag
|
|
78
|
-
openclaw plugins install @tencent/openclaw-weixin@legacy
|
|
79
|
-
```
|
|
80
|
-
|
|
81
71
|
### 如何查看当前 openclaw 版本
|
|
82
72
|
|
|
83
73
|
```bash
|
|
@@ -86,34 +76,9 @@ openclaw --version
|
|
|
86
76
|
|
|
87
77
|
## 发布策略
|
|
88
78
|
|
|
89
|
-
###
|
|
90
|
-
|
|
91
|
-
| dist-tag | 对应版本线 | 说明 |
|
|
92
|
-
|----------|-----------|------|
|
|
93
|
-
| `latest` | 2.x | 新宿主线,`npm install` / `openclaw plugins install` 默认安装 |
|
|
94
|
-
| `legacy` | 1.x | 旧宿主维护线,需显式指定 `@legacy` |
|
|
95
|
-
|
|
96
|
-
### 发布命令
|
|
79
|
+
### 本仓库(CLI installer)与插件仓库的关系
|
|
97
80
|
|
|
98
|
-
|
|
99
|
-
# 发布新宿主线 (2.x)
|
|
100
|
-
npm run publish:external:latest -- patch
|
|
101
|
-
npm run publish:internal:latest -- patch
|
|
102
|
-
|
|
103
|
-
# 发布旧宿主维护线 (1.x)
|
|
104
|
-
npm run publish:external:legacy -- patch
|
|
105
|
-
npm run publish:internal:legacy -- patch
|
|
106
|
-
|
|
107
|
-
# dry run 预检
|
|
108
|
-
npm run publish:external:latest -- patch --dry-run
|
|
109
|
-
```
|
|
81
|
+
本仓库发布的是 **CLI 安装器**(`openclaw-weixin-cli`),不是插件本身(`openclaw-weixin`)。
|
|
110
82
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
# 安装开发依赖
|
|
115
|
-
npm install
|
|
116
|
-
|
|
117
|
-
# 本地测试 install 命令
|
|
118
|
-
node cli.mjs install
|
|
119
|
-
```
|
|
83
|
+
- **插件仓库**:openclaw-weixin,通过各分支发布到不同的 npm dist-tag
|
|
84
|
+
- **本仓库**:CLI 安装器,根据 `COMPAT_MATRIX` 自动选择正确的插件 dist-tag 来安装
|
package/cli.mjs
CHANGED
|
@@ -6,12 +6,22 @@ import path from "node:path";
|
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import {
|
|
8
8
|
COMPAT_MATRIX,
|
|
9
|
+
compareVersions,
|
|
9
10
|
findCompatEntry,
|
|
10
11
|
formatRange,
|
|
11
12
|
} from "./lib/compat.mjs";
|
|
12
13
|
|
|
13
14
|
const PLUGIN_SPEC = "@tencent-weixin/openclaw-weixin";
|
|
14
15
|
const CHANNEL_ID = "openclaw-weixin";
|
|
16
|
+
/** Only OpenClaw 2026.3.22–2026.3.23 need node_modules/openclaw symlink for jiti. */
|
|
17
|
+
const SYMLINK_OPENCLAW_MIN = "2026.3.22";
|
|
18
|
+
const SYMLINK_OPENCLAW_MAX = "2026.3.23";
|
|
19
|
+
|
|
20
|
+
const LEGACY_TAG_ALIASES = {
|
|
21
|
+
legacy: "compat-host-gte2026.3.0-lt2026.3.22",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const COMPAT_MATRIX_DIST_TAG_PAD = Math.max(...COMPAT_MATRIX.map((e) => e.distTag.length));
|
|
15
25
|
|
|
16
26
|
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
17
27
|
|
|
@@ -62,7 +72,9 @@ function selectPluginTag(openclawVersion) {
|
|
|
62
72
|
error(`当前 OpenClaw 版本 ${openclawVersion} 不在任何已知兼容范围内`);
|
|
63
73
|
console.log("\n 已知兼容矩阵:");
|
|
64
74
|
for (const e of COMPAT_MATRIX) {
|
|
65
|
-
console.log(
|
|
75
|
+
console.log(
|
|
76
|
+
` ${e.distTag.padEnd(COMPAT_MATRIX_DIST_TAG_PAD)} OpenClaw ${formatRange(e.openclawRange)}`,
|
|
77
|
+
);
|
|
66
78
|
}
|
|
67
79
|
console.log();
|
|
68
80
|
return null;
|
|
@@ -110,7 +122,23 @@ function resolvePluginExtDir() {
|
|
|
110
122
|
* openclaw package root. This lets jiti resolve openclaw/plugin-sdk/*
|
|
111
123
|
* without openclaw being a runtime dependency.
|
|
112
124
|
*/
|
|
113
|
-
function
|
|
125
|
+
function hostVersionNeedsOpenclawSymlink(hostVersion) {
|
|
126
|
+
if (!hostVersion) return false;
|
|
127
|
+
const geMin = compareVersions(hostVersion, SYMLINK_OPENCLAW_MIN);
|
|
128
|
+
const leMax = compareVersions(hostVersion, SYMLINK_OPENCLAW_MAX);
|
|
129
|
+
return (
|
|
130
|
+
!Number.isNaN(geMin) &&
|
|
131
|
+
!Number.isNaN(leMax) &&
|
|
132
|
+
geMin >= 0 &&
|
|
133
|
+
leMax <= 0
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function ensureOpenclawSymlink(hostVersion) {
|
|
138
|
+
if (!hostVersionNeedsOpenclawSymlink(hostVersion)) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
114
142
|
const hostRoot = resolveHostOpenclawRoot();
|
|
115
143
|
if (!hostRoot) {
|
|
116
144
|
error("无法定位宿主 openclaw 包根目录,跳过 symlink 创建");
|
|
@@ -130,7 +158,6 @@ function ensureOpenclawSymlink() {
|
|
|
130
158
|
try {
|
|
131
159
|
const existing = fs.readlinkSync(linkPath);
|
|
132
160
|
if (fs.realpathSync(existing) === fs.realpathSync(hostRoot)) {
|
|
133
|
-
log("openclaw symlink 已存在且正确");
|
|
134
161
|
return;
|
|
135
162
|
}
|
|
136
163
|
// Wrong target — remove and recreate
|
|
@@ -144,6 +171,30 @@ function ensureOpenclawSymlink() {
|
|
|
144
171
|
log(`已创建 symlink: node_modules/openclaw → ${hostRoot}`);
|
|
145
172
|
}
|
|
146
173
|
|
|
174
|
+
// ── installed plugin detection ───────────────────────────────────────────────
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Read the openclaw config and return the dist-tag that was used to install
|
|
178
|
+
* the plugin. OpenClaw stores `plugins.installs.<id>.spec` as the raw
|
|
179
|
+
* install spec (e.g. "@tencent/openclaw-weixin@latest"). We extract the
|
|
180
|
+
* trailing tag/version after the last "@".
|
|
181
|
+
* Returns the tag string, or null if not installed / unreadable.
|
|
182
|
+
*/
|
|
183
|
+
function getInstalledPluginTag() {
|
|
184
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR || path.join(os.homedir(), ".openclaw");
|
|
185
|
+
const configPath = path.join(stateDir, "openclaw.json");
|
|
186
|
+
try {
|
|
187
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
188
|
+
const spec = config?.plugins?.installs?.[CHANNEL_ID]?.spec;
|
|
189
|
+
if (!spec) return null;
|
|
190
|
+
const atIdx = spec.lastIndexOf("@");
|
|
191
|
+
const raw = atIdx > 0 ? spec.slice(atIdx + 1) : "latest";
|
|
192
|
+
return LEGACY_TAG_ALIASES[raw] || raw;
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
147
198
|
// ── commands ─────────────────────────────────────────────────────────────────
|
|
148
199
|
|
|
149
200
|
function install() {
|
|
@@ -170,9 +221,30 @@ function install() {
|
|
|
170
221
|
}
|
|
171
222
|
|
|
172
223
|
const pluginInstallSpec = `${PLUGIN_SPEC}@${compat.distTag}`;
|
|
173
|
-
log(
|
|
224
|
+
log(`匹配 dist-tag: ${compat.distTag}`);
|
|
225
|
+
|
|
226
|
+
// 3. If already installed with a different dist-tag, uninstall first
|
|
227
|
+
// so the fresh install picks up the correct dist-tag.
|
|
228
|
+
// If the installed spec is a pinned version number, skip entirely.
|
|
229
|
+
const installedTag = getInstalledPluginTag();
|
|
230
|
+
if (installedTag !== null && /^\d+\.\d+\.\d+/.test(installedTag)) {
|
|
231
|
+
log(`本地已安装插件为固定版本 ${installedTag},跳过升级`);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (installedTag !== null && installedTag !== compat.distTag) {
|
|
235
|
+
log(`本地已安装插件为 @${installedTag},与目标 @${compat.distTag} 不一致,先卸载旧版本...`);
|
|
236
|
+
try {
|
|
237
|
+
run(`echo y | openclaw plugins uninstall "${CHANNEL_ID}"`);
|
|
238
|
+
log("旧版本已卸载");
|
|
239
|
+
} catch (uninstallErr) {
|
|
240
|
+
error("旧版本卸载失败,请手动执行:");
|
|
241
|
+
if (uninstallErr.stderr) console.error(uninstallErr.stderr);
|
|
242
|
+
console.log(` openclaw plugins uninstall "${CHANNEL_ID}"`);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
174
246
|
|
|
175
|
-
//
|
|
247
|
+
// 4. Install plugin via openclaw
|
|
176
248
|
log(`正在安装插件 ${pluginInstallSpec}...`);
|
|
177
249
|
try {
|
|
178
250
|
const installOut = run(`openclaw plugins install "${pluginInstallSpec}"`);
|
|
@@ -197,11 +269,11 @@ function install() {
|
|
|
197
269
|
}
|
|
198
270
|
}
|
|
199
271
|
|
|
200
|
-
//
|
|
272
|
+
// 5. Symlink host openclaw into plugin's node_modules (2026.3.22–2026.3.23 only)
|
|
201
273
|
// so jiti can resolve openclaw/plugin-sdk/* without a runtime dependency.
|
|
202
|
-
ensureOpenclawSymlink();
|
|
274
|
+
ensureOpenclawSymlink(hostVersion);
|
|
203
275
|
|
|
204
|
-
//
|
|
276
|
+
// 6. Login (interactive QR scan)
|
|
205
277
|
log("插件就绪,开始首次连接...");
|
|
206
278
|
try {
|
|
207
279
|
run(`openclaw channels login --channel ${CHANNEL_ID}`, { silent: false });
|
|
@@ -211,7 +283,7 @@ function install() {
|
|
|
211
283
|
console.log(` openclaw channels login --channel ${CHANNEL_ID}`);
|
|
212
284
|
}
|
|
213
285
|
|
|
214
|
-
//
|
|
286
|
+
// 7. Restart gateway so it picks up the new account
|
|
215
287
|
log("正在重启 OpenClaw Gateway...");
|
|
216
288
|
try {
|
|
217
289
|
run(`openclaw gateway restart`, { silent: false });
|
|
@@ -231,7 +303,9 @@ function help() {
|
|
|
231
303
|
|
|
232
304
|
兼容矩阵:`);
|
|
233
305
|
for (const e of COMPAT_MATRIX) {
|
|
234
|
-
console.log(
|
|
306
|
+
console.log(
|
|
307
|
+
` ${e.distTag.padEnd(COMPAT_MATRIX_DIST_TAG_PAD)} OpenClaw ${formatRange(e.openclawRange)}`,
|
|
308
|
+
);
|
|
235
309
|
}
|
|
236
310
|
console.log();
|
|
237
311
|
}
|
package/lib/compat.mjs
CHANGED
|
@@ -8,15 +8,13 @@
|
|
|
8
8
|
export const COMPAT_MATRIX = [
|
|
9
9
|
{
|
|
10
10
|
pluginMajor: 1,
|
|
11
|
-
distTag: '
|
|
11
|
+
distTag: 'compat-host-gte2026.3.0-lt2026.3.22',
|
|
12
12
|
openclawRange: { gte: '2026.3.0', lt: '2026.3.22' },
|
|
13
|
-
label: '1.0.x (旧宿主线)',
|
|
14
13
|
},
|
|
15
14
|
{
|
|
16
15
|
pluginMajor: 2,
|
|
17
16
|
distTag: 'latest',
|
|
18
17
|
openclawRange: { gte: '2026.3.22' },
|
|
19
|
-
label: '2.0.x (新宿主线)',
|
|
20
18
|
},
|
|
21
19
|
];
|
|
22
20
|
|
package/lib/version-check.mjs
CHANGED
|
@@ -73,7 +73,7 @@ export function assertHostCompat() {
|
|
|
73
73
|
|
|
74
74
|
const supported = formatRange(entry.openclawRange);
|
|
75
75
|
const suggestion = compat
|
|
76
|
-
? `请安装 openclaw-weixin@${compat.distTag}
|
|
76
|
+
? `请安装 openclaw-weixin@${compat.distTag}`
|
|
77
77
|
: '请升级或降级 OpenClaw 宿主到受支持的版本';
|
|
78
78
|
|
|
79
79
|
throw new Error(
|