@tencent-weixin/openclaw-weixin-cli 2.1.1 → 2.1.3

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 CHANGED
@@ -22,7 +22,7 @@ npx -y @tencent-weixin/openclaw-weixin-cli install
22
22
  | openclaw-weixin | 支持的 OpenClaw | dist-tag | 说明 |
23
23
  |-----------------|-----------------------|---------------------------------------|----------------------|
24
24
  | 1.0.x | >=2026.3.0 <2026.3.22 | `compat-host-gte2026.3.0-lt2026.3.22` | 兼容轨道 |
25
- | 2.0.x | >=2026.3.22 | `latest` | 当前推荐主线 |
25
+ | v2 主线 | >=2026.3.22 | `latest` | 当前推荐 |
26
26
 
27
27
  > 从 2.0.0 开始,插件采用独立 semver 版本号,不再对齐宿主 OpenClaw 版本号。
28
28
 
@@ -82,114 +82,3 @@ openclaw --version
82
82
 
83
83
  - **插件仓库**:openclaw-weixin,通过各分支发布到不同的 npm dist-tag
84
84
  - **本仓库**:CLI 安装器,根据 `COMPAT_MATRIX` 自动选择正确的插件 dist-tag 来安装
85
-
86
- ### 分支管理规则
87
-
88
- 内网和外网通过不同分支管理,prerelease 分支从主分支拉出,合并回主分支:
89
-
90
- | 分支 | 用途 | package.json 状态 |
91
- |------|------|------------------|
92
- | `master-prerelease` | 日常开发 + 内网发布 | 内网发布后保持内网包名和版本 |
93
- | `master` | 外网发布 | 外网发布后保持外网包名和版本 |
94
-
95
- **核心原则:**
96
- - 日常开发和内网发布在 `-prerelease` 分支上进行
97
- - 需要发外网时,将 prerelease 分支合入对应主分支,再在主分支上发布
98
- - 发布后 package.json **不回退**,分支保持对应环境的最新发布状态
99
- - prerelease 和主分支同构(共用 `publish.config.json`),合并时自然更新
100
-
101
- ### CLI 发布命令
102
-
103
- ```bash
104
- # 在 prerelease 分支上发布内网
105
- node scripts/publish.mjs internal patch
106
-
107
- # dry run 预检
108
- node scripts/publish.mjs internal patch --dry-run
109
- ```
110
-
111
- 发布脚本会:
112
- 1. 检查工作区是否干净
113
- 2. 将 `package.json` 的 name/version 和 `cli.mjs` 的 PLUGIN_SPEC 替换为目标环境的值
114
- 3. 更新 `publish.config.json` 中对应目标的版本号
115
- 4. 提交 release commit 并打 git tag
116
- 5. npm publish
117
- 6. push commit + tag
118
-
119
- 发布后 package.json 保持发布态,不回退。如果 npm publish 失败,自动回滚 release commit 和 tag。
120
-
121
- ### 内网验证后发外网
122
-
123
- ```bash
124
- # ① 在 prerelease 分支上完成内网发布和验证
125
-
126
- # ② 合入主分支
127
- git checkout master
128
- git merge master-prerelease
129
-
130
- # ③ 在主分支上发布外网
131
- node scripts/publish.mjs external patch
132
- ```
133
-
134
- ### 兼容轨道发版流程
135
-
136
- 当 openclaw 发布破坏兼容性的新版本时:
137
-
138
- #### 1. 插件仓库操作(openclaw-weixin)
139
-
140
- ```bash
141
- # 从当前分支拉出兼容轨道
142
- git checkout -b compat-host-gteX.Y.Z-ltA.B.C-prerelease master-prerelease
143
- git checkout -b compat-host-gteX.Y.Z-ltA.B.C master
144
- # 修改 compat 分支上的 publish.config.json,将 npmTag 改为轨道名
145
-
146
- # master-prerelease 上适配新宿主,major + 1
147
- ```
148
-
149
- #### 2. CLI 仓库操作(本仓库)
150
-
151
- ```bash
152
- # ① 更新 lib/compat.mjs 的 COMPAT_MATRIX
153
-
154
- # ② 在 prerelease 分支上发布内网验证
155
- node scripts/publish.mjs internal minor
156
-
157
- # ③ 验证后合入主分支发外网
158
- git checkout master && git merge master-prerelease
159
- node scripts/publish.mjs external minor
160
- ```
161
-
162
- #### 3. 验证清单
163
-
164
- - [ ] `npx @tencent/openclaw-weixin-cli install` 在旧宿主上安装兼容轨道版本
165
- - [ ] `npx @tencent/openclaw-weixin-cli install` 在新宿主上安装 latest 版本
166
- - [ ] 已安装旧 tag 的用户重跑 CLI 后自动卸载旧版、安装新版
167
- - [ ] 插件运行时 `version-check.mjs` 报错信息指引正确
168
-
169
- ### 兼容轨道 bug 修复
170
-
171
- ```bash
172
- # ① 在 compat prerelease 分支上修复
173
- git checkout compat-host-gteX.Y.Z-ltA.B.C-prerelease
174
- # cherry-pick 或直接修复
175
- node scripts/publish.mjs internal patch
176
-
177
- # ② 需要发外网时合入 compat 主分支
178
- git checkout compat-host-gteX.Y.Z-ltA.B.C
179
- git merge compat-host-gteX.Y.Z-ltA.B.C-prerelease
180
- node scripts/publish.mjs external patch
181
-
182
- # ③ 评估是否需要同步到 master 和其他 compat 分支
183
- ```
184
-
185
- > CLI 不需要重新发布——同一 dist-tag 下的 patch 更新,用户通过 `openclaw plugins update` 即可获取。
186
-
187
- ## 开发
188
-
189
- ```bash
190
- # 安装开发依赖
191
- npm install
192
-
193
- # 本地测试 install 命令
194
- node cli.mjs install
195
- ```
package/cli.mjs CHANGED
@@ -16,11 +16,23 @@ const CHANNEL_ID = "openclaw-weixin";
16
16
  /** Only OpenClaw 2026.3.22–2026.3.23 need node_modules/openclaw symlink for jiti. */
