






















@@ -0,0 +1,113 @@
1+import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
2+import type {
3+OpenClawPluginApi,
4+OpenClawPluginCommandDefinition,
5+PluginCommandContext,
6+} from "openclaw/plugin-sdk/plugin-entry";
7+import { describe, expect, it } from "vitest";
8+import {
9+getWrittenQQBotConfig,
10+installCommandRuntime,
11+} from "../../engine/commands/slash-command-test-support.js";
12+import { ensurePlatformAdapter } from "../bootstrap.js";
13+import { registerQQBotFrameworkCommands } from "./framework-registration.js";
14+15+function createConfig(): OpenClawConfig {
16+return {
17+channels: {
18+qqbot: {
19+appId: "app",
20+allowFrom: ["TRUSTED_OPENID"],
21+streaming: false,
22+accounts: {
23+default: {
24+allowFrom: ["TRUSTED_OPENID"],
25+streaming: false,
26+},
27+},
28+},
29+},
30+};
31+}
32+33+function registerCommands(): OpenClawPluginCommandDefinition[] {
34+ensurePlatformAdapter();
35+const commands: OpenClawPluginCommandDefinition[] = [];
36+const api = {
37+logger: {},
38+registerCommand: (command: OpenClawPluginCommandDefinition) => {
39+commands.push(command);
40+},
41+} as unknown as OpenClawPluginApi;
42+43+registerQQBotFrameworkCommands(api);
44+return commands;
45+}
46+47+function findCommand(
48+commands: OpenClawPluginCommandDefinition[],
49+name: string,
50+): OpenClawPluginCommandDefinition {
51+const command = commands.find((entry) => entry.name === name);
52+expect(command).toBeDefined();
53+return command as OpenClawPluginCommandDefinition;
54+}
55+56+function createCommandContext(
57+config: OpenClawConfig,
58+from: string | undefined,
59+): PluginCommandContext {
60+return {
61+senderId: "TRUSTED_OPENID",
62+channel: "qqbot",
63+isAuthorizedSender: true,
64+args: "on",
65+commandBody: "/bot-streaming on",
66+ config,
67+ from,
68+requestConversationBinding: async () => undefined,
69+detachConversationBinding: async () => ({ removed: false }),
70+getCurrentConversationBinding: async () => null,
71+} as unknown as PluginCommandContext;
72+}
73+74+describe("registerQQBotFrameworkCommands", () => {
75+it("registers bot-streaming as an auth-gated framework command", () => {
76+const command = findCommand(registerCommands(), "bot-streaming");
77+78+expect(command.requireAuth).toBe(true);
79+});
80+81+it("preserves the private-chat guard for bot-streaming on generic framework calls", async () => {
82+const config = createConfig();
83+const writes: OpenClawConfig[] = [];
84+installCommandRuntime(config, writes);
85+const command = findCommand(registerCommands(), "bot-streaming");
86+87+const missingFromResult = await command.handler(createCommandContext(config, undefined));
88+const nonQQBotResult = await command.handler(createCommandContext(config, "generic:dm:user"));
89+const groupResult = await command.handler(
90+createCommandContext(config, "qqbot:group:GROUP_OPENID"),
91+);
92+93+expect(missingFromResult).toEqual({ text: "💡 请在私聊中使用此指令" });
94+expect(nonQQBotResult).toEqual({ text: "💡 请在私聊中使用此指令" });
95+expect(groupResult).toEqual({ text: "💡 请在私聊中使用此指令" });
96+expect(writes).toHaveLength(0);
97+});
98+99+it("allows bot-streaming on explicit QQBot private-chat framework calls", async () => {
100+const config = createConfig();
101+const writes: OpenClawConfig[] = [];
102+installCommandRuntime(config, writes);
103+const command = findCommand(registerCommands(), "bot-streaming");
104+105+const result = await command.handler(createCommandContext(config, "qqbot:c2c:TRUSTED_OPENID"));
106+107+const qqbot = getWrittenQQBotConfig(writes[0]);
108+expect(result).toMatchObject({ text: expect.stringContaining("已开启") });
109+expect(writes).toHaveLength(1);
110+expect(qqbot?.streaming).toBe(true);
111+expect(qqbot?.accounts?.default?.streaming).toBe(true);
112+});
113+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。