mirror of https://github.com/openclaw/openclaw.git
fix: honor qqbot default account config
This commit is contained in:
parent
b929a4c27d
commit
acfa09679c
|
|
@ -5,7 +5,11 @@ import { validateJsonSchemaValue } from "../../../src/plugins/schema-validator.j
|
|||
import { qqbotPlugin } from "./channel.js";
|
||||
import { qqbotSetupPlugin } from "./channel.setup.js";
|
||||
import { QQBotConfigSchema } from "./config-schema.js";
|
||||
import { DEFAULT_ACCOUNT_ID, resolveQQBotAccount } from "./config.js";
|
||||
import {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
resolveDefaultQQBotAccountId,
|
||||
resolveQQBotAccount,
|
||||
} from "./config.js";
|
||||
|
||||
describe("qqbot config", () => {
|
||||
it("accepts top-level speech overrides in the manifest schema", () => {
|
||||
|
|
@ -62,6 +66,23 @@ describe("qqbot config", () => {
|
|||
expect(result.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("honors configured defaultAccount when resolving the default QQ Bot account id", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
qqbot: {
|
||||
defaultAccount: "bot2",
|
||||
accounts: {
|
||||
bot2: {
|
||||
appId: "654321",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
expect(resolveDefaultQQBotAccountId(cfg)).toBe("bot2");
|
||||
});
|
||||
|
||||
it("accepts SecretRef-backed credentials in the runtime schema", () => {
|
||||
const parsed = QQBotConfigSchema.safeParse({
|
||||
defaultAccount: "bot2",
|
||||
|
|
@ -142,6 +163,30 @@ describe("qqbot config", () => {
|
|||
expect(resolved.config.upgradeMode).toBe("hot-reload");
|
||||
});
|
||||
|
||||
it("uses configured defaultAccount when accountId is omitted", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
qqbot: {
|
||||
defaultAccount: "bot2",
|
||||
accounts: {
|
||||
bot2: {
|
||||
appId: "654321",
|
||||
clientSecret: "secret-value",
|
||||
name: "Bot Two",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const resolved = resolveQQBotAccount(cfg);
|
||||
|
||||
expect(resolved.accountId).toBe("bot2");
|
||||
expect(resolved.appId).toBe("654321");
|
||||
expect(resolved.clientSecret).toBe("secret-value");
|
||||
expect(resolved.name).toBe("Bot Two");
|
||||
});
|
||||
|
||||
it("rejects unresolved SecretRefs on runtime resolution", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,15 @@ export const DEFAULT_ACCOUNT_ID = "default";
|
|||
|
||||
interface QQBotChannelConfig extends QQBotAccountConfig {
|
||||
accounts?: Record<string, QQBotAccountConfig>;
|
||||
defaultAccount?: string;
|
||||
}
|
||||
|
||||
function normalizeConfiguredDefaultAccountId(raw: unknown): string | null {
|
||||
if (typeof raw !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = raw.trim().toLowerCase();
|
||||
return trimmed ? trimmed : null;
|
||||
}
|
||||
|
||||
function normalizeQQBotAccountConfig(account: QQBotAccountConfig | undefined): QQBotAccountConfig {
|
||||
|
|
@ -51,6 +60,14 @@ export function listQQBotAccountIds(cfg: OpenClawConfig): string[] {
|
|||
/** Resolve the default QQBot account ID. */
|
||||
export function resolveDefaultQQBotAccountId(cfg: OpenClawConfig): string {
|
||||
const qqbot = cfg.channels?.qqbot as QQBotChannelConfig | undefined;
|
||||
const configuredDefaultAccountId = normalizeConfiguredDefaultAccountId(qqbot?.defaultAccount);
|
||||
if (
|
||||
configuredDefaultAccountId &&
|
||||
(configuredDefaultAccountId === DEFAULT_ACCOUNT_ID ||
|
||||
Boolean(qqbot?.accounts?.[configuredDefaultAccountId]?.appId))
|
||||
) {
|
||||
return configuredDefaultAccountId;
|
||||
}
|
||||
if (qqbot?.appId || process.env.QQBOT_APP_ID) {
|
||||
return DEFAULT_ACCOUNT_ID;
|
||||
}
|
||||
|
|
@ -69,7 +86,7 @@ export function resolveQQBotAccount(
|
|||
accountId?: string | null,
|
||||
opts?: { allowUnresolvedSecretRef?: boolean },
|
||||
): ResolvedQQBotAccount {
|
||||
const resolvedAccountId = accountId ?? DEFAULT_ACCOUNT_ID;
|
||||
const resolvedAccountId = accountId ?? resolveDefaultQQBotAccountId(cfg);
|
||||
const qqbot = cfg.channels?.qqbot as QQBotChannelConfig | undefined;
|
||||
|
||||
let accountConfig: QQBotAccountConfig = {};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { sendProactive } from "./proactive.js";
|
||||
|
||||
const apiMocks = vi.hoisted(() => ({
|
||||
getAccessToken: vi.fn(),
|
||||
sendProactiveC2CMessage: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./api.js", () => ({
|
||||
getAccessToken: apiMocks.getAccessToken,
|
||||
sendProactiveC2CMessage: apiMocks.sendProactiveC2CMessage,
|
||||
sendProactiveGroupMessage: vi.fn(),
|
||||
sendChannelMessage: vi.fn(),
|
||||
sendC2CImageMessage: vi.fn(),
|
||||
sendGroupImageMessage: vi.fn(),
|
||||
}));
|
||||
|
||||
describe("qqbot proactive sends", () => {
|
||||
beforeEach(() => {
|
||||
apiMocks.getAccessToken.mockReset();
|
||||
apiMocks.sendProactiveC2CMessage.mockReset();
|
||||
});
|
||||
|
||||
it("uses configured defaultAccount when accountId is omitted", async () => {
|
||||
apiMocks.getAccessToken.mockResolvedValue("access-token");
|
||||
apiMocks.sendProactiveC2CMessage.mockResolvedValue({
|
||||
id: "msg-1",
|
||||
timestamp: 123,
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
channels: {
|
||||
qqbot: {
|
||||
defaultAccount: "bot2",
|
||||
accounts: {
|
||||
bot2: {
|
||||
appId: "654321",
|
||||
clientSecret: "secret-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const result = await sendProactive(
|
||||
{
|
||||
to: "openid-1",
|
||||
text: "hello",
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
|
||||
expect(apiMocks.getAccessToken).toHaveBeenCalledWith("654321", "secret-value");
|
||||
expect(apiMocks.sendProactiveC2CMessage).toHaveBeenCalledWith(
|
||||
"654321",
|
||||
"access-token",
|
||||
"openid-1",
|
||||
"hello",
|
||||
);
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.messageId).toBe("msg-1");
|
||||
});
|
||||
});
|
||||
|
|
@ -58,7 +58,7 @@ import {
|
|||
sendC2CImageMessage,
|
||||
sendGroupImageMessage,
|
||||
} from "./api.js";
|
||||
import { resolveQQBotAccount } from "./config.js";
|
||||
import { resolveDefaultQQBotAccountId, resolveQQBotAccount } from "./config.js";
|
||||
|
||||
/** Look up a known user entry (adapter for the old proactive API shape). */
|
||||
export function getKnownUser(
|
||||
|
|
@ -98,7 +98,13 @@ export async function sendProactive(
|
|||
options: ProactiveSendOptions,
|
||||
cfg: OpenClawConfig,
|
||||
): Promise<ProactiveSendResult> {
|
||||
const { to, text, type = "c2c", imageUrl, accountId = "default" } = options;
|
||||
const {
|
||||
to,
|
||||
text,
|
||||
type = "c2c",
|
||||
imageUrl,
|
||||
accountId = resolveDefaultQQBotAccountId(cfg),
|
||||
} = options;
|
||||
|
||||
const account = resolveQQBotAccount(cfg, accountId);
|
||||
|
||||
|
|
@ -174,7 +180,7 @@ export async function sendBulkProactiveMessage(
|
|||
text: string,
|
||||
type: "c2c" | "group",
|
||||
cfg: OpenClawConfig,
|
||||
accountId = "default",
|
||||
accountId = resolveDefaultQQBotAccountId(cfg),
|
||||
): Promise<Array<{ to: string; result: ProactiveSendResult }>> {
|
||||
const results: Array<{ to: string; result: ProactiveSendResult }> = [];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue