feat: add WeChat QR code login and AGP WebSocket channel plugin
- Auth module: WeChat OAuth2 scan-to-login flow with terminal QR code - Token persistence to ~/.openclaw/wechat-access-auth.json (chmod 600) - Token resolution: config > saved state > interactive login - Invite code verification (configurable bypass) - Production/test environment support - AGP WebSocket client with heartbeat, reconnect, wake detection - Message handler: Agent dispatch with streaming text and tool calls - Random device GUID generation (persisted, no real machine ID)
This commit is contained in:
49
common/agent-events.ts
Normal file
49
common/agent-events.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import type { onAgentEvent as OnAgentEventType } from "openclaw/plugin-sdk";
|
||||
|
||||
export type AgentEventStream = "lifecycle" | "tool" | "assistant" | "error" | (string & {});
|
||||
|
||||
export type AgentEventPayload = {
|
||||
runId: string;
|
||||
seq: number;
|
||||
stream: AgentEventStream;
|
||||
ts: number;
|
||||
data: Record<string, unknown>;
|
||||
sessionKey?: string;
|
||||
};
|
||||
|
||||
// 动态导入,兼容 openclaw 未导出该函数的情况
|
||||
let _onAgentEvent: typeof OnAgentEventType | undefined;
|
||||
|
||||
// SDK 加载完成的 Promise,确保只加载一次
|
||||
const sdkReady: Promise<typeof OnAgentEventType | undefined> = (async () => {
|
||||
try {
|
||||
const sdk = await import("openclaw/plugin-sdk");
|
||||
if (typeof sdk.onAgentEvent === "function") {
|
||||
_onAgentEvent = sdk.onAgentEvent;
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return _onAgentEvent;
|
||||
})();
|
||||
|
||||
/**
|
||||
* 注册 Agent 事件监听器。
|
||||
*
|
||||
* 修复了原版的时序问题:原版使用 loadOnAgentEvent().then() 异步注册,
|
||||
* 导致在 dispatchReplyWithBufferedBlockDispatcher 调用之前注册的监听器
|
||||
* 实际上在 Agent 开始产生事件时还未真正挂载,造成事件全部丢失。
|
||||
*
|
||||
* 新版通过 await sdkReady 确保 SDK 加载完成后再注册监听器,
|
||||
* 调用方需要 await 此函数返回的 Promise,再调用 dispatchReply。
|
||||
*/
|
||||
export const onAgentEvent = async (
|
||||
listener: Parameters<typeof OnAgentEventType>[0]
|
||||
): Promise<() => boolean> => {
|
||||
const fn = await sdkReady;
|
||||
if (fn) {
|
||||
const unsubscribe = fn(listener);
|
||||
return unsubscribe;
|
||||
}
|
||||
return () => false;
|
||||
};
|
||||
Reference in New Issue
Block a user