@tencent-connect/openclaw-qqbot 1.6.5-alpha.0 → 1.6.5-alpha.1

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.
@@ -129,26 +129,24 @@ export function sendStartupGreetings(ctx, trigger) {
129
129
  return;
130
130
  }
131
131
  const upgradeTargetOpenId = loadUpgradeGreetingTargetOpenId(ctx.accountId, ctx.appId, ctx.log);
132
- const targetOpenId = upgradeTargetOpenId || resolveAdminOpenId(ctx);
133
- if (!targetOpenId) {
134
- markStartupGreetingFailed(ctx.accountId, ctx.appId, plan.version, "no-admin");
135
- ctx.log?.info(`[qqbot:${ctx.accountId}] Skipping startup greeting (no admin or known user)`);
132
+ // 没有 upgrade-greeting-target 文件 不是通过 /bot-upgrade 触发的升级
133
+ // (console 手动重启、脚本升级等场景),静默更新 marker 不发消息
134
+ if (!upgradeTargetOpenId) {
135
+ markStartupGreetingSent(ctx.accountId, ctx.appId, plan.version);
136
+ ctx.log?.info(`[qqbot:${ctx.accountId}] Version changed but no upgrade-greeting-target, silently updating marker (trigger=${trigger})`);
136
137
  return;
137
138
  }
138
139
  try {
139
- const receiverType = upgradeTargetOpenId ? "upgrade-requester" : "admin";
140
- ctx.log?.info(`[qqbot:${ctx.accountId}] Sending startup greeting to ${receiverType} (trigger=${trigger}): "${plan.greeting}"`);
140
+ ctx.log?.info(`[qqbot:${ctx.accountId}] Sending startup greeting to upgrade-requester (trigger=${trigger}): "${plan.greeting}"`);
141
141
  const token = await getAccessToken(ctx.appId, ctx.clientSecret);
142
142
  const GREETING_TIMEOUT_MS = 10_000;
143
143
  await Promise.race([
144
- sendProactiveC2CMessage(token, targetOpenId, plan.greeting),
144
+ sendProactiveC2CMessage(token, upgradeTargetOpenId, plan.greeting),
145
145
  new Promise((_, reject) => setTimeout(() => reject(new Error("Startup greeting send timeout (10s)")), GREETING_TIMEOUT_MS)),
146
146
  ]);
147
147
  markStartupGreetingSent(ctx.accountId, ctx.appId, plan.version);
148
- if (upgradeTargetOpenId) {
149
- clearUpgradeGreetingTargetOpenId(ctx.accountId, ctx.appId);
150
- }
151
- ctx.log?.info(`[qqbot:${ctx.accountId}] Sent startup greeting to ${receiverType}: ${targetOpenId}`);
148
+ clearUpgradeGreetingTargetOpenId(ctx.accountId, ctx.appId);
149
+ ctx.log?.info(`[qqbot:${ctx.accountId}] Sent startup greeting to upgrade-requester: ${upgradeTargetOpenId}`);
152
150
  }
153
151
  catch (err) {
154
152
  const message = err instanceof Error ? err.message : String(err);
@@ -3,6 +3,7 @@
3
3
  "name": "OpenClaw QQ Bot",
4
4
  "description": "QQ Bot channel plugin with message support, cron jobs, and proactive messaging",
5
5
  "channels": ["qqbot"],
6
+ "extensions": ["./dist/index.js"],
6
7
  "skills": ["skills/qqbot-channel", "skills/qqbot-remind", "skills/qqbot-media"],
7
8
  "capabilities": {
8
9
  "proactiveMessaging": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-connect/openclaw-qqbot",
3
- "version": "1.6.5-alpha.0",
3
+ "version": "1.6.5-alpha.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -16,32 +16,19 @@
16
16
  "scripts",
17
17
  "index.ts",
18
18
  "tsconfig.json",
19
- "openclaw.plugin.json",
20
- "clawdbot.plugin.json",
21
- "moltbot.plugin.json"
19
+ "openclaw.plugin.json"
22
20
  ],
23
- "clawdbot": {
24
- "id": "openclaw-qqbot",
25
- "extensions": [
26
- "./index.ts"
27
- ]
28
- },
29
- "moltbot": {
30
- "id": "openclaw-qqbot",
31
- "extensions": [
32
- "./index.ts"
33
- ]
34
- },
35
21
  "openclaw": {
36
22
  "id": "openclaw-qqbot",
37
23
  "extensions": [
38
- "./index.ts"
24
+ "./dist/index.js"
39
25
  ]
40
26
  },
41
27
  "scripts": {
42
28
  "build": "tsc || true",
43
29
  "dev": "tsc --watch",
44
- "prepack": "npm install --omit=dev"
30
+ "prepack": "npm install --omit=dev",
31
+ "postinstall": "node scripts/postinstall-link-sdk.js 2>/dev/null || true"
45
32
  },
46
33
  "dependencies": {
47
34
  "mpg123-decoder": "^1.0.3",
@@ -59,8 +46,6 @@
59
46
  "typescript": "^5.9.3"
60
47
  },
61
48
  "peerDependencies": {
62
- "clawdbot": "*",
63
- "moltbot": "*",
64
49
  "openclaw": "*"
65
50
  },
66
51
  "homepage": "https://github.com/tencent-connect/openclaw-qqbot",
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+
3
+ // When installed as an openclaw extension under ~/.openclaw/extensions/,
4
+ // the plugin needs access to `openclaw/plugin-sdk` at runtime.
5
+ // openclaw's jiti loader resolves this via alias by walking up from the plugin
6
+ // path to find the openclaw package root — but ~/.openclaw/extensions/ is not
7
+ // under the openclaw package tree, so the alias lookup fails.
8
+ //
9
+ // This script creates a symlink from the plugin's node_modules/openclaw to the
10
+ // globally installed openclaw package, allowing Node's native ESM resolver
11
+ // (used by jiti with tryNative:true for .js files) to find `openclaw/plugin-sdk`.
12
+
13
+ import { existsSync, symlinkSync, mkdirSync, readlinkSync } from "node:fs";
14
+ import { dirname, join, resolve } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { execSync } from "node:child_process";
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const pluginRoot = resolve(__dirname, "..");
20
+
21
+ // Only run when installed under .openclaw/extensions/
22
+ if (!pluginRoot.includes(".openclaw") && !pluginRoot.includes("extensions")) {
23
+ process.exit(0);
24
+ }
25
+
26
+ const linkTarget = join(pluginRoot, "node_modules", "openclaw");
27
+
28
+ // Already linked or exists
29
+ if (existsSync(linkTarget)) {
30
+ process.exit(0);
31
+ }
32
+
33
+ // Find the global openclaw installation
34
+ 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
+
44
+ if (!openclawRoot) {
45
+ 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;
52
+ }
53
+ } catch {}
54
+ }
55
+
56
+ if (!openclawRoot) {
57
+ // Not fatal — plugin may work if openclaw loads it with proper alias resolution
58
+ process.exit(0);
59
+ }
60
+
61
+ try {
62
+ mkdirSync(join(pluginRoot, "node_modules"), { recursive: true });
63
+ symlinkSync(openclawRoot, linkTarget, "junction");
64
+ } catch {
65
+ // Silently ignore — symlink creation may fail on some systems
66
+ }
@@ -152,27 +152,26 @@ export function sendStartupGreetings(ctx: AdminResolverContext, trigger: "READY"
152
152
  }
