openclaw-plugin-yuanbao 2.12.0 → 3.0.1-beta.fc13eaa5
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 +0 -1
- package/api.ts +0 -4
- package/dist/api.d.ts +0 -1
- package/dist/api.js +0 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -5
- package/dist/setup-entry.d.ts +1 -1
- package/dist/src/business/commands/log-upload/extractor.js +1 -1
- package/dist/src/business/pipeline/middlewares/dispatch-reply.js +1 -12
- package/dist/src/business/pipeline/middlewares/guard-special-command.js +0 -40
- package/dist/src/business/pipeline/middlewares/guard-special-command.test.js +0 -24
- package/dist/src/channel-shared.d.ts +2 -2
- package/dist/src/channel-shared.js +1 -1
- package/dist/src/setup-surface.js +7 -7
- package/index.ts +1 -11
- package/openclaw.plugin.json +2 -2
- package/package.json +5 -8
- package/src/business/commands/log-upload/extractor.ts +1 -1
- package/src/business/pipeline/middlewares/dispatch-reply.ts +1 -14
- package/src/business/pipeline/middlewares/guard-special-command.test.ts +0 -24
- package/src/business/pipeline/middlewares/guard-special-command.ts +1 -53
- package/src/channel-shared.ts +1 -1
- package/src/setup-surface.ts +7 -7
- package/dist/src/business/commands/upgrade/env.d.ts +0 -4
- package/dist/src/business/commands/upgrade/env.js +0 -45
- package/dist/src/business/commands/upgrade/index.d.ts +0 -8
- package/dist/src/business/commands/upgrade/index.js +0 -33
- package/dist/src/business/commands/upgrade/upgrade.d.ts +0 -2
- package/dist/src/business/commands/upgrade/upgrade.js +0 -299
- package/dist/src/business/commands/upgrade/utils.d.ts +0 -24
- package/dist/src/business/commands/upgrade/utils.js +0 -197
- package/src/business/commands/upgrade/env.ts +0 -64
- package/src/business/commands/upgrade/index.ts +0 -62
- package/src/business/commands/upgrade/upgrade.ts +0 -414
- package/src/business/commands/upgrade/utils.ts +0 -267
package/README.md
CHANGED
package/api.ts
CHANGED
|
@@ -8,9 +8,5 @@ export { yuanbaoSetupPlugin } from "./src/channel.setup.js";
|
|
|
8
8
|
export { initLogger } from "./src/logger.js";
|
|
9
9
|
export { initEnv } from "./src/infra/env.js";
|
|
10
10
|
export { registerTools } from "./src/business/tools/index.js";
|
|
11
|
-
export {
|
|
12
|
-
yuanbaoUpgradeCommand,
|
|
13
|
-
yuanbaobotUpgradeCommand,
|
|
14
|
-
} from "./src/business/commands/upgrade/index.js";
|
|
15
11
|
export { logUploadCommandDefinition } from "./src/business/commands/log-upload/index.js";
|
|
16
12
|
export { initBuiltinStickers } from "./src/business/actions/sticker/init-builtin-stickers.js";
|
package/dist/api.d.ts
CHANGED
|
@@ -3,6 +3,5 @@ export { yuanbaoSetupPlugin } from "./src/channel.setup.js";
|
|
|
3
3
|
export { initLogger } from "./src/logger.js";
|
|
4
4
|
export { initEnv } from "./src/infra/env.js";
|
|
5
5
|
export { registerTools } from "./src/business/tools/index.js";
|
|
6
|
-
export { yuanbaoUpgradeCommand, yuanbaobotUpgradeCommand, } from "./src/business/commands/upgrade/index.js";
|
|
7
6
|
export { logUploadCommandDefinition } from "./src/business/commands/log-upload/index.js";
|
|
8
7
|
export { initBuiltinStickers } from "./src/business/actions/sticker/init-builtin-stickers.js";
|
package/dist/api.js
CHANGED
|
@@ -3,6 +3,5 @@ export { yuanbaoSetupPlugin } from "./src/channel.setup.js";
|
|
|
3
3
|
export { initLogger } from "./src/logger.js";
|
|
4
4
|
export { initEnv } from "./src/infra/env.js";
|
|
5
5
|
export { registerTools } from "./src/business/tools/index.js";
|
|
6
|
-
export { yuanbaoUpgradeCommand, yuanbaobotUpgradeCommand, } from "./src/business/commands/upgrade/index.js";
|
|
7
6
|
export { logUploadCommandDefinition } from "./src/business/commands/log-upload/index.js";
|
|
8
7
|
export { initBuiltinStickers } from "./src/business/actions/sticker/init-builtin-stickers.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("openclaw/plugin-sdk/channel-entry-contract").BundledChannelEntryContract<import("openclaw/plugin-sdk
|
|
1
|
+
declare const _default: import("openclaw/plugin-sdk/channel-entry-contract").BundledChannelEntryContract<import("openclaw/plugin-sdk").ChannelPlugin>;
|
|
2
2
|
export default _default;
|
package/dist/index.js
CHANGED
|
@@ -7,11 +7,7 @@ function registerTools(api) {
|
|
|
7
7
|
register(api);
|
|
8
8
|
}
|
|
9
9
|
function registerCommands(api) {
|
|
10
|
-
const yuanbaoUpgradeCommand = loadBundledEntryExportSync(import.meta.url, { specifier: "./api.js", exportName: "yuanbaoUpgradeCommand" });
|
|
11
|
-
const yuanbaobotUpgradeCommand = loadBundledEntryExportSync(import.meta.url, { specifier: "./api.js", exportName: "yuanbaobotUpgradeCommand" });
|
|
12
10
|
const logUploadCommandDefinition = loadBundledEntryExportSync(import.meta.url, { specifier: "./api.js", exportName: "logUploadCommandDefinition" });
|
|
13
|
-
api.registerCommand(yuanbaoUpgradeCommand);
|
|
14
|
-
api.registerCommand(yuanbaobotUpgradeCommand);
|
|
15
11
|
api.registerCommand(logUploadCommandDefinition);
|
|
16
12
|
}
|
|
17
13
|
function initBuiltinStickers() {
|
|
@@ -36,7 +32,7 @@ function initLogger(api) {
|
|
|
36
32
|
init(api);
|
|
37
33
|
}
|
|
38
34
|
export default defineBundledChannelEntry({
|
|
39
|
-
id: "
|
|
35
|
+
id: "yuanbao",
|
|
40
36
|
name: "YuanBao",
|
|
41
37
|
description: "YuanBao channel plugin",
|
|
42
38
|
importMetaUrl: import.meta.url,
|
package/dist/setup-entry.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("openclaw/plugin-sdk/channel-entry-contract").BundledChannelSetupEntryContract<import("openclaw/plugin-sdk
|
|
1
|
+
declare const _default: import("openclaw/plugin-sdk/channel-entry-contract").BundledChannelSetupEntryContract<import("openclaw/plugin-sdk").ChannelPlugin>;
|
|
2
2
|
export default _default;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
2
|
-
import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/
|
|
2
|
+
import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/run-command";
|
|
3
3
|
import { createLog } from "../../../logger.js";
|
|
4
4
|
import { getYuanbaoRuntime } from "../../../runtime.js";
|
|
5
5
|
const EXEC_TIMEOUT_MS = 10_000;
|
|
@@ -3,7 +3,6 @@ import { resolveOutboundMediaUrls, normalizeOutboundReplyPayload, } from "opencl
|
|
|
3
3
|
import { WS_HEARTBEAT } from "../../../access/ws/types.js";
|
|
4
4
|
import { getPluginVersion } from "../../../infra/env.js";
|
|
5
5
|
import { createLog } from "../../../logger.js";
|
|
6
|
-
import { PLUGIN_ID, readInstalledVersion } from "../../commands/upgrade/utils.js";
|
|
7
6
|
import { createReplyHeartbeatController } from "../../outbound/heartbeat.js";
|
|
8
7
|
import { runWithTraceContext } from "../../trace/context.js";
|
|
9
8
|
export const dispatchReply = {
|
|
@@ -152,17 +151,7 @@ export const dispatchReply = {
|
|
|
152
151
|
await doDispatchReply();
|
|
153
152
|
}
|
|
154
153
|
if (ctx.rawBody.trim().startsWith("/status")) {
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
const installed = await readInstalledVersion(PLUGIN_ID);
|
|
158
|
-
displayVersion = installed ?? getPluginVersion();
|
|
159
|
-
}
|
|
160
|
-
catch (err) {
|
|
161
|
-
ctx.log.warn("[dispatch-reply] readInstalledVersion failed, fallback to in-memory", {
|
|
162
|
-
error: String(err),
|
|
163
|
-
});
|
|
164
|
-
displayVersion = getPluginVersion();
|
|
165
|
-
}
|
|
154
|
+
const displayVersion = getPluginVersion();
|
|
166
155
|
await queueSession.push({
|
|
167
156
|
type: "text",
|
|
168
157
|
text: `\n\n🤖 Bot: yuanbaobot(${displayVersion})`,
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { sendText } from "../../actions/text/send.js";
|
|
2
|
-
import { parseUpgradeCommand } from "../../commands/upgrade/index.js";
|
|
3
|
-
import { performUpgrade } from "../../commands/upgrade/upgrade.js";
|
|
4
2
|
function isOwnerMessage(raw) {
|
|
5
3
|
return Boolean(raw.bot_owner_id && raw.from_account === raw.bot_owner_id);
|
|
6
4
|
}
|
|
@@ -21,44 +19,6 @@ export const guardSpecialCommand = {
|
|
|
21
19
|
handler: async (ctx, next) => {
|
|
22
20
|
const { raw, rawBody, fromAccount, isGroup, groupCode } = ctx;
|
|
23
21
|
const trimmedBody = rawBody.trim();
|
|
24
|
-
const upgradeCmd = parseUpgradeCommand(trimmedBody);
|
|
25
|
-
if (upgradeCmd.matched) {
|
|
26
|
-
ctx.log.info(`[guard-special-command] received ${trimmedBody} command`);
|
|
27
|
-
if (!isOwnerMessage(raw)) {
|
|
28
|
-
ctx.log.warn(`[guard-special-command] non-owner attempted ${trimmedBody}, rejected`, {
|
|
29
|
-
fromAccount,
|
|
30
|
-
});
|
|
31
|
-
const rejectText = isGroup
|
|
32
|
-
? `派中暂不支持该命令,请 Bot 创建人在私聊发送 ${trimmedBody} 进行升级`
|
|
33
|
-
: "⚠️ 您无权执行此操作,仅 Bot 创建人可以执行此操作。";
|
|
34
|
-
await sendReplyMessage(ctx, rejectText);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
ctx.log.info(`[guard-special-command] owner triggered upgrade command ${trimmedBody}`, {
|
|
38
|
-
fromAccount,
|
|
39
|
-
});
|
|
40
|
-
const onProgress = async (text) => {
|
|
41
|
-
try {
|
|
42
|
-
await sendReplyMessage(ctx, text);
|
|
43
|
-
}
|
|
44
|
-
catch (err) {
|
|
45
|
-
ctx.log.error("[guard-special-command] onProgress sendReplyMessage failed", {
|
|
46
|
-
error: String(err),
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
try {
|
|
51
|
-
const resultText = await performUpgrade(ctx.config, ctx.account.accountId, onProgress, upgradeCmd.version);
|
|
52
|
-
if (resultText) {
|
|
53
|
-
await sendReplyMessage(ctx, resultText);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
ctx.log.error("[guard-special-command] performUpgrade threw", { error: String(err) });
|
|
58
|
-
await sendReplyMessage(ctx, "❌ 升级过程发生异常,请稍后重试。");
|
|
59
|
-
}
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
22
|
if (trimmedBody.startsWith("/issue-log")) {
|
|
63
23
|
ctx.log.info("[guard-special-command] received /issue-log command");
|
|
64
24
|
if (!isOwnerMessage(raw)) {
|
|
@@ -2,30 +2,6 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
import { createMockCtx, createMockNext } from "../test-helpers/mock-ctx.js";
|
|
4
4
|
function setupMocks(t) {
|
|
5
|
-
const UPGRADE_COMMAND_NAMES = ["/yuanbao-upgrade", "/yuanbaobot-upgrade"];
|
|
6
|
-
t.mock.module("../../commands/upgrade/index.js", {
|
|
7
|
-
namedExports: {
|
|
8
|
-
UPGRADE_COMMAND_NAMES,
|
|
9
|
-
parseUpgradeCommand(rawBody) {
|
|
10
|
-
const body = rawBody.trim();
|
|
11
|
-
for (const name of UPGRADE_COMMAND_NAMES) {
|
|
12
|
-
if (body === name) {
|
|
13
|
-
return { matched: true };
|
|
14
|
-
}
|
|
15
|
-
if (body.startsWith(`${name} `)) {
|
|
16
|
-
const version = body.slice(name.length + 1).trim() || undefined;
|
|
17
|
-
return { matched: true, version };
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return { matched: false };
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
t.mock.module("../../commands/upgrade/upgrade.js", {
|
|
25
|
-
namedExports: {
|
|
26
|
-
performUpgrade: async () => "",
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
5
|
t.mock.module("../../actions/text/send.js", {
|
|
30
6
|
namedExports: {
|
|
31
7
|
sendText: async () => ({ ok: true }),
|
|
@@ -3,9 +3,9 @@ import { yuanbaoConfigSchema } from "./config-schema.js";
|
|
|
3
3
|
import { yuanbaoSetupAdapter } from "./setup-core.js";
|
|
4
4
|
import { yuanbaoSetupWizard } from "./setup-surface.js";
|
|
5
5
|
import type { ResolvedYuanbaoAccount } from "./types.js";
|
|
6
|
-
export declare const YUANBAO_CHANNEL_ID: "
|
|
6
|
+
export declare const YUANBAO_CHANNEL_ID: "yuanbao";
|
|
7
7
|
export declare const yuanbaoMeta: {
|
|
8
|
-
readonly id: "
|
|
8
|
+
readonly id: "yuanbao";
|
|
9
9
|
readonly label: "Yuanbao";
|
|
10
10
|
readonly selectionLabel: "Yuanbao (腾讯元宝)";
|
|
11
11
|
readonly detailLabel: "Yuanbao";
|
|
@@ -3,7 +3,7 @@ import { listYuanbaoAccountIds, resolveDefaultYuanbaoAccountId, resolveYuanbaoAc
|
|
|
3
3
|
import { yuanbaoConfigSchema } from "./config-schema.js";
|
|
4
4
|
import { yuanbaoSetupAdapter } from "./setup-core.js";
|
|
5
5
|
import { yuanbaoSetupWizard } from "./setup-surface.js";
|
|
6
|
-
export const YUANBAO_CHANNEL_ID = "
|
|
6
|
+
export const YUANBAO_CHANNEL_ID = "yuanbao";
|
|
7
7
|
export const yuanbaoMeta = {
|
|
8
8
|
id: YUANBAO_CHANNEL_ID,
|
|
9
9
|
label: "Yuanbao",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createStandardChannelSetupStatus, setSetupChannelEnabled, patchTopLevelChannelConfigSection, } from "openclaw/plugin-sdk/setup";
|
|
2
2
|
import { resolveYuanbaoAccount } from "./accounts.js";
|
|
3
|
-
const
|
|
3
|
+
const YUANBAO_CHANNEL_ID = "yuanbao";
|
|
4
4
|
export const yuanbaoSetupWizard = {
|
|
5
|
-
channel:
|
|
5
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
6
6
|
status: createStandardChannelSetupStatus({
|
|
7
7
|
channelLabel: "YuanBao Bot",
|
|
8
8
|
configuredLabel: "configured",
|
|
@@ -62,7 +62,7 @@ export const yuanbaoSetupWizard = {
|
|
|
62
62
|
},
|
|
63
63
|
applySet: ({ cfg, value }) => patchTopLevelChannelConfigSection({
|
|
64
64
|
cfg,
|
|
65
|
-
channel:
|
|
65
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
66
66
|
patch: { appKey: value },
|
|
67
67
|
}),
|
|
68
68
|
},
|
|
@@ -92,7 +92,7 @@ export const yuanbaoSetupWizard = {
|
|
|
92
92
|
},
|
|
93
93
|
applySet: ({ cfg, value }) => patchTopLevelChannelConfigSection({
|
|
94
94
|
cfg,
|
|
95
|
-
channel:
|
|
95
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
96
96
|
patch: { appSecret: value },
|
|
97
97
|
}),
|
|
98
98
|
},
|
|
@@ -108,13 +108,13 @@ export const yuanbaoSetupWizard = {
|
|
|
108
108
|
},
|
|
109
109
|
applySet: ({ cfg, value }) => patchTopLevelChannelConfigSection({
|
|
110
110
|
cfg,
|
|
111
|
-
channel:
|
|
111
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
112
112
|
patch: { name: value },
|
|
113
113
|
}),
|
|
114
114
|
},
|
|
115
115
|
],
|
|
116
116
|
finalize: ({ cfg }) => {
|
|
117
|
-
const next = setSetupChannelEnabled(cfg,
|
|
117
|
+
const next = setSetupChannelEnabled(cfg, YUANBAO_CHANNEL_ID, true);
|
|
118
118
|
return { cfg: next };
|
|
119
119
|
},
|
|
120
120
|
completionNote: {
|
|
@@ -124,5 +124,5 @@ export const yuanbaoSetupWizard = {
|
|
|
124
124
|
"Run `openclaw start` to connect your bot.",
|
|
125
125
|
],
|
|
126
126
|
},
|
|
127
|
-
disable: (cfg) => setSetupChannelEnabled(cfg,
|
|
127
|
+
disable: (cfg) => setSetupChannelEnabled(cfg, YUANBAO_CHANNEL_ID, false),
|
|
128
128
|
};
|
package/index.ts
CHANGED
|
@@ -15,21 +15,11 @@ function registerTools(api: OpenClawPluginApi) {
|
|
|
15
15
|
|
|
16
16
|
/** Lazy-load and register all slash commands */
|
|
17
17
|
function registerCommands(api: OpenClawPluginApi) {
|
|
18
|
-
const yuanbaoUpgradeCommand = loadBundledEntryExportSync<Parameters<OpenClawPluginApi["registerCommand"]>[0]>(
|
|
19
|
-
import.meta.url,
|
|
20
|
-
{ specifier: "./api.js", exportName: "yuanbaoUpgradeCommand" },
|
|
21
|
-
);
|
|
22
|
-
const yuanbaobotUpgradeCommand = loadBundledEntryExportSync<Parameters<OpenClawPluginApi["registerCommand"]>[0]>(
|
|
23
|
-
import.meta.url,
|
|
24
|
-
{ specifier: "./api.js", exportName: "yuanbaobotUpgradeCommand" },
|
|
25
|
-
);
|
|
26
18
|
const logUploadCommandDefinition = loadBundledEntryExportSync<Parameters<OpenClawPluginApi["registerCommand"]>[0]>(
|
|
27
19
|
import.meta.url,
|
|
28
20
|
{ specifier: "./api.js", exportName: "logUploadCommandDefinition" },
|
|
29
21
|
);
|
|
30
22
|
|
|
31
|
-
api.registerCommand(yuanbaoUpgradeCommand);
|
|
32
|
-
api.registerCommand(yuanbaobotUpgradeCommand);
|
|
33
23
|
api.registerCommand(logUploadCommandDefinition);
|
|
34
24
|
}
|
|
35
25
|
|
|
@@ -61,7 +51,7 @@ function initLogger(api: OpenClawPluginApi) {
|
|
|
61
51
|
}
|
|
62
52
|
|
|
63
53
|
export default defineBundledChannelEntry({
|
|
64
|
-
id: "
|
|
54
|
+
id: "yuanbao",
|
|
65
55
|
name: "YuanBao",
|
|
66
56
|
description: "YuanBao channel plugin",
|
|
67
57
|
importMetaUrl: import.meta.url,
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-plugin-yuanbao",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1-beta.fc13eaa5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Tencent YuanBao intelligent bot channel plugin",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"setupEntry": "./setup-entry.ts",
|
|
31
31
|
"channel": {
|
|
32
|
-
"id": "
|
|
32
|
+
"id": "yuanbao",
|
|
33
33
|
"label": "Yuanbao",
|
|
34
34
|
"selectionLabel": "Yuanbao (元宝)",
|
|
35
35
|
"detailLabel": "Yuanbao",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"npmSpec": "openclaw-plugin-yuanbao",
|
|
53
53
|
"localPath": "extensions/yuanbao",
|
|
54
54
|
"defaultChoice": "npm",
|
|
55
|
-
"minHostVersion": ">=2026.4.
|
|
55
|
+
"minHostVersion": ">=2026.4.27"
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"private": false,
|
|
@@ -74,16 +74,13 @@
|
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"cos-nodejs-sdk-v5": "^2.15.4",
|
|
76
76
|
"protobufjs": "^8.0.0",
|
|
77
|
-
"uuid": "^13.0.0",
|
|
78
77
|
"ws": "^8.19.0"
|
|
79
78
|
},
|
|
80
79
|
"overrides": {
|
|
81
|
-
"fast-xml-parser": ">=4.5.4"
|
|
82
|
-
"@hono/node-server": ">=1.19.10",
|
|
83
|
-
"yauzl": ">=3.2.1"
|
|
80
|
+
"fast-xml-parser": ">=4.5.4"
|
|
84
81
|
},
|
|
85
82
|
"peerDependencies": {
|
|
86
|
-
"openclaw": ">=2026.4.
|
|
83
|
+
"openclaw": ">=2026.4.27"
|
|
87
84
|
},
|
|
88
85
|
"scripts": {
|
|
89
86
|
"build": "tsc",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
2
|
-
import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/
|
|
2
|
+
import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/run-command";
|
|
3
3
|
import { createLog } from "../../../logger.js";
|
|
4
4
|
import { getYuanbaoRuntime } from "../../../runtime.js";
|
|
5
5
|
import type {
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
import { WS_HEARTBEAT } from "../../../access/ws/types.js";
|
|
15
15
|
import { getPluginVersion } from "../../../infra/env.js";
|
|
16
16
|
import { createLog } from "../../../logger.js";
|
|
17
|
-
import { PLUGIN_ID, readInstalledVersion } from "../../commands/upgrade/utils.js";
|
|
18
17
|
import { createReplyHeartbeatController } from "../../outbound/heartbeat.js";
|
|
19
18
|
import { runWithTraceContext } from "../../trace/context.js";
|
|
20
19
|
import type { MiddlewareDescriptor } from "../types.js";
|
|
@@ -217,20 +216,8 @@ export const dispatchReply: MiddlewareDescriptor = {
|
|
|
217
216
|
}
|
|
218
217
|
|
|
219
218
|
// ⭐ Append /status version info before flush.
|
|
220
|
-
// Always prefer the on-disk authoritative version (same source as `openclaw plugins list`)
|
|
221
|
-
// so /status doesn't lie after an upgrade when the old process survived a failed
|
|
222
|
-
// gateway restart. Fall back to in-memory version only if the disk read fails.
|
|
223
219
|
if (ctx.rawBody.trim().startsWith("/status")) {
|
|
224
|
-
|
|
225
|
-
try {
|
|
226
|
-
const installed = await readInstalledVersion(PLUGIN_ID);
|
|
227
|
-
displayVersion = installed ?? getPluginVersion();
|
|
228
|
-
} catch (err) {
|
|
229
|
-
ctx.log.warn("[dispatch-reply] readInstalledVersion failed, fallback to in-memory", {
|
|
230
|
-
error: String(err),
|
|
231
|
-
});
|
|
232
|
-
displayVersion = getPluginVersion();
|
|
233
|
-
}
|
|
220
|
+
const displayVersion = getPluginVersion();
|
|
234
221
|
await queueSession.push({
|
|
235
222
|
type: "text",
|
|
236
223
|
text: `\n\n🤖 Bot: yuanbaobot(${displayVersion})`,
|
|
@@ -8,30 +8,6 @@ import { createMockCtx, createMockNext } from "../test-helpers/mock-ctx.js";
|
|
|
8
8
|
|
|
9
9
|
/** Create shared mock modules */
|
|
10
10
|
function setupMocks(t: any) {
|
|
11
|
-
const UPGRADE_COMMAND_NAMES = ["/yuanbao-upgrade", "/yuanbaobot-upgrade"] as const;
|
|
12
|
-
t.mock.module("../../commands/upgrade/index.js", {
|
|
13
|
-
namedExports: {
|
|
14
|
-
UPGRADE_COMMAND_NAMES,
|
|
15
|
-
parseUpgradeCommand(rawBody: string) {
|
|
16
|
-
const body = rawBody.trim();
|
|
17
|
-
for (const name of UPGRADE_COMMAND_NAMES) {
|
|
18
|
-
if (body === name) {
|
|
19
|
-
return { matched: true };
|
|
20
|
-
}
|
|
21
|
-
if (body.startsWith(`${name} `)) {
|
|
22
|
-
const version = body.slice(name.length + 1).trim() || undefined;
|
|
23
|
-
return { matched: true, version };
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return { matched: false };
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
t.mock.module("../../commands/upgrade/upgrade.js", {
|
|
31
|
-
namedExports: {
|
|
32
|
-
performUpgrade: async () => "",
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
11
|
t.mock.module("../../actions/text/send.js", {
|
|
36
12
|
namedExports: {
|
|
37
13
|
sendText: async () => ({ ok: true }),
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Middleware: owner guard for /
|
|
2
|
+
* Middleware: owner guard for /issue-log and other special commands.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { DeliverTarget } from "../../actions/deliver.js";
|
|
6
6
|
import { sendText } from "../../actions/text/send.js";
|
|
7
|
-
import { parseUpgradeCommand } from "../../commands/upgrade/index.js";
|
|
8
|
-
import { performUpgrade } from "../../commands/upgrade/upgrade.js";
|
|
9
7
|
import type { MiddlewareDescriptor, PipelineContext } from "../types.js";
|
|
10
8
|
|
|
11
9
|
/**
|
|
@@ -37,56 +35,6 @@ export const guardSpecialCommand: MiddlewareDescriptor = {
|
|
|
37
35
|
const { raw, rawBody, fromAccount, isGroup, groupCode } = ctx;
|
|
38
36
|
const trimmedBody = rawBody.trim();
|
|
39
37
|
|
|
40
|
-
// Upgrade command owner guard (supports /yuanbao-upgrade and /yuanbao-upgrade 1.2.3)
|
|
41
|
-
const upgradeCmd = parseUpgradeCommand(trimmedBody);
|
|
42
|
-
if (upgradeCmd.matched) {
|
|
43
|
-
ctx.log.info(`[guard-special-command] received ${trimmedBody} command`);
|
|
44
|
-
|
|
45
|
-
if (!isOwnerMessage(raw)) {
|
|
46
|
-
ctx.log.warn(`[guard-special-command] non-owner attempted ${trimmedBody}, rejected`, {
|
|
47
|
-
fromAccount,
|
|
48
|
-
});
|
|
49
|
-
const rejectText = isGroup
|
|
50
|
-
? `派中暂不支持该命令,请 Bot 创建人在私聊发送 ${trimmedBody} 进行升级`
|
|
51
|
-
: "⚠️ 您无权执行此操作,仅 Bot 创建人可以执行此操作。";
|
|
52
|
-
await sendReplyMessage(ctx, rejectText);
|
|
53
|
-
return; // Abort pipeline
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Owner check passed; send "upgrading" prompt
|
|
57
|
-
ctx.log.info(`[guard-special-command] owner triggered upgrade command ${trimmedBody}`, {
|
|
58
|
-
fromAccount,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Execute upgrade here (middleware owns more context than the plugin command handler);
|
|
62
|
-
// progress messages are streamed back via sendReplyMessage.
|
|
63
|
-
const onProgress = async (text: string): Promise<void> => {
|
|
64
|
-
try {
|
|
65
|
-
await sendReplyMessage(ctx, text);
|
|
66
|
-
} catch (err) {
|
|
67
|
-
ctx.log.error("[guard-special-command] onProgress sendReplyMessage failed", {
|
|
68
|
-
error: String(err),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const resultText = await performUpgrade(
|
|
75
|
-
ctx.config,
|
|
76
|
-
ctx.account.accountId,
|
|
77
|
-
onProgress,
|
|
78
|
-
upgradeCmd.version,
|
|
79
|
-
);
|
|
80
|
-
if (resultText) {
|
|
81
|
-
await sendReplyMessage(ctx, resultText);
|
|
82
|
-
}
|
|
83
|
-
} catch (err) {
|
|
84
|
-
ctx.log.error("[guard-special-command] performUpgrade threw", { error: String(err) });
|
|
85
|
-
await sendReplyMessage(ctx, "❌ 升级过程发生异常,请稍后重试。");
|
|
86
|
-
}
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
38
|
// /issue-log owner guard
|
|
91
39
|
if (trimmedBody.startsWith("/issue-log")) {
|
|
92
40
|
ctx.log.info("[guard-special-command] received /issue-log command");
|
package/src/channel-shared.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { yuanbaoSetupAdapter } from "./setup-core.js";
|
|
|
24
24
|
import { yuanbaoSetupWizard } from "./setup-surface.js";
|
|
25
25
|
import type { ResolvedYuanbaoAccount } from "./types.js";
|
|
26
26
|
|
|
27
|
-
export const YUANBAO_CHANNEL_ID = "
|
|
27
|
+
export const YUANBAO_CHANNEL_ID = "yuanbao" as const;
|
|
28
28
|
|
|
29
29
|
export const yuanbaoMeta = {
|
|
30
30
|
id: YUANBAO_CHANNEL_ID,
|
package/src/setup-surface.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/core";
|
|
|
8
8
|
import { resolveYuanbaoAccount } from "./accounts.js";
|
|
9
9
|
import type { YuanbaoConfig } from "./types.js";
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const YUANBAO_CHANNEL_ID = "yuanbao" as const;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Declarative setup wizard for the Yuanbao channel.
|
|
@@ -17,7 +17,7 @@ const CHANNEL = "yuanbao" as const;
|
|
|
17
17
|
* during `openclaw setup` / onboard flows.
|
|
18
18
|
*/
|
|
19
19
|
export const yuanbaoSetupWizard: ChannelSetupWizard = {
|
|
20
|
-
channel:
|
|
20
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
21
21
|
|
|
22
22
|
status: createStandardChannelSetupStatus({
|
|
23
23
|
channelLabel: "YuanBao Bot",
|
|
@@ -79,7 +79,7 @@ export const yuanbaoSetupWizard: ChannelSetupWizard = {
|
|
|
79
79
|
},
|
|
80
80
|
applySet: ({ cfg, value }) => patchTopLevelChannelConfigSection({
|
|
81
81
|
cfg,
|
|
82
|
-
channel:
|
|
82
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
83
83
|
patch: { appKey: value },
|
|
84
84
|
}),
|
|
85
85
|
},
|
|
@@ -109,7 +109,7 @@ export const yuanbaoSetupWizard: ChannelSetupWizard = {
|
|
|
109
109
|
},
|
|
110
110
|
applySet: ({ cfg, value }) => patchTopLevelChannelConfigSection({
|
|
111
111
|
cfg,
|
|
112
|
-
channel:
|
|
112
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
113
113
|
patch: { appSecret: value },
|
|
114
114
|
}),
|
|
115
115
|
},
|
|
@@ -126,7 +126,7 @@ export const yuanbaoSetupWizard: ChannelSetupWizard = {
|
|
|
126
126
|
},
|
|
127
127
|
applySet: ({ cfg, value }) => patchTopLevelChannelConfigSection({
|
|
128
128
|
cfg,
|
|
129
|
-
channel:
|
|
129
|
+
channel: YUANBAO_CHANNEL_ID,
|
|
130
130
|
patch: { name: value },
|
|
131
131
|
}),
|
|
132
132
|
},
|
|
@@ -134,7 +134,7 @@ export const yuanbaoSetupWizard: ChannelSetupWizard = {
|
|
|
134
134
|
|
|
135
135
|
finalize: ({ cfg }) => {
|
|
136
136
|
// Ensure the channel is enabled after wizard completes
|
|
137
|
-
const next = setSetupChannelEnabled(cfg,
|
|
137
|
+
const next = setSetupChannelEnabled(cfg, YUANBAO_CHANNEL_ID, true);
|
|
138
138
|
return { cfg: next };
|
|
139
139
|
},
|
|
140
140
|
|
|
@@ -146,5 +146,5 @@ export const yuanbaoSetupWizard: ChannelSetupWizard = {
|
|
|
146
146
|
],
|
|
147
147
|
},
|
|
148
148
|
|
|
149
|
-
disable: (cfg: OpenClawConfig) => setSetupChannelEnabled(cfg,
|
|
149
|
+
disable: (cfg: OpenClawConfig) => setSetupChannelEnabled(cfg, YUANBAO_CHANNEL_ID, false),
|
|
150
150
|
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { dirname } from "node:path";
|
|
2
|
-
import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/matrix";
|
|
3
|
-
export function makeEnv() {
|
|
4
|
-
const nodeBinDir = dirname(process.execPath);
|
|
5
|
-
const currentPath = process.env.PATH ?? "";
|
|
6
|
-
return {
|
|
7
|
-
...process.env,
|
|
8
|
-
PATH: currentPath.includes(nodeBinDir) ? currentPath : `${nodeBinDir}:${currentPath}`,
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export async function resolveNpmBin() {
|
|
12
|
-
try {
|
|
13
|
-
const result = await runPluginCommandWithTimeout({
|
|
14
|
-
argv: ["which", "npm"],
|
|
15
|
-
timeoutMs: 5000,
|
|
16
|
-
env: makeEnv(),
|
|
17
|
-
});
|
|
18
|
-
const resolved = result.stdout.trim();
|
|
19
|
-
if (result.code === 0 && resolved) {
|
|
20
|
-
return resolved;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
}
|
|
25
|
-
return "npm";
|
|
26
|
-
}
|
|
27
|
-
export async function resolveOpenClawBin() {
|
|
28
|
-
try {
|
|
29
|
-
const result = await runPluginCommandWithTimeout({
|
|
30
|
-
argv: ["which", "openclaw"],
|
|
31
|
-
timeoutMs: 5000,
|
|
32
|
-
env: makeEnv(),
|
|
33
|
-
});
|
|
34
|
-
const resolved = result.stdout.trim();
|
|
35
|
-
if (result.code === 0 && resolved) {
|
|
36
|
-
return resolved;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
}
|
|
41
|
-
return "openclaw";
|
|
42
|
-
}
|
|
43
|
-
export function nodeExecPath() {
|
|
44
|
-
return process.execPath;
|
|
45
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { OpenClawPluginCommandDefinition } from "openclaw/plugin-sdk/core";
|
|
2
|
-
export declare const UPGRADE_COMMAND_NAMES: readonly ["/yuanbao-upgrade", "/yuanbaobot-upgrade"];
|
|
3
|
-
export declare function parseUpgradeCommand(rawBody: string): {
|
|
4
|
-
matched: boolean;
|
|
5
|
-
version?: string;
|
|
6
|
-
};
|
|
7
|
-
export declare const yuanbaoUpgradeCommand: OpenClawPluginCommandDefinition;
|
|
8
|
-
export declare const yuanbaobotUpgradeCommand: OpenClawPluginCommandDefinition;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { performUpgrade } from "./upgrade.js";
|
|
2
|
-
import { registerPluginCommand } from "../command-sync/index.js";
|
|
3
|
-
export const UPGRADE_COMMAND_NAMES = ["/yuanbao-upgrade", "/yuanbaobot-upgrade"];
|
|
4
|
-
export function parseUpgradeCommand(rawBody) {
|
|
5
|
-
const body = rawBody.trim();
|
|
6
|
-
for (const name of UPGRADE_COMMAND_NAMES) {
|
|
7
|
-
if (body === name) {
|
|
8
|
-
return { matched: true };
|
|
9
|
-
}
|
|
10
|
-
if (body.startsWith(`${name} `)) {
|
|
11
|
-
const version = body.slice(name.length + 1).trim() || undefined;
|
|
12
|
-
return { matched: true, version };
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return { matched: false };
|
|
16
|
-
}
|
|
17
|
-
function makeUpgradeCommand(name, description) {
|
|
18
|
-
return {
|
|
19
|
-
name,
|
|
20
|
-
description,
|
|
21
|
-
requireAuth: false,
|
|
22
|
-
acceptsArgs: true,
|
|
23
|
-
handler: async (ctx) => {
|
|
24
|
-
const requested = ctx.args?.trim() || undefined;
|
|
25
|
-
const text = await performUpgrade(ctx.config, ctx.accountId, undefined, requested);
|
|
26
|
-
return { text };
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
export const yuanbaoUpgradeCommand = makeUpgradeCommand(UPGRADE_COMMAND_NAMES[0].slice(1), "升级 yuanbao 插件到最新正式版本");
|
|
31
|
-
export const yuanbaobotUpgradeCommand = makeUpgradeCommand(UPGRADE_COMMAND_NAMES[1].slice(1), "升级 yuanbao 插件到最新正式版本(别名)");
|
|
32
|
-
registerPluginCommand(yuanbaoUpgradeCommand.name, yuanbaoUpgradeCommand.description);
|
|
33
|
-
registerPluginCommand(yuanbaobotUpgradeCommand.name, yuanbaobotUpgradeCommand.description);
|