@elizaos/plugin-wechat 2.0.0-alpha.537 → 2.0.3-beta.5

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.
@@ -1,121 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from "vitest";
2
- import { WechatChannel } from "./channel";
3
- import type { WechatMessageContext } from "./types";
4
-
5
- function createConfig() {
6
- return {
7
- accounts: {
8
- main: {
9
- apiKey: "main-key",
10
- proxyUrl: "https://proxy.example.com",
11
- },
12
- secondary: {
13
- apiKey: "secondary-key",
14
- proxyUrl: "https://proxy.example.com",
15
- },
16
- },
17
- };
18
- }
19
-
20
- function createMessage(
21
- overrides: Partial<WechatMessageContext> = {},
22
- ): WechatMessageContext {
23
- return {
24
- id: "wechat-msg-1",
25
- type: "text",
26
- sender: "wxid-alice",
27
- recipient: "wxid-agent",
28
- content: "hello agent",
29
- timestamp: 123,
30
- raw: {},
31
- ...overrides,
32
- };
33
- }
34
-
35
- afterEach(() => {
36
- vi.useRealTimers();
37
- vi.restoreAllMocks();
38
- });
39
-
40
- describe("WechatChannel", () => {
41
- it("routes inbound messages to the matching account bot", () => {
42
- const channel = new WechatChannel({
43
- config: createConfig(),
44
- onMessage: vi.fn(),
45
- });
46
- const mainBot = { handleIncoming: vi.fn(), stop: vi.fn() };
47
- const secondaryBot = { handleIncoming: vi.fn(), stop: vi.fn() };
48
-
49
- (
50
- channel as unknown as {
51
- accounts: Map<
52
- string,
53
- { client: object; dispatcher: object; bot: typeof mainBot }
54
- >;
55
- routeIncoming: (accountId: string, msg: WechatMessageContext) => void;
56
- }
57
- ).accounts.set("main", {
58
- client: {},
59
- dispatcher: {},
60
- bot: mainBot,
61
- });
62
- (
63
- channel as unknown as {
64
- accounts: Map<
65
- string,
66
- { client: object; dispatcher: object; bot: typeof secondaryBot }
67
- >;
68
- }
69
- ).accounts.set("secondary", {
70
- client: {},
71
- dispatcher: {},
72
- bot: secondaryBot,
73
- });
74
-
75
- (
76
- channel as unknown as {
77
- routeIncoming: (accountId: string, msg: WechatMessageContext) => void;
78
- }
79
- ).routeIncoming("secondary", createMessage());
80
-
81
- expect(mainBot.handleIncoming).not.toHaveBeenCalled();
82
- expect(secondaryBot.handleIncoming).toHaveBeenCalledWith(
83
- expect.objectContaining({ id: "wechat-msg-1" }),
84
- );
85
- });
86
-
87
- it("times out login when QR verification never completes", async () => {
88
- vi.useFakeTimers();
89
- vi.spyOn(console, "log").mockImplementation(() => undefined);
90
-
91
- const channel = new WechatChannel({
92
- config: createConfig(),
93
- onMessage: vi.fn(),
94
- });
95
- const client = {
96
- getStatus: vi.fn().mockResolvedValue({
97
- valid: true,
98
- loginState: "waiting",
99
- }),
100
- getQRCode: vi.fn().mockResolvedValue("https://proxy.example.com/qr"),
101
- checkLogin: vi.fn().mockResolvedValue({ status: "waiting" }),
102
- };
103
-
104
- (
105
- channel as unknown as { abortController: AbortController | null }
106
- ).abortController = new AbortController();
107
-
108
- const loginPromise = (
109
- channel as unknown as {
110
- ensureLoggedIn: (
111
- accountId: string,
112
- client: typeof client,
113
- ) => Promise<void>;
114
- }
115
- ).ensureLoggedIn("main", client);
116
- const rejection = expect(loginPromise).rejects.toThrow(/timed out/i);
117
-
118
- await vi.advanceTimersByTimeAsync(5 * 60_000 + 5_000);
119
- await rejection;
120
- });
121
- });
@@ -1,24 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import path from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { describe, expect, it } from "vitest";
5
-
6
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
-
8
- describe("proxy-client 429 body consumption", () => {
9
- it("consumes response body before retry on 429", () => {
10
- const source = readFileSync(
11
- path.join(__dirname, "proxy-client.ts"),
12
- "utf-8",
13
- );
14
-
15
- const idx = source.indexOf("res.status === 429");
16
- expect(idx).toBeGreaterThan(-1);
17
-
18
- const block = source.slice(idx, idx + 500);
19
- expect(block).toContain("res.text()");
20
- expect(block.indexOf("res.text()")).toBeLessThan(
21
- block.indexOf("continue;"),
22
- );
23
- });
24
- });
@@ -1,46 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from "vitest";
2
- import { ProxyClient } from "./proxy-client";
3
-
4
- describe("ProxyClient", () => {
5
- afterEach(() => {
6
- vi.restoreAllMocks();
7
- });
8
-
9
- it("rejects insecure proxy URLs", () => {
10
- expect(
11
- () =>
12
- new ProxyClient({
13
- id: "main",
14
- apiKey: "main-key",
15
- proxyUrl: "http://127.0.0.1:8787",
16
- deviceType: "ipad",
17
- webhookPort: 18790,
18
- }),
19
- ).toThrow("proxyUrl must use https://");
20
- });
21
-
22
- it("sends X-Device-Type header in requests", async () => {
23
- const client = new ProxyClient({
24
- id: "test-account",
25
- apiKey: "test-key",
26
- proxyUrl: "https://proxy.example.com",
27
- deviceType: "mac",
28
- webhookPort: 18790,
29
- });
30
-
31
- let capturedHeaders: Record<string, string> = {};
32
- vi.spyOn(globalThis, "fetch").mockImplementation(async (_url, init) => {
33
- capturedHeaders = (init?.headers ?? {}) as Record<string, string>;
34
- return new Response(
35
- JSON.stringify({ code: 1000, data: { status: "logged_in" } }),
36
- { status: 200, headers: { "content-type": "application/json" } },
37
- );
38
- });
39
-
40
- await client.getStatus();
41
-
42
- expect(capturedHeaders["X-Device-Type"]).toBe("mac");
43
- expect(capturedHeaders["X-Account-ID"]).toBe("test-account");
44
- expect(capturedHeaders["X-API-Key"]).toBe("test-key");
45
- });
46
- });
@@ -1,135 +0,0 @@
1
- import type { Content } from "@elizaos/core";
2
- import { describe, expect, it, vi } from "vitest";
3
- import { deliverIncomingWechatMessage } from "./runtime-bridge";
4
- import type { WechatMessageContext } from "./types";
5
-
6
- function createMessage(
7
- overrides: Partial<WechatMessageContext> = {},
8
- ): WechatMessageContext {
9
- return {
10
- id: "wechat-msg-1",
11
- type: "text",
12
- sender: "wxid-alice",
13
- recipient: "wxid-agent",
14
- content: "hello agent",
15
- timestamp: 123,
16
- raw: { type: 60001 },
17
- ...overrides,
18
- };
19
- }
20
-
21
- function createRuntime(overrides: Record<string, unknown> = {}) {
22
- return {
23
- agentId: "00000000-0000-0000-0000-000000000001",
24
- ensureConnection: vi.fn().mockResolvedValue(undefined),
25
- createMemory: vi.fn().mockResolvedValue(undefined),
26
- emitEvent: vi.fn().mockResolvedValue(undefined),
27
- logger: {
28
- warn: vi.fn(),
29
- error: vi.fn(),
30
- },
31
- ...overrides,
32
- };
33
- }
34
-
35
- describe("deliverIncomingWechatMessage", () => {
36
- it("routes incoming messages through the runtime message API and reply callback", async () => {
37
- const sendText = vi.fn().mockResolvedValue(undefined);
38
- const sendMessage = vi.fn(
39
- async (
40
- _runtime: unknown,
41
- _memory: unknown,
42
- options?: {
43
- onResponse?: (content: Content) => Promise<unknown>;
44
- },
45
- ) => {
46
- await options?.onResponse?.({ text: "reply from agent" } as Content);
47
- return { responseContent: { text: "reply from agent" } as Content };
48
- },
49
- );
50
- const runtime = createRuntime({
51
- elizaOS: { sendMessage },
52
- });
53
-
54
- await deliverIncomingWechatMessage({
55
- runtime,
56
- accountId: "main",
57
- message: createMessage(),
58
- sendText,
59
- });
60
-
61
- expect(runtime.ensureConnection).toHaveBeenCalledWith(
62
- expect.objectContaining({
63
- entityId: expect.any(String),
64
- roomId: expect.any(String),
65
- userName: "wxid-alice",
66
- userId: "wxid-alice",
67
- source: "wechat",
68
- channelId: "wxid-alice",
69
- worldName: "WeChat",
70
- }),
71
- );
72
- expect(sendMessage).toHaveBeenCalledTimes(1);
73
-
74
- const [, memory] = sendMessage.mock.calls[0];
75
- expect(memory).toEqual(
76
- expect.objectContaining({
77
- content: expect.objectContaining({
78
- text: "hello agent",
79
- source: "wechat",
80
- channelType: "DM",
81
- }),
82
- metadata: expect.objectContaining({
83
- type: "message",
84
- source: "wechat",
85
- provider: "wechat",
86
- fromId: "wxid-alice",
87
- wechat: expect.objectContaining({
88
- userId: "wxid-alice",
89
- messageId: "wechat-msg-1",
90
- }),
91
- }),
92
- }),
93
- );
94
-
95
- expect(sendText).toHaveBeenCalledTimes(1);
96
- expect(sendText).toHaveBeenCalledWith(
97
- "main",
98
- "wxid-alice",
99
- "reply from agent",
100
- );
101
- expect(runtime.createMemory).toHaveBeenCalledWith(
102
- expect.objectContaining({
103
- content: expect.objectContaining({
104
- text: "reply from agent",
105
- source: "wechat",
106
- channelType: "DM",
107
- }),
108
- }),
109
- "messages",
110
- );
111
- });
112
-
113
- it("falls back to MESSAGE_RECEIVED events when no message pipeline is available", async () => {
114
- const runtime = createRuntime();
115
-
116
- await deliverIncomingWechatMessage({
117
- runtime,
118
- accountId: "main",
119
- message: createMessage(),
120
- sendText: vi.fn().mockResolvedValue(undefined),
121
- });
122
-
123
- expect(runtime.emitEvent).toHaveBeenCalledWith(["MESSAGE_RECEIVED"], {
124
- runtime,
125
- message: expect.objectContaining({
126
- content: expect.objectContaining({
127
- text: "hello agent",
128
- source: "wechat",
129
- }),
130
- }),
131
- callback: expect.any(Function),
132
- source: "wechat",
133
- });
134
- });
135
- });