mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
144 lines
4.4 KiB
TypeScript
144 lines
4.4 KiB
TypeScript
import { createPluginRuntimeMock } from "openclaw/plugin-sdk/channel-test-helpers";
|
|
import type { PluginRuntime } from "openclaw/plugin-sdk/core";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { handleClickClackInbound } from "./inbound.js";
|
|
import { setClickClackRuntime } from "./runtime.js";
|
|
import type { CoreConfig, ResolvedClickClackAccount } from "./types.js";
|
|
|
|
const sendClickClackTextMock = vi.hoisted(() => vi.fn());
|
|
|
|
type LlmCompleteMock = ReturnType<
|
|
typeof vi.fn<
|
|
(params: {
|
|
agentId?: string;
|
|
model?: string;
|
|
maxTokens?: number;
|
|
purpose?: string;
|
|
messages?: unknown[];
|
|
}) => Promise<unknown>
|
|
>
|
|
>;
|
|
|
|
vi.mock("./outbound.js", () => ({
|
|
sendClickClackText: sendClickClackTextMock,
|
|
}));
|
|
|
|
function createRuntime(): PluginRuntime {
|
|
return createPluginRuntimeMock({
|
|
agent: {
|
|
runEmbeddedPiAgent: vi.fn().mockResolvedValue({
|
|
payloads: [{ text: "service bot online" }],
|
|
meta: {},
|
|
}),
|
|
},
|
|
channel: {
|
|
routing: {
|
|
resolveAgentRoute({
|
|
accountId,
|
|
peer,
|
|
}: Parameters<PluginRuntime["channel"]["routing"]["resolveAgentRoute"]>[0]) {
|
|
return {
|
|
agentId: "main",
|
|
channel: "clickclack",
|
|
accountId: accountId ?? "default",
|
|
sessionKey: `agent:main:clickclack:${peer?.kind ?? "channel"}:${peer?.id ?? "general"}`,
|
|
mainSessionKey: "agent:main:main",
|
|
lastRoutePolicy: "session",
|
|
matchedBy: "default",
|
|
};
|
|
},
|
|
buildAgentSessionKey({
|
|
agentId,
|
|
channel,
|
|
accountId,
|
|
peer,
|
|
}: Parameters<PluginRuntime["channel"]["routing"]["buildAgentSessionKey"]>[0]) {
|
|
return `agent:${agentId}:${channel}:${accountId ?? "default"}:${peer?.kind ?? "channel"}:${peer?.id ?? "general"}`;
|
|
},
|
|
},
|
|
},
|
|
llm: {
|
|
complete: vi.fn().mockResolvedValue({
|
|
text: "service bot online",
|
|
provider: "openai",
|
|
model: "gpt-5.4-mini",
|
|
agentId: "service-bot",
|
|
usage: {},
|
|
audit: {
|
|
caller: { kind: "plugin", id: "clickclack" },
|
|
},
|
|
}),
|
|
},
|
|
} as unknown as PluginRuntime);
|
|
}
|
|
|
|
describe("handleClickClackInbound", () => {
|
|
it("runs model-mode bot accounts without tools and posts the bot reply", async () => {
|
|
sendClickClackTextMock.mockReset();
|
|
const runtime = createRuntime();
|
|
setClickClackRuntime(runtime);
|
|
const cfg = {
|
|
agents: {
|
|
defaults: {
|
|
model: "openai/gpt-5.4-mini",
|
|
},
|
|
},
|
|
} satisfies CoreConfig;
|
|
const account = {
|
|
accountId: "service",
|
|
enabled: true,
|
|
configured: true,
|
|
baseUrl: "http://127.0.0.1:8080",
|
|
token: "ccb_service",
|
|
workspace: "wsp_1",
|
|
agentId: "service-bot",
|
|
replyMode: "model",
|
|
model: "openai/gpt-5.4-mini",
|
|
senderIsOwner: false,
|
|
toolsAllow: [],
|
|
defaultTo: "channel:general",
|
|
allowFrom: ["*"],
|
|
reconnectMs: 1_500,
|
|
config: {},
|
|
} satisfies ResolvedClickClackAccount;
|
|
|
|
await handleClickClackInbound({
|
|
account,
|
|
config: cfg,
|
|
message: {
|
|
id: "msg_1",
|
|
workspace_id: "wsp_1",
|
|
channel_id: "chn_1",
|
|
author_id: "usr_human",
|
|
thread_root_id: "msg_1",
|
|
body: "hello bot",
|
|
body_format: "markdown",
|
|
created_at: "2026-05-09T12:00:00.000Z",
|
|
author: {
|
|
id: "usr_human",
|
|
kind: "human",
|
|
display_name: "Peter",
|
|
handle: "steipete",
|
|
avatar_url: "",
|
|
created_at: "2026-05-09T12:00:00.000Z",
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(runtime.channel.turn.runPrepared).not.toHaveBeenCalled();
|
|
expect(runtime.agent.runEmbeddedPiAgent).not.toHaveBeenCalled();
|
|
const completionRequest = (runtime.llm.complete as LlmCompleteMock).mock.calls[0]?.[0];
|
|
expect(completionRequest?.agentId).toBe("service-bot");
|
|
expect(completionRequest?.model).toBe("openai/gpt-5.4-mini");
|
|
expect(completionRequest?.maxTokens).toBe(96);
|
|
expect(completionRequest?.purpose).toBe("clickclack bot reply");
|
|
expect(completionRequest?.messages).toEqual([{ role: "user", content: "hello bot" }]);
|
|
|
|
const sendRequest = sendClickClackTextMock.mock.calls[0]?.[0];
|
|
expect(sendRequest?.accountId).toBe("service");
|
|
expect(sendRequest?.to).toBe("channel:chn_1");
|
|
expect(sendRequest?.text).toBe("service bot online");
|
|
expect(sendRequest?.replyToId).toBe("msg_1");
|
|
});
|
|
});
|