@tencent-connect/openclaw-qqbot 1.6.5-alpha.1 → 1.6.5-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-connect/openclaw-qqbot",
3
- "version": "1.6.5-alpha.1",
3
+ "version": "1.6.5-alpha.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  // globally installed openclaw package, allowing Node's native ESM resolver
11
11
  // (used by jiti with tryNative:true for .js files) to find `openclaw/plugin-sdk`.
12
12
 
13
- import { existsSync, symlinkSync, mkdirSync, readlinkSync } from "node:fs";
13
+ import { existsSync, symlinkSync, mkdirSync, realpathSync } from "node:fs";
14
14
  import { dirname, join, resolve } from "node:path";
15
15
  import { fileURLToPath } from "node:url";
16
16
  import { execSync } from "node:child_process";
@@ -18,8 +18,9 @@ import { execSync } from "node:child_process";
18
18
  const __dirname = dirname(fileURLToPath(import.meta.url));
19
19
  const pluginRoot = resolve(__dirname, "..");
20
20
 
21
- // Only run when installed under .openclaw/extensions/
22
- if (!pluginRoot.includes(".openclaw") && !pluginRoot.includes("extensions")) {
21
+ // Only run when installed under an openclaw-like extensions directory
22
+ // (supports openclaw, clawdbot, moltbot, etc.)
23
+ if (!pluginRoot.includes("extensions")) {
23
24
  process.exit(0);
24
25
  }
25
26
 
@@ -30,37 +31,83 @@ if (existsSync(linkTarget)) {
30
31
  process.exit(0);
31
32
  }
32
33
 
34
+ // CLI names to try (openclaw and its aliases)
35
+ const CLI_NAMES = ["openclaw", "clawdbot", "moltbot"];
36
+
33
37
  // Find the global openclaw installation
34
38
  let openclawRoot = null;
35
- try {
36
- // Try require.resolve from global context
37
- const globalRoot = execSync("npm root -g", { encoding: "utf-8" }).trim();
38
- const candidate = join(globalRoot, "openclaw");
39
- if (existsSync(join(candidate, "package.json"))) {
40
- openclawRoot = candidate;
41
- }
42
- } catch {}
43
39
 
40
+ // Strategy 1: npm root -g → look for any known CLI package name
44
41
  if (!openclawRoot) {
45
42
  try {
46
- // Try resolving from the openclaw CLI binary
47
- const bin = execSync("which openclaw", { encoding: "utf-8" }).trim();
48
- // bin is typically <prefix>/bin/openclaw -> ../lib/node_modules/openclaw/...
49
- const candidate = resolve(dirname(bin), "..", "lib", "node_modules", "openclaw");
50
- if (existsSync(join(candidate, "package.json"))) {
51
- openclawRoot = candidate;
43
+ const globalRoot = execSync("npm root -g", { encoding: "utf-8" }).trim();
44
+ for (const name of CLI_NAMES) {
45
+ const candidate = join(globalRoot, name);
46
+ if (existsSync(join(candidate, "package.json"))) {
47
+ openclawRoot = candidate;
48
+ break;
49
+ }
52
50
  }
53
51
  } catch {}
54
52
  }
55
53
 
54
+ // Strategy 2: resolve from the CLI binary (which openclaw / clawdbot / moltbot)
55
+ if (!openclawRoot) {
56
+ const whichCmd = process.platform === "win32" ? "where" : "which";
57
+ for (const name of CLI_NAMES) {
58
+ try {
59
+ const bin = execSync(`${whichCmd} ${name}`, { encoding: "utf-8" }).trim().split("\n")[0];
60
+ if (!bin) continue;
61
+ // Resolve symlinks to get actual binary location
62
+ const realBin = realpathSync(bin);
63
+ // bin is typically <prefix>/bin/<name> -> ../lib/node_modules/<name>/...
64
+ const candidate = resolve(dirname(realBin), "..", "lib", "node_modules", name);
65
+ if (existsSync(join(candidate, "package.json"))) {
66
+ openclawRoot = candidate;
67
+ break;
68
+ }
69
+ // Also try: binary might be inside the package itself (e.g. .../node_modules/<name>/bin/<name>)
70
+ const candidate2 = resolve(dirname(realBin), "..");
71
+ if (existsSync(join(candidate2, "package.json")) && existsSync(join(candidate2, "plugin-sdk"))) {
72
+ openclawRoot = candidate2;
73
+ break;
74
+ }
75
+ } catch {}
76
+ }
77
+ }
78
+
79
+ // Strategy 3: walk up from the extensions directory to find the CLI's data root,
80
+ // then look for a global node_modules sibling
81
+ if (!openclawRoot) {
82
+ // pluginRoot is like /home/user/.openclaw/extensions/openclaw-qqbot
83
+ // The CLI data dir is /home/user/.openclaw (or .clawdbot, .moltbot)
84
+ const extensionsDir = dirname(pluginRoot);
85
+ const dataDir = dirname(extensionsDir);
86
+ const dataDirName = dataDir.split("/").pop() || dataDir.split("\\").pop() || "";
87
+ // dataDirName is like ".openclaw" → strip the dot to get "openclaw"
88
+ const cliName = dataDirName.replace(/^\./, "");
89
+ if (cliName) {
90
+ try {
91
+ const globalRoot = execSync("npm root -g", { encoding: "utf-8" }).trim();
92
+ const candidate = join(globalRoot, cliName);
93
+ if (existsSync(join(candidate, "package.json"))) {
94
+ openclawRoot = candidate;
95
+ }
96
+ } catch {}
97
+ }
98
+ }
99
+
56
100
  if (!openclawRoot) {
57
101
  // Not fatal — plugin may work if openclaw loads it with proper alias resolution
102
+ // But log a warning so upgrade scripts can detect the failure
103
+ console.error("[postinstall-link-sdk] WARNING: could not find openclaw/clawdbot/moltbot global installation, symlink not created");
58
104
  process.exit(0);
59
105
  }
60
106
 
61
107
  try {
62
108
  mkdirSync(join(pluginRoot, "node_modules"), { recursive: true });
63
109
  symlinkSync(openclawRoot, linkTarget, "junction");
64
- } catch {
65
- // Silently ignore — symlink creation may fail on some systems
110
+ console.log(`[postinstall-link-sdk] symlink created: node_modules/openclaw -> ${openclawRoot}`);
111
+ } catch (e) {
112
+ console.error(`[postinstall-link-sdk] WARNING: symlink creation failed: ${e.message}`);
66
113
  }
@@ -315,6 +315,47 @@ foreach ($legacyName in @("qqbot", "openclaw-qq")) {
315
315
  }
316
316
  Write-Host " Installed to: $TARGET_DIR"
317
317
 
318
+ # Execute postinstall script to create openclaw SDK symlink
319
+ # (upgrade-via-npm is pure file operation, npm install is not run, so postinstall won't trigger automatically)
320
+ $PostinstallScript = Join-Path $TARGET_DIR "scripts" "postinstall-link-sdk.js"
321
+ if (Test-Path $PostinstallScript) {
322
+ Write-Host " Running postinstall: creating openclaw SDK symlink..."
323
+ try {
324
+ Push-Location $TARGET_DIR
325
+ $postOutput = & node $PostinstallScript 2>&1
326
+ Pop-Location
327
+ if ($postOutput) { Write-Host " $postOutput" }
328
+ } catch {
329
+ Write-Host " [WARN] postinstall script failed (non-fatal)" -ForegroundColor Yellow
330
+ try { Pop-Location } catch {}
331
+ }
332
+ # Verify symlink creation
333
+ $symlinkPath = Join-Path $TARGET_DIR "node_modules" "openclaw"
334
+ if (Test-Path $symlinkPath) {
335
+ Write-Host " [OK] openclaw SDK symlink ready"
336
+ } else {
337
+ Write-Host " [WARN] openclaw SDK symlink not created, attempting manual fallback..." -ForegroundColor Yellow
338
+ $cliDataDir = Split-Path $EXTENSIONS_DIR -Parent
339
+ $cliName = (Split-Path $cliDataDir -Leaf) -replace '^\.',''
340
+ try {
341
+ $globalRoot = (& npm root -g 2>$null).Trim()
342
+ $globalPkg = Join-Path $globalRoot $cliName
343
+ if ($globalRoot -and (Test-Path $globalPkg)) {
344
+ $nmDir = Join-Path $TARGET_DIR "node_modules"
345
+ if (-not (Test-Path $nmDir)) { New-Item -ItemType Directory -Path $nmDir -Force | Out-Null }
346
+ New-Item -ItemType Junction -Path $symlinkPath -Target $globalPkg -Force | Out-Null
347
+ Write-Host " [OK] Manual symlink created: -> $globalPkg"
348
+ } else {
349
+ Write-Host " [ERROR] Cannot locate global $cliName installation (npm root -g: $globalRoot)" -ForegroundColor Red
350
+ }
351
+ } catch {
352
+ Write-Host " [ERROR] Manual symlink creation also failed: $($_.Exception.Message)" -ForegroundColor Red
353
+ }
354
+ }
355
+ } else {
356
+ Write-Host " [WARN] postinstall script not found, skipping symlink creation" -ForegroundColor Yellow
357
+ }
358
+
318
359
  # [4/5] Verify installation
319
360
  Write-Host ""
320
361
  Write-Host "[4/5] Verifying installation..."
@@ -297,6 +297,36 @@ for dir_name in qqbot openclaw-qq; do
297
297
  done
298
298
  echo " 已安装到: $TARGET_DIR"
299
299
 
300
+ # 执行 postinstall 脚本创建 openclaw SDK symlink
301
+ # (upgrade-via-npm 是纯文件操作,不走 npm install,所以 postinstall 不会自动触发)
302
+ POSTINSTALL_SCRIPT="$TARGET_DIR/scripts/postinstall-link-sdk.js"
303
+ if [ -f "$POSTINSTALL_SCRIPT" ]; then
304
+ echo " 执行 postinstall: 创建 openclaw SDK symlink..."
305
+ POSTINSTALL_OUTPUT="$(cd "$TARGET_DIR" && node "$POSTINSTALL_SCRIPT" 2>&1)" || true
306
+ [ -n "$POSTINSTALL_OUTPUT" ] && echo " $POSTINSTALL_OUTPUT"
307
+ # 验证 symlink 是否创建成功
308
+ if [ -d "$TARGET_DIR/node_modules/openclaw" ]; then
309
+ echo " ✅ openclaw SDK symlink 已就绪"
310
+ else
311
+ echo " ⚠️ openclaw SDK symlink 未创建,插件可能无法加载"
312
+ echo " 尝试手动创建 symlink..."
313
+ # 手动 fallback:尝试从 CLI 数据目录名推断全局包名
314
+ _CLI_DATA_DIR="$(dirname "$EXTENSIONS_DIR")"
315
+ _CLI_NAME="$(basename "$_CLI_DATA_DIR" | sed 's/^\.//')"
316
+ _GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"
317
+ if [ -n "$_GLOBAL_ROOT" ] && [ -n "$_CLI_NAME" ] && [ -d "$_GLOBAL_ROOT/$_CLI_NAME" ]; then
318
+ mkdir -p "$TARGET_DIR/node_modules"
319
+ ln -sf "$_GLOBAL_ROOT/$_CLI_NAME" "$TARGET_DIR/node_modules/openclaw" 2>/dev/null && \
320
+ echo " ✅ 手动 symlink 创建成功: -> $_GLOBAL_ROOT/$_CLI_NAME" || \
321
+ echo " ❌ 手动 symlink 创建也失败了"
322
+ else
323
+ echo " ❌ 无法定位全局 $_CLI_NAME 安装路径(npm root -g: $_GLOBAL_ROOT)"
324
+ fi
325
+ fi
326
+ else
327
+ echo " ⚠️ 未找到 postinstall 脚本,跳过 symlink 创建"
328
+ fi
329
+
300
330
  # [4/5] 输出新版本号和升级报告(供调用方解析)
301
331
  echo ""
302
332
  echo "[4/5] 验证安装..."