17
17
  const SYMLINK_OPENCLAW_MIN = "2026.3.22";
18
18
  const SYMLINK_OPENCLAW_MAX = "2026.3.23";
19
+ /**
20
+ * OpenClaw 2026.5.2 之前的 5.x 版本里,channel-catalog-registry 调
21
+ * discoverOpenClawPlugins 时漏传 installRecords,导致 npm 装的第三方插件
22
+ * 不被 CLI catalog 收录(`channels add/login` 报 Unsupported channel)。
23
+ * 我们通过把 plugin 同时软链到 ~/.openclaw/extensions/<id> 让它走 global
24
+ * 发现路径,绕开 ledger。host 修复发布后需要把上界 EXT_SYMLINK_OPENCLAW_MAX
25
+ * 收紧到具体的修复版本号。
26
+ */
27
+ const EXT_SYMLINK_OPENCLAW_MIN = "2026.5.2";
28
+ const EXT_SYMLINK_OPENCLAW_MAX = "2026.5.99";
19
29
 
20
30
  const LEGACY_TAG_ALIASES = {
21
31
  legacy: "compat-host-gte2026.3.0-lt2026.3.22",
22
32
  };
23
33
 
34
+ const COMPAT_MATRIX_DIST_TAG_PAD = Math.max(...COMPAT_MATRIX.map((e) => e.distTag.length));
35
+
24
36
  // ── helpers ──────────────────────────────────────────────────────────────────
25
37
 