153
153
 
154
154
  const upgradeTargetOpenId = loadUpgradeGreetingTargetOpenId(ctx.accountId, ctx.appId, ctx.log);
155
- const targetOpenId = upgradeTargetOpenId || resolveAdminOpenId(ctx);
156
- if (!targetOpenId) {
157
- markStartupGreetingFailed(ctx.accountId, ctx.appId, plan.version, "no-admin");
158
- ctx.log?.info(`[qqbot:${ctx.accountId}] Skipping startup greeting (no admin or known user)`);
155
+
156
+ // 没有 upgrade-greeting-target 文件 → 不是通过 /bot-upgrade 触发的升级
157
+ // (console 手动重启、脚本升级等场景),静默更新 marker 不发消息
158
+ if (!upgradeTargetOpenId) {
159
+ markStartupGreetingSent(ctx.accountId, ctx.appId, plan.version);
160
+ ctx.log?.info(`[qqbot:${ctx.accountId}] Version changed but no upgrade-greeting-target, silently updating marker (trigger=${trigger})`);
159
161
  return;
160
162
  }
161
163
 
162
164
  try {
163
- const receiverType = upgradeTargetOpenId ? "upgrade-requester" : "admin";
164
- ctx.log?.info(`[qqbot:${ctx.accountId}] Sending startup greeting to ${receiverType} (trigger=${trigger}): "${plan.greeting}"`);
165
+ ctx.log?.info(`[qqbot:${ctx.accountId}] Sending startup greeting to upgrade-requester (trigger=${trigger}): "${plan.greeting}"`);
165
166
  const token = await getAccessToken(ctx.appId, ctx.clientSecret);
166
167
  const GREETING_TIMEOUT_MS = 10_000;
167
168
  await Promise.race([
168
- sendProactiveC2CMessage(token, targetOpenId, plan.greeting),
169
+ sendProactiveC2CMessage(token, upgradeTargetOpenId, plan.greeting),
169
170
  new Promise((_, reject) => setTimeout(() => reject(new Error("Startup greeting send timeout (10s)")), GREETING_TIMEOUT_MS)),
170
171
  ]);
171
172
  markStartupGreetingSent(ctx.accountId, ctx.appId, plan.version);
172
- if (upgradeTargetOpenId) {
173
- clearUpgradeGreetingTargetOpenId(ctx.accountId, ctx.appId);
174
- }
175
- ctx.log?.info(`[qqbot:${ctx.accountId}] Sent startup greeting to ${receiverType}: ${targetOpenId}`);
173
+ clearUpgradeGreetingTargetOpenId(ctx.accountId, ctx.appId);
174
+ ctx.log?.info(`[qqbot:${ctx.accountId}] Sent startup greeting to upgrade-requester: ${upgradeTargetOpenId}`);
176
175
  } catch (err) {
177
176
  const message = err instanceof Error ? err.message : String(err);
178
177
  markStartupGreetingFailed(ctx.accountId, ctx.appId, plan.version, message);
@@ -1,16 +0,0 @@
1
- {
2
- "id": "openclaw-qqbot",
3
- "name": "OpenClaw QQ Bot",
4
- "description": "QQ Bot channel plugin with message support, cron jobs, and proactive messaging",
5
- "channels": ["qqbot"],
6
- "skills": ["skills/qqbot-channel", "skills/qqbot-remind", "skills/qqbot-media"],
7
- "capabilities": {
8
- "proactiveMessaging": true,
9
- "cronJobs": true
10
- },
11
- "configSchema": {
12
- "type": "object",
13
- "additionalProperties": false,
14
- "properties": {}
15
- }
16
- }
@@ -1,16 +0,0 @@
1
- {
2
- "id": "openclaw-qqbot",
3
- "name": "OpenClaw QQ Bot",
4
- "description": "QQ Bot channel plugin with message support, cron jobs, and proactive messaging",
5
- "channels": ["qqbot"],
6
- "skills": ["skills/qqbot-channel", "skills/qqbot-remind", "skills/qqbot-media"],
7
- "capabilities": {
8
- "proactiveMessaging": true,
9
- "cronJobs": true
10
- },
11
- "configSchema": {
12
- "type": "object",
13
- "additionalProperties": false,
14
- "properties": {}
15
- }
16
- }