Files
wechat-access-unqclawed/auth/state-store.ts
HenryXiaoYang ba754ccc31 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)
2026-03-10 02:29:06 +08:00

49 lines
1.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file state-store.ts
* @description 登录态持久化存储
*
* 将 token 保存到本地文件,下次启动时自动加载,避免重复扫码。
* 文件权限设为 0o600仅当前用户可读写。
*/
import { readFileSync, writeFileSync, unlinkSync, mkdirSync, chmodSync } from "node:fs";
import { join, dirname } from "node:path";
import { homedir } from "node:os";
import type { PersistedAuthState } from "./types.js";
const DEFAULT_STATE_PATH = join(homedir(), ".openclaw", "wechat-access-auth.json");
export const getStatePath = (customPath?: string): string =>
customPath || DEFAULT_STATE_PATH;
export const loadState = (customPath?: string): PersistedAuthState | null => {
const filePath = getStatePath(customPath);
try {
const raw = readFileSync(filePath, "utf-8");
return JSON.parse(raw) as PersistedAuthState;
} catch {
return null;
}
};
export const saveState = (state: PersistedAuthState, customPath?: string): void => {
const filePath = getStatePath(customPath);
mkdirSync(dirname(filePath), { recursive: true });
writeFileSync(filePath, JSON.stringify(state, null, 2), { encoding: "utf-8", mode: 0o600 });
// 确保已有文件也收紧权限
try {
chmodSync(filePath, 0o600);
} catch {
// Windows 等平台可能不支持 chmod忽略
}
};
export const clearState = (customPath?: string): void => {
const filePath = getStatePath(customPath);
try {
unlinkSync(filePath);
} catch {
// file not found — ignore
}
};