26
38
  function log(msg) {
@@ -70,7 +82,9 @@ function selectPluginTag(openclawVersion) {
70
82
  error(`当前 OpenClaw 版本 ${openclawVersion} 不在任何已知兼容范围内`);
71
83
  console.log("\n 已知兼容矩阵:");
72
84
  for (const e of COMPAT_MATRIX) {
73
- console.log(` ${e.label} → OpenClaw ${formatRange(e.openclawRange)}`);
85
+ console.log(
86
+ ` ${e.distTag.padEnd(COMPAT_MATRIX_DIST_TAG_PAD)} OpenClaw ${formatRange(e.openclawRange)}`,
87
+ );
74
88
  }
75
89
  console.log();
76
90
  return null;
@@ -167,6 +181,76 @@ function ensureOpenclawSymlink(hostVersion) {
167
181
  log(`已创建 symlink: node_modules/openclaw → ${hostRoot}`);
168
182
  }
169
183
 
184
+ // ── extensions symlink (host 5.2 catalog bug workaround) ────────────────────
185
+
186
+ function hostVersionNeedsExtSymlink(hostVersion) {
187
+ if (!hostVersion) return false;
188
+ const geMin = compareVersions(hostVersion, EXT_SYMLINK_OPENCLAW_MIN);
189
+ const leMax = compareVersions(hostVersion, EXT_SYMLINK_OPENCLAW_MAX);
190
+ return (
191
+ !Number.isNaN(geMin) &&
192
+ !Number.isNaN(leMax) &&
193
+ geMin >= 0 &&
194
+ leMax <= 0
195
+ );
196
+ }
197
+
198
+ function resolveNpmInstalledPluginRoot() {
199
+ const stateDir = process.env.OPENCLAW_STATE_DIR || path.join(os.homedir(), ".openclaw");
200
+ const dir = path.join(stateDir, "npm", "node_modules", PLUGIN_SPEC);
201
+ try {
202
+ if (fs.existsSync(path.join(dir, "package.json"))) return dir;
203
+ } catch {}
204
+ return null;
205
+ }
206
+
207
+ /**
208
+ * Make ~/.openclaw/extensions/openclaw-weixin a symlink pointing to the
209
+ * npm-installed plugin root. This lets host 5.2's CLI catalog (which scans
210
+ * the global extensions root) discover the plugin even though
211
+ * channel-catalog-registry forgets to forward installRecords to discovery.
212
+ */
213
+ function ensurePluginExtSymlink(hostVersion) {
214
+ if (!hostVersionNeedsExtSymlink(hostVersion)) {
215
+ return;
216
+ }
217
+
218
+ const npmRoot = resolveNpmInstalledPluginRoot();
219
+ if (!npmRoot) {
220
+ return;
221
+ }
222
+
223
+ const linkPath = resolvePluginExtDir();
224
+ let linkDirReal;
225
+ try {
226
+ linkDirReal = fs.realpathSync(npmRoot);
227
+ } catch {
228
+ return;
229
+ }
230
+
231
+ // Already correct?
232
+ try {
233
+ const stat = fs.lstatSync(linkPath);
234
+ if (stat.isSymbolicLink()) {
235
+ const existingReal = fs.realpathSync(linkPath);
236
+ if (existingReal === linkDirReal) return;
237
+ }
238
+ fs.rmSync(linkPath, { recursive: true, force: true });
239
+ } catch {
240
+ // doesn't exist — fine
241
+ }
242
+
243
+ fs.mkdirSync(path.dirname(linkPath), { recursive: true });
244
+ try {
245
+ fs.symlinkSync(npmRoot, linkPath, "dir");
246
+ log(`已创建 symlink: extensions/${CHANNEL_ID} → ${npmRoot}`);
247
+ } catch (err) {
248
+ error(
249
+ `创建 extensions symlink 失败 (${err?.message ?? err});CLI 可能仍会报 Unsupported channel。`,
250
+ );
251
+ }
252
+ }
253
+
170
254
  // ── installed plugin detection ───────────────────────────────────────────────
171
255
 
172
256
  /**
@@ -217,7 +301,7 @@ function install() {
217
301
  }
218
302
 
219
303
  const pluginInstallSpec = `${PLUGIN_SPEC}@${compat.distTag}`;
220
- log(`匹配兼容版本: ${compat.label} (dist-tag: ${compat.distTag})`);
304
+ log(`匹配 dist-tag: ${compat.distTag}`);
221
305
 
222
306
  // 3. If already installed with a different dist-tag, uninstall first
223
307
  // so the fresh install picks up the correct dist-tag.
@@ -269,6 +353,11 @@ function install() {
269
353
  // so jiti can resolve openclaw/plugin-sdk/* without a runtime dependency.
270
354
  ensureOpenclawSymlink(hostVersion);
271
355
 
356
+ // 5b. Symlink npm-installed plugin into ~/.openclaw/extensions/<id>
357
+ // (2026.5.2 only) so the CLI catalog can discover this channel despite
358
+ // the channel-catalog-registry installRecords bug.
359
+ ensurePluginExtSymlink(hostVersion);
360
+
272
361
  // 6. Login (interactive QR scan)
273
362
  log("插件就绪,开始首次连接...");
274
363
  try {
@@ -299,7 +388,9 @@ function help() {
299
388
 
300
389
  兼容矩阵:`);
301
390
  for (const e of COMPAT_MATRIX) {
302
- console.log(` ${e.label.padEnd(28)} OpenClaw ${formatRange(e.openclawRange)}`);
391
+ console.log(
392
+ ` ${e.distTag.padEnd(COMPAT_MATRIX_DIST_TAG_PAD)} OpenClaw ${formatRange(e.openclawRange)}`,
393
+ );
303
394
  }
304
395
  console.log();
305
396
  }
package/lib/compat.mjs CHANGED
@@ -10,13 +10,11 @@ export const COMPAT_MATRIX = [
10
10
  pluginMajor: 1,
11
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 (兼容轨道: OpenClaw >=2026.3.0 <2026.3.22)',
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
 
@@ -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} (${compat.label})`
76
+ ? `请安装 openclaw-weixin@${compat.distTag}`
77
77
  : '请升级或降级 OpenClaw 宿主到受支持的版本';
78
78
 
79
79
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-weixin/openclaw-weixin-cli",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Lightweight installer for the OpenClaw Weixin channel plugin",
5
5
  "license": "MIT",
6
6
  "author": "Tencent",