@lingyao037/openclaw-lingyao-cli 0.3.5 → 0.4.0
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.
- package/dist/{accounts-Bkwmg14Q.d.ts → accounts-AwHXj7VB.d.ts} +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/index.d.ts +258 -562
- package/dist/index.js +162 -59
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts","../src/adapters/config.ts","../src/adapters/gateway.ts","../src/adapters/status.ts","../src/adapters/directory.ts","../src/adapters/messaging.ts","../src/adapters/outbound.ts","../src/orchestrator.ts","../src/types.ts","../src/server-client.ts","../src/websocket-client.ts","../src/accounts.ts","../src/crypto.ts","../src/bot.ts","../src/probe.ts","../src/metrics.ts","../src/errors.ts","../src/channel.ts","../src/token.ts","../src/config-schema.ts","../src/index.ts"],"sourcesContent":["import type { LingyaoRuntime } from \"./types.js\";\n\n/**\n * Global runtime instance storage\n */\nlet globalRuntime: LingyaoRuntime | null = null;\n\n/**\n * Set the global runtime instance\n */\nexport function setRuntime(runtime: LingyaoRuntime): void {\n globalRuntime = runtime;\n}\n\n/**\n * Get the global runtime instance\n */\nexport function getRuntime(): LingyaoRuntime {\n if (!globalRuntime) {\n throw new Error(\"Runtime not initialized. Call setRuntime() first.\");\n }\n return globalRuntime;\n}\n\n/**\n * Check if runtime is initialized\n */\nexport function hasRuntime(): boolean {\n return globalRuntime !== null;\n}\n\n/**\n * Clear the global runtime instance\n */\nexport function clearRuntime(): void {\n globalRuntime = null;\n}\n","/**\n * Config Adapter - Account resolution, config validation\n *\n * serverUrl is NOT exposed to users — hardcoded as LINGYAO_SERVER_URL.\n */\n\nimport type { LingyaoAccountConfig } from '../types.js';\n\n/**\n * OpenClawConfig - compatible with SDK interface\n */\nexport interface OpenClawConfig {\n channels?: Record<string, unknown>;\n}\n\n/**\n * Resolved account after config resolution.\n */\nexport interface ResolvedAccount {\n readonly id: string;\n readonly enabled: boolean;\n readonly dmPolicy: 'paired' | 'open' | 'deny';\n readonly allowFrom: readonly string[];\n readonly rawConfig: LingyaoAccountConfig;\n}\n\n/**\n * Extract the lingyao accounts from OpenClaw config.\n */\nfunction extractAccounts(cfg: OpenClawConfig): Record<string, LingyaoAccountConfig> {\n const channels = (cfg as Record<string, unknown>)?.channels as Record<string, unknown> | undefined;\n const lingyao = channels?.lingyao as Record<string, unknown> | undefined;\n const accounts = lingyao?.accounts as Record<string, LingyaoAccountConfig> | undefined;\n\n if (!accounts) return {};\n return accounts;\n}\n\n/**\n * Create the config adapter.\n */\nexport function createConfigAdapter() {\n return {\n listAccountIds(cfg: OpenClawConfig): string[] {\n const accounts = extractAccounts(cfg);\n return Object.keys(accounts);\n },\n\n resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedAccount {\n const accounts = extractAccounts(cfg);\n const ids = Object.keys(accounts);\n\n if (ids.length === 0) {\n // No accounts configured — auto-create a default\n accounts['default'] = {};\n }\n\n const resolvedId = accountId ?? (ids.includes('default') ? 'default' : ids[0]);\n\n if (!resolvedId) {\n throw new Error('No lingyao accounts configured');\n }\n\n const accountConfig = accounts[resolvedId];\n if (!accountConfig) {\n throw new Error(`Account \"${resolvedId}\" not found`);\n }\n\n return {\n id: resolvedId,\n enabled: (accountConfig as Record<string, unknown>)?.enabled !== false,\n dmPolicy: ((accountConfig as Record<string, unknown>)?.dmPolicy as ResolvedAccount['dmPolicy']) ?? 'paired',\n allowFrom: Object.freeze(((accountConfig as Record<string, unknown>)?.allowFrom as string[]) ?? []),\n rawConfig: accountConfig as LingyaoAccountConfig,\n };\n },\n\n isConfigured(_account: ResolvedAccount, _cfg: OpenClawConfig): boolean {\n return true;\n },\n\n isEnabled(account: ResolvedAccount, _cfg: OpenClawConfig): boolean {\n return account.enabled;\n },\n };\n}\n","/**\n * Gateway Adapter - Account lifecycle management\n *\n * Implements ChannelGatewayAdapter:\n * - startAccount: create WS/HTTP connections for an account\n * - stopAccount: tear down connections for an account\n *\n * Delegates to MultiAccountOrchestrator for all operations.\n *\n * SDK passes ChannelGatewayContext with required fields:\n * cfg, accountId, account, runtime, abortSignal, log,\n * getStatus, setStatus, channelRuntime?\n */\n\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\nimport type { ResolvedAccount } from './config.js';\n\n/**\n * SDK-compatible ChannelGatewayContext interface\n */\nexport interface ChannelGatewayContext<ResolvedAccount = unknown> {\n cfg: OpenClawConfig;\n accountId: string;\n account: ResolvedAccount;\n runtime: RuntimeEnv;\n abortSignal: AbortSignal;\n log?: {\n info: (msg: string) => void;\n warn?: (msg: string) => void;\n error?: (msg: string) => void;\n debug?: (msg: string) => void;\n };\n getStatus: () => ChannelAccountSnapshot;\n setStatus: (next: ChannelAccountSnapshot) => void;\n channelRuntime?: unknown;\n}\n\nexport interface OpenClawConfig {\n channels?: Record<string, unknown>;\n}\n\nexport interface RuntimeEnv {\n // Minimal runtime interface\n}\n\nexport interface ChannelAccountSnapshot {\n accountId: string;\n configured: boolean;\n enabled: boolean;\n running: boolean;\n}\n\n/**\n * Create the gateway adapter.\n *\n * @param getOrchestrator - Lazy accessor for the orchestrator instance.\n * The orchestrator is created in setRuntime, but the adapter is created\n * at module load time. Using a getter ensures the adapter accesses\n * the initialized orchestrator when called.\n */\nexport function createGatewayAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null\n) {\n return {\n async startAccount(ctx: ChannelGatewayContext<ResolvedAccount>): Promise<void> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized. Ensure setRuntime was called.');\n }\n\n ctx.log?.info(`Starting account \"${ctx.accountId}\"`);\n\n await orchestrator.start(ctx.account);\n\n ctx.log?.info(`Account \"${ctx.accountId}\" started successfully`);\n },\n\n async stopAccount(ctx: ChannelGatewayContext<ResolvedAccount>): Promise<void> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized');\n }\n\n ctx.log?.info(`Stopping account \"${ctx.accountId}\"`);\n\n await orchestrator.stop(ctx.accountId);\n },\n };\n}\n","/**\n * Status Adapter - Health checks and channel summary\n *\n * Implements ChannelStatusAdapter:\n * - probeAccount: run health checks for a specific account\n * - buildChannelSummary: aggregate status for a single account\n *\n * SDK passes:\n * probeAccount({ account, timeoutMs, cfg })\n * buildChannelSummary({ account, cfg, defaultAccountId, snapshot })\n *\n * Wraps existing Probe and Monitor classes.\n */\n\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\nimport type { ResolvedAccount } from './config.js';\n\n/**\n * SDK-compatible status interfaces\n */\nexport interface OpenClawConfig {\n channels?: Record<string, unknown>;\n}\n\nexport interface ChannelAccountSnapshot {\n accountId: string;\n configured: boolean;\n enabled: boolean;\n running: boolean;\n}\n\n/**\n * Probe result structure.\n */\nexport interface LingyaoProbeResult {\n ok: boolean;\n status: 'healthy' | 'degraded' | 'unhealthy';\n wsConnected: boolean;\n uptime?: number;\n checks?: Record<string, { passed: boolean; message: string; duration?: number }>;\n error?: string;\n}\n\n/**\n * Create the status adapter.\n */\nexport function createStatusAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null,\n _runtime?: unknown\n) {\n return {\n async probeAccount(params: {\n account: ResolvedAccount;\n timeoutMs: number;\n cfg: OpenClawConfig;\n }): Promise<LingyaoProbeResult> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n return {\n ok: false,\n status: 'unhealthy',\n wsConnected: false,\n error: 'Orchestrator not initialized',\n };\n }\n\n const state = orchestrator.getAccountState(params.account.id);\n if (!state) {\n return {\n ok: false,\n status: 'unhealthy',\n wsConnected: false,\n error: 'Account not started',\n };\n }\n\n try {\n const healthResult = await state.probe.runHealthChecks();\n const wsConnected = state.wsClient?.isConnected() ?? false;\n\n let status: 'healthy' | 'degraded' | 'unhealthy' = 'healthy';\n switch (healthResult.status) {\n case 'healthy':\n status = wsConnected ? 'healthy' : 'degraded';\n break;\n case 'degraded':\n status = 'degraded';\n break;\n case 'unhealthy':\n status = 'unhealthy';\n break;\n }\n\n const checks: Record<string, { passed: boolean; message: string; duration?: number }> = {};\n for (const [name, result] of healthResult.checks) {\n checks[name] = {\n passed: result.passed,\n message: result.message ?? '',\n duration: result.duration,\n };\n }\n\n return {\n ok: status !== 'unhealthy',\n status,\n wsConnected,\n uptime: Date.now() - state.startTime,\n checks,\n };\n } catch (error) {\n return {\n ok: false,\n status: 'unhealthy',\n wsConnected: false,\n error: (error as Error).message,\n };\n }\n },\n\n async buildChannelSummary(params: {\n account: ResolvedAccount;\n cfg: OpenClawConfig;\n defaultAccountId: string;\n snapshot: ChannelAccountSnapshot;\n }): Promise<Record<string, unknown>> {\n const orchestrator = getOrchestrator();\n const accountId = params.account.id;\n const state = orchestrator?.getAccountState(accountId);\n const runningIds = orchestrator?.getRunningAccountIds() ?? [];\n\n return {\n accountId,\n status: state?.status ?? 'stopped',\n wsConnected: state?.wsClient?.isConnected() ?? false,\n isDefault: accountId === params.defaultAccountId,\n running: runningIds.includes(accountId),\n uptime: state ? Date.now() - state.startTime : 0,\n };\n },\n };\n}\n","/**\n * Directory Adapter - List paired devices (peers)\n *\n * Implements ChannelDirectoryAdapter:\n * - listPeers: return all active paired devices for an account\n *\n * SDK passes:\n * listPeers({ cfg, accountId?, query?, limit?, runtime })\n *\n * Returns ChannelDirectoryEntry[] with { kind, id, name?, ... }\n *\n * Uses AccountManager to get the device list.\n * Each device is returned as a \"user\" peer (no groups in Lingyao).\n */\n\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\n\n/**\n * SDK-compatible directory interfaces\n */\nexport interface OpenClawConfig {\n channels?: Record<string, unknown>;\n}\n\nexport type ChannelDirectoryEntryKind = 'user' | 'group' | 'channel';\n\nexport interface ChannelDirectoryEntry {\n kind: ChannelDirectoryEntryKind;\n id: string;\n name?: string;\n handle?: string;\n avatarUrl?: string;\n rank?: number;\n raw?: unknown;\n}\n\nexport interface RuntimeEnv {\n // Minimal runtime interface\n}\n\nexport interface ChannelDirectoryListParams {\n cfg: OpenClawConfig;\n accountId?: string | null;\n query?: string | null;\n limit?: number | null;\n runtime: RuntimeEnv;\n}\n\n/**\n * Create the directory adapter.\n */\nexport function createDirectoryAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null\n) {\n return {\n async listPeers(params: ChannelDirectoryListParams): Promise<ChannelDirectoryEntry[]> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n return [];\n }\n\n const accountId = params.accountId ?? 'default';\n const accountManager = orchestrator.getAccountManager(accountId);\n if (!accountManager) {\n return [];\n }\n\n const activeAccounts = accountManager.getActiveAccounts();\n\n let entries: ChannelDirectoryEntry[] = activeAccounts.map(account => ({\n kind: 'user' as const,\n id: account.deviceId,\n name: account.deviceInfo.name || account.deviceId,\n handle: account.deviceId,\n raw: account,\n }));\n\n if (params.query) {\n const q = params.query.toLowerCase();\n entries = entries.filter(\n e => e.id.toLowerCase().includes(q) || (e.name?.toLowerCase().includes(q) ?? false)\n );\n }\n\n if (params.limit != null && params.limit > 0) {\n entries = entries.slice(0, params.limit);\n }\n\n return entries;\n },\n };\n}\n","/**\n * Messaging Adapter - Target normalization and session resolution\n *\n * Implements ChannelMessagingAdapter:\n * - normalizeTarget: strip \"lingyao:\" prefix, return pure deviceId\n * - resolveSessionTarget: return \"lingyao:{id}\" format\n * - inferTargetChatType: always \"direct\" (Lingyao has no groups)\n */\n\n/**\n * SDK-compatible messaging interfaces\n */\nexport type ChatType = 'direct' | 'group';\n\nconst PREFIX = 'lingyao:';\n\nexport function createMessagingAdapter() {\n return {\n normalizeTarget(raw: string): string | undefined {\n if (!raw || typeof raw !== 'string') {\n return undefined;\n }\n\n const target = raw.startsWith(PREFIX)\n ? raw.slice(PREFIX.length)\n : raw;\n\n if (!target) {\n return undefined;\n }\n\n return target;\n },\n\n resolveSessionTarget(params: {\n kind: 'user' | 'group' | 'channel';\n id: string;\n threadId?: string | number | null;\n }): string | undefined {\n return `${PREFIX}${params.id}`;\n },\n\n inferTargetChatType(_params: {\n to: string;\n }): ChatType | undefined {\n return 'direct';\n },\n };\n}\n","/**\n * Outbound Adapter - Send messages from Agent to App devices\n *\n * Implements ChannelOutboundAdapter:\n * - deliveryMode: \"direct\" (synchronous via WS)\n * - sendText: send plain text notification\n * - sendPayload: send structured payload notification\n * - resolveTarget: validate and resolve target deviceId\n *\n * SDK passes ChannelOutboundContext = { cfg, to, text, accountId?, ... }\n * and expects OutboundDeliveryResult = { channel, messageId, ... } return.\n *\n * Routes through MultiAccountOrchestrator to the correct\n * account's WS connection.\n */\n\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\n\n/**\n * SDK-compatible outbound interfaces\n */\nexport interface OpenClawConfig {\n channels?: Record<string, unknown>;\n}\n\nexport interface ChannelOutboundContext {\n cfg: OpenClawConfig;\n to: string;\n text: string;\n mediaUrl?: string;\n accountId?: string | null;\n silent?: boolean;\n}\n\nexport interface ChannelOutboundPayloadContext extends ChannelOutboundContext {\n payload: unknown;\n}\n\nexport interface OutboundDeliveryResult {\n channel: string;\n messageId: string;\n chatId?: string;\n timestamp?: number;\n meta?: Record<string, unknown>;\n}\n\n/**\n * Create the outbound adapter.\n */\nexport function createOutboundAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null\n) {\n return {\n deliveryMode: 'direct' as const,\n\n async sendText(ctx: ChannelOutboundContext): Promise<OutboundDeliveryResult> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized');\n }\n\n const accountId = ctx.accountId ?? 'default';\n const sent = orchestrator.sendNotification(\n accountId,\n ctx.to,\n { title: 'OpenClaw', body: ctx.text }\n );\n\n if (!sent) {\n throw new Error(\n `Failed to send text to device \"${ctx.to}\" on account \"${accountId}\": not connected`\n );\n }\n\n return {\n channel: 'lingyao',\n messageId: `out_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,\n chatId: ctx.to,\n timestamp: Date.now(),\n };\n },\n\n async sendPayload(ctx: ChannelOutboundPayloadContext): Promise<OutboundDeliveryResult> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized');\n }\n\n const accountId = ctx.accountId ?? 'default';\n const sent = orchestrator.sendNotification(\n accountId,\n ctx.to,\n ctx.payload as Record<string, unknown>\n );\n\n if (!sent) {\n throw new Error(\n `Failed to send payload to device \"${ctx.to}\" on account \"${accountId}\": not connected`\n );\n }\n\n return {\n channel: 'lingyao',\n messageId: `out_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,\n chatId: ctx.to,\n timestamp: Date.now(),\n };\n },\n\n resolveTarget(params: {\n cfg?: OpenClawConfig;\n to?: string;\n accountId?: string | null;\n }): { ok: true; to: string } | { ok: false; error: Error } {\n const raw = params.to;\n if (!raw || typeof raw !== 'string' || raw.trim().length === 0) {\n return { ok: false, error: new Error('Target deviceId is empty or missing') };\n }\n return { ok: true, to: raw.trim() };\n },\n };\n}\n","/**\n * Multi-Account Orchestrator\n *\n * Manages per-account WS/HTTP instances for multi-account support.\n * Each account gets independent LingyaoWSClient, ServerHttpClient,\n * AccountManager, MessageProcessor, Probe, and Monitor instances.\n *\n * Data flow:\n * Gateway Adapter → orchestrator.start(account) → WS connect\n * Inbound (App) → WS message → orchestrator → MessageProcessor → Agent\n * Outbound (Agent)→ orchestrator.sendNotification() → WS → App\n */\n\nimport { hostname } from 'node:os';\nimport { LINGYAO_SERVER_URL } from './types.js';\nimport type { LingyaoRuntime } from './types.js';\nimport type { ResolvedAccount } from './adapters/config.js';\nimport { ServerHttpClient } from './server-client.js';\nimport { LingyaoWSClient } from './websocket-client.js';\nimport { AccountManager } from './accounts.js';\nimport { MessageProcessor, type AgentMessage } from './bot.js';\nimport { Probe } from './probe.js';\nimport { Monitor, MonitoringEvent } from './metrics.js';\nimport { ErrorHandler } from './errors.js';\n\n/**\n * Per-account runtime state\n */\ninterface AccountState {\n accountId: string;\n wsClient: LingyaoWSClient | null;\n httpClient: ServerHttpClient | null;\n accountManager: AccountManager;\n messageProcessor: MessageProcessor | null;\n probe: Probe;\n monitor: Monitor;\n errorHandler: ErrorHandler;\n status: 'stopped' | 'starting' | 'running' | 'stopping' | 'error';\n startTime: number;\n gatewayId: string;\n}\n\n/**\n * Generate a gateway ID for an account\n */\nfunction generateGatewayId(accountId: string): string {\n const host = hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();\n const suffix = Math.random().toString(36).substring(2, 8);\n return `gw_openclaw_${host}_${accountId}_${suffix}`;\n}\n\nexport class MultiAccountOrchestrator {\n private runtime: LingyaoRuntime;\n private accounts: Map<string, AccountState> = new Map();\n private messageHandler: ((message: AgentMessage) => void | Promise<void>) | null = null;\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n }\n\n /**\n * Set the message handler for delivering messages to the Agent.\n * Propagates to all running accounts.\n */\n setMessageHandler(handler: (message: AgentMessage) => void | Promise<void>): void {\n this.messageHandler = handler;\n for (const state of this.accounts.values()) {\n if (state.messageProcessor) {\n state.messageProcessor.setMessageHandler(handler);\n }\n }\n }\n\n /**\n * Get the current message handler (for gateway adapter injection).\n */\n getMessageHandler(): ((message: AgentMessage) => void | Promise<void>) | null {\n return this.messageHandler;\n }\n\n /**\n * Start an account: create components, register to server, connect WS.\n */\n async start(account: ResolvedAccount): Promise<void> {\n const { id: accountId } = account;\n\n const existing = this.accounts.get(accountId);\n if (existing?.status === 'running') {\n this.runtime.logger.warn(`Account \"${accountId}\" is already running`);\n return;\n }\n\n this.runtime.logger.info(`Starting account \"${accountId}\"`);\n\n const gatewayId = generateGatewayId(accountId);\n const storagePrefix = `lingyao:${accountId}`;\n\n const accountManager = new AccountManager(this.runtime);\n const messageProcessor = new MessageProcessor(this.runtime, accountManager);\n const probe = new Probe(this.runtime);\n const monitor = new Monitor(this.runtime);\n const errorHandler = new ErrorHandler(this.runtime);\n const httpClient = new ServerHttpClient(\n this.runtime,\n gatewayId,\n { baseURL: LINGYAO_SERVER_URL },\n storagePrefix\n );\n\n const state: AccountState = {\n accountId,\n wsClient: null,\n httpClient,\n accountManager,\n messageProcessor,\n probe,\n monitor,\n errorHandler,\n status: 'starting',\n startTime: Date.now(),\n gatewayId,\n };\n\n this.accounts.set(accountId, state);\n\n try {\n await accountManager.initialize();\n await messageProcessor.initialize();\n\n if (this.messageHandler) {\n messageProcessor.setMessageHandler(this.messageHandler);\n }\n\n // Register to server (restore from storage or fresh register)\n await this.registerToServer(state);\n\n // Create and connect WebSocket client\n const wsClient = new LingyaoWSClient(this.runtime, {\n url: `${LINGYAO_SERVER_URL}/v1/gateway/ws`,\n gatewayId,\n token: httpClient.getGatewayToken() ?? undefined,\n reconnectInterval: 5000,\n heartbeatInterval: 30000,\n messageHandler: this.createMessageHandler(state),\n eventHandler: this.createEventHandler(state),\n });\n\n await wsClient.connect();\n state.wsClient = wsClient;\n state.status = 'running';\n\n this.runtime.logger.info(`Account \"${accountId}\" started successfully`);\n } catch (error) {\n state.status = 'error';\n this.runtime.logger.error(`Failed to start account \"${accountId}\"`, error);\n throw error;\n }\n }\n\n /**\n * Stop an account: disconnect WS, stop heartbeat.\n */\n async stop(accountId: string): Promise<void> {\n const state = this.accounts.get(accountId);\n if (!state || state.status === 'stopped') {\n return;\n }\n\n this.runtime.logger.info(`Stopping account \"${accountId}\"`);\n state.status = 'stopping';\n\n if (state.wsClient) {\n state.wsClient.disconnect();\n state.wsClient = null;\n }\n\n if (state.httpClient) {\n state.httpClient.stopHeartbeat();\n }\n\n state.status = 'stopped';\n this.runtime.logger.info(`Account \"${accountId}\" stopped`);\n }\n\n /**\n * Stop all running accounts.\n */\n async stopAll(): Promise<void> {\n const stops = Array.from(this.accounts.keys()).map(id => this.stop(id));\n await Promise.all(stops);\n }\n\n /**\n * Get account state by ID.\n */\n getAccountState(accountId: string): AccountState | undefined {\n return this.accounts.get(accountId);\n }\n\n /**\n * Get account's WS client.\n */\n getWSClient(accountId: string): LingyaoWSClient | null {\n return this.accounts.get(accountId)?.wsClient ?? null;\n }\n\n /**\n * Get account's HTTP client.\n */\n getHttpClient(accountId: string): ServerHttpClient | null {\n return this.accounts.get(accountId)?.httpClient ?? null;\n }\n\n /**\n * Get account's AccountManager.\n */\n getAccountManager(accountId: string): AccountManager | null {\n return this.accounts.get(accountId)?.accountManager ?? null;\n }\n\n /**\n * Get account's Probe.\n */\n getProbe(accountId: string): Probe | null {\n return this.accounts.get(accountId)?.probe ?? null;\n }\n\n /**\n * Get account's Monitor.\n */\n getMonitor(accountId: string): Monitor | null {\n return this.accounts.get(accountId)?.monitor ?? null;\n }\n\n /**\n * Send notification to a device on a specific account.\n * Returns true if sent, false if WS not connected.\n */\n sendNotification(\n accountId: string,\n deviceId: string,\n notification: Record<string, unknown>\n ): boolean {\n const wsClient = this.getWSClient(accountId);\n if (!wsClient || !wsClient.isConnected()) {\n return false;\n }\n\n wsClient.sendNotification(deviceId, notification);\n return true;\n }\n\n /**\n * List all running account IDs.\n */\n getRunningAccountIds(): string[] {\n return Array.from(this.accounts.entries())\n .filter(([, state]) => state.status === 'running')\n .map(([id]) => id);\n }\n\n /**\n * Register to lingyao server for a specific account.\n */\n private async registerToServer(state: AccountState): Promise<void> {\n if (!state.httpClient) {\n throw new Error('HTTP client not available');\n }\n\n try {\n const restored = await state.httpClient.restoreFromStorage();\n if (restored) {\n this.runtime.logger.info(`Account \"${state.accountId}\": session restored from storage`);\n return;\n }\n\n this.runtime.logger.info(`Account \"${state.accountId}\": registering to server...`, {\n gatewayId: state.gatewayId,\n });\n\n const response = await state.httpClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n\n this.runtime.logger.info(`Account \"${state.accountId}\": registered successfully`, {\n expiresAt: new Date(response.expiresAt).toISOString(),\n });\n } catch (error) {\n this.runtime.logger.error(`Account \"${state.accountId}\": registration failed`, error);\n // Don't throw - WS client will attempt connection anyway and auto-reconnect\n }\n }\n\n /**\n * Create message handler for inbound App messages on a specific account.\n */\n private createMessageHandler(state: AccountState) {\n return async (message: any): Promise<void> => {\n try {\n const appMessage = message.payload;\n const deviceId = appMessage.deviceId;\n const msg = appMessage.message;\n\n this.runtime.logger.info(`[${state.accountId}] Received message from App`, {\n deviceId,\n messageType: msg.type,\n messageId: msg.id,\n });\n\n state.monitor.recordEvent(MonitoringEvent.MESSAGE_RECEIVED, {\n deviceId,\n messageType: msg.type,\n });\n\n switch (msg.type) {\n case 'sync_diary':\n case 'sync_memory':\n await this.handleSyncMessage(state, deviceId, msg);\n break;\n case 'heartbeat':\n await state.accountManager.updateLastSeen(deviceId);\n state.monitor.recordEvent(MonitoringEvent.HEARTBEAT_RECEIVED, { deviceId });\n break;\n default:\n this.runtime.logger.warn(`[${state.accountId}] Unknown message type`, { type: msg.type });\n }\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] Error handling App message`, error);\n state.monitor.recordEvent(MonitoringEvent.ERROR_OCCURRED, {\n errorType: 'message_handling',\n });\n }\n };\n }\n\n /**\n * Handle sync message (diary or memory).\n */\n private async handleSyncMessage(\n state: AccountState,\n deviceId: string,\n message: {\n id: string;\n type: 'sync_diary' | 'sync_memory';\n timestamp: number;\n content: string;\n metadata?: Record<string, unknown>;\n }\n ): Promise<void> {\n if (!state.messageProcessor) {\n this.runtime.logger.warn(`[${state.accountId}] Message processor not initialized`);\n return;\n }\n\n const agentMessage: AgentMessage = {\n id: message.id,\n type: message.type === 'sync_diary' ? 'diary' : 'memory',\n from: deviceId,\n deviceId,\n content: message.content,\n metadata: message.metadata || {},\n timestamp: message.timestamp,\n };\n\n await state.messageProcessor.deliverToAgent(agentMessage);\n }\n\n /**\n * Create event handler for WS connection events on a specific account.\n */\n private createEventHandler(state: AccountState) {\n return (event: any): void => {\n switch (event.type) {\n case 'connected':\n this.runtime.logger.info(`[${state.accountId}] WS connected`, {\n connectionId: event.connectionId,\n });\n state.monitor.recordEvent(MonitoringEvent.CONNECTION_OPEN, {\n connectionId: event.connectionId,\n });\n break;\n case 'disconnected':\n this.runtime.logger.warn(`[${state.accountId}] WS disconnected`, {\n code: event.code,\n reason: event.reason,\n });\n state.monitor.recordEvent(MonitoringEvent.CONNECTION_CLOSE, {\n code: event.code,\n reason: event.reason,\n });\n break;\n case 'error':\n this.runtime.logger.error(`[${state.accountId}] WS error`, event.error);\n state.probe.recordError(event.error.message, 'websocket');\n state.monitor.recordEvent(MonitoringEvent.CONNECTION_ERROR, {\n error: event.error,\n });\n state.errorHandler.handleError(event.error);\n break;\n }\n };\n }\n}\n","/**\n * Lingyao relay server URL (internal constant, not user-configurable)\n */\nexport const LINGYAO_SERVER_URL = 'https://api.lingyao.live';\n\n/**\n * Message type enumeration for all Lingyao message types\n */\nexport enum MessageType {\n // Sync types - App to Gateway\n SYNC_DIARY = \"sync_diary\",\n SYNC_MEMORY = \"sync_memory\",\n SYNC_ACK = \"sync_ack\",\n\n // Notify types - Gateway to App\n NOTIFY_TEXT = \"notify_text\",\n NOTIFY_ACTION = \"notify_action\",\n\n // Control types\n HEARTBEAT = \"heartbeat\",\n PAIRING_REQUEST = \"pairing_request\",\n PAIRING_CONFIRM = \"pairing_confirm\",\n}\n\n/**\n * Base message structure for all Lingyao messages\n */\nexport interface LingyaoMessage {\n id: string;\n type: MessageType;\n timestamp: number;\n from: string;\n to: string;\n payload: unknown;\n signature?: string;\n}\n\n/**\n * Diary sync payload\n */\nexport interface DiarySyncPayload {\n diaryId: string;\n title?: string;\n content: string;\n emotion?: string;\n tags?: string[];\n mediaUrls?: string[];\n createdAt: number;\n updatedAt: number;\n}\n\n/**\n * Memory sync payload\n */\nexport interface MemorySyncPayload {\n memoryId: string;\n type: \"diary\" | \"fact\" | \"preference\" | \"decision\";\n content: string;\n importance: number;\n metadata?: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Notification payload\n */\nexport interface NotifyPayload {\n title: string;\n body: string;\n action?: NotifyAction;\n}\n\n/**\n * Notification action descriptor\n */\nexport interface NotifyAction {\n type: \"open_memory\" | \"view_diary\" | \"custom\";\n params: Record<string, unknown>;\n}\n\n/**\n * Device token structure\n */\nexport interface DeviceToken {\n deviceId: string;\n pairingId: string;\n token: string;\n secret: string;\n expiresAt: number;\n deviceInfo: DeviceInfo;\n}\n\n/**\n * Device information\n */\nexport interface DeviceInfo {\n name: string;\n platform: string;\n version: string;\n}\n\n/**\n * Pairing code structure\n */\nexport interface PairingCode {\n code: string;\n timestamp: number;\n nonce: string;\n expiresAt: number;\n}\n\n/**\n * Sync request from App\n */\nexport interface SyncRequest {\n deviceToken: string;\n messages: LingyaoMessage[];\n lastSyncAt?: number;\n}\n\n/**\n * Sync response from Gateway\n */\nexport interface SyncResponse {\n processed: string[];\n failed: FailedEntry[];\n}\n\n/**\n * Failed sync entry\n */\nexport interface FailedEntry {\n id: string;\n error: string;\n}\n\n/**\n * Poll request from App\n */\nexport interface PollRequest {\n deviceToken: string;\n timeout?: number;\n}\n\n/**\n * Poll response from Gateway\n */\nexport interface PollResponse {\n messages: LingyaoMessage[];\n hasMore: boolean;\n}\n\n/**\n * Ack request from App\n */\nexport interface AckRequest {\n deviceToken: string;\n messageIds: string[];\n}\n\n/**\n * Pairing confirm request from App\n */\nexport interface PairingConfirmRequest {\n pairingCode: string;\n deviceInfo: DeviceInfo;\n}\n\n/**\n * Pairing confirm response from Gateway\n */\nexport interface PairingConfirmResponse {\n pairingId: string;\n deviceToken: DeviceToken;\n}\n\n/**\n * Token refresh request\n */\nexport interface TokenRefreshRequest {\n currentToken: string;\n}\n\n/**\n * Token refresh response\n */\nexport interface TokenRefreshResponse {\n deviceToken: DeviceToken;\n}\n\n/**\n * Notify request (Agent to Gateway)\n */\nexport interface NotifyRequest {\n deviceId: string;\n notification: NotifyPayload;\n}\n\n/**\n * Per-account configuration (under channels.lingyao.accounts.<id>)\n */\nexport interface LingyaoAccountConfig {\n enabled?: boolean;\n dmPolicy?: \"paired\" | \"open\" | \"deny\";\n allowFrom?: string[];\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n}\n\n/**\n * Channel configuration\n */\nexport interface LingyaoConfig {\n enabled: boolean;\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n dmPolicy?: \"paired\" | \"open\" | \"deny\";\n allowFrom?: string[];\n accounts?: Record<string, LingyaoAccountConfig>;\n}\n\n/**\n * Plugin runtime API\n */\nexport interface LingyaoRuntime {\n config: LingyaoConfig;\n logger: {\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n debug: (message: string, ...args: unknown[]) => void;\n };\n storage: {\n get: (key: string) => Promise<unknown | null>;\n set: (key: string, value: unknown) => Promise<void>;\n delete: (key: string) => Promise<void>;\n };\n tools: {\n call: (name: string, params: Record<string, unknown>) => Promise<unknown>;\n };\n}\n\n/**\n * Account information\n */\nexport interface LingyaoAccount {\n deviceId: string;\n deviceInfo: DeviceInfo;\n deviceToken: DeviceToken;\n pairedAt: number;\n lastSeenAt: number;\n status: \"active\" | \"inactive\" | \"revoked\";\n}\n\n/**\n * Message queue entry\n */\nexport interface QueuedMessage {\n message: LingyaoMessage;\n status: \"pending\" | \"delivered\" | \"failed\";\n retryCount: number;\n createdAt: number;\n}\n\n/**\n * WebSocket connection info\n */\nexport interface WebSocketConnection {\n deviceId: string;\n ws: unknown;\n connectedAt: number;\n lastHeartbeat: number;\n}\n\n/**\n * Health status\n */\nexport interface HealthStatus {\n status: \"healthy\" | \"degraded\" | \"unhealthy\";\n uptime: number;\n activeConnections: number;\n queuedMessages: number;\n lastError?: string;\n}\n","/**\n * 灵爻服务器 HTTP 客户端\n *\n * 主动连接到灵爻服务器,实现 Gateway 注册、心跳、消息推送\n * 符合 openapi.yaml 规范\n */\n\nimport axios from 'axios';\nimport type { LingyaoRuntime } from './types.js';\n\n// 类型定义 - 避免 axios 类型导出在 DTS 构建中的问题\ntype AxiosInstance = ReturnType<typeof axios.create>;\n\ninterface AxiosErrorLike extends Error {\n response?: {\n status?: number;\n data?: any;\n };\n config?: any;\n code?: string;\n isAxiosError?: boolean;\n}\n\n/**\n * axios 错误类型守卫\n */\nfunction isAxiosError(error: unknown): error is AxiosErrorLike {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'isAxiosError' in error &&\n (error as AxiosErrorLike).isAxiosError === true\n );\n}\n\n/**\n * 服务器 API 配置\n */\nexport interface ServerConfig {\n baseURL: string;\n apiBase: string;\n timeout: number;\n connectionTimeout: number;\n}\n\n/**\n * Gateway 注册响应\n */\nexport interface GatewayRegisterResponse {\n gatewayToken: string;\n expiresAt: number;\n webhookSecret: string;\n serverConfig: {\n heartbeatInterval: number;\n maxOfflineMessages: number;\n supportedMessageTypes: string[];\n };\n}\n\n/**\n * 心跳响应\n */\nexport interface HeartbeatResponse {\n serverTime: number;\n pendingMessages: number;\n}\n\n/**\n * 发送消息请求\n */\nexport interface SendMessageRequest {\n deviceId: string;\n message: {\n id: string;\n type: 'notify_text' | 'notify_action';\n timestamp: number;\n payload: {\n title?: string;\n body?: string;\n action?: {\n type: 'open_memory' | 'view_diary' | 'custom';\n params?: Record<string, unknown>;\n };\n };\n };\n options?: {\n priority?: 'normal' | 'low' | 'high';\n ttl?: number;\n };\n}\n\n/**\n * 发送消息响应\n */\nexport interface SendMessageResponse {\n messageId: string;\n status: 'queued' | 'delivered' | 'failed';\n deliveredAt: number | null;\n queued: boolean;\n}\n\n/**\n * Gateway 状态\n */\nexport type GatewayStatus = 'online' | 'offline' | 'maintenance';\n\n/**\n * HTTP 客户端实现\n */\nexport class ServerHttpClient {\n private runtime: LingyaoRuntime;\n private config: ServerConfig;\n private axiosInstance: AxiosInstance;\n private gatewayToken: string | null = null;\n private webhookSecret: string | null = null;\n private tokenExpiresAt: number = 0;\n private heartbeatInterval: number = 30000;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private gatewayId: string;\n private isRegistered: boolean = false;\n private isConnecting: boolean = false;\n\n private storagePrefix: string;\n\n constructor(\n runtime: LingyaoRuntime,\n gatewayId: string,\n serverConfig: Partial<ServerConfig> = {},\n storagePrefix: string = 'lingyao'\n ) {\n this.runtime = runtime;\n this.gatewayId = gatewayId;\n this.storagePrefix = storagePrefix;\n this.config = {\n baseURL: serverConfig.baseURL || 'https://api.lingyao.live',\n apiBase: serverConfig.apiBase || '/v1',\n timeout: serverConfig.timeout || 30000,\n connectionTimeout: serverConfig.connectionTimeout || 5000,\n };\n\n // 创建 axios 实例\n this.axiosInstance = axios.create({\n baseURL: this.config.baseURL + this.config.apiBase,\n timeout: this.config.timeout,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n // 请求拦截器 - 添加 Token\n this.axiosInstance.interceptors.request.use(\n (config) => {\n if (this.gatewayToken && config.headers) {\n config.headers.Authorization = `Bearer ${this.gatewayToken}`;\n }\n return config;\n },\n (error) => Promise.reject(error)\n );\n\n // 响应拦截器 - 处理错误\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n async (error: unknown) => {\n if (isAxiosError(error)) {\n if (error.response?.status === 401) {\n // Token 过期,尝试刷新\n this.runtime.logger.warn('Token expired, attempting to re-register...');\n await this.register();\n }\n }\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * 注册 Gateway 到服务器\n */\n async register(\n capabilities: {\n websocket?: boolean;\n compression?: boolean;\n maxMessageSize?: number;\n } = {}\n ): Promise<GatewayRegisterResponse> {\n if (this.isConnecting) {\n throw new Error('Registration already in progress');\n }\n\n this.isConnecting = true;\n\n try {\n this.runtime.logger.info(`Registering gateway ${this.gatewayId} to server...`);\n\n const response = await this.axiosInstance.post<GatewayRegisterResponse>(\n '/gateway/register',\n {\n gatewayId: this.gatewayId,\n version: '0.1.0',\n capabilities: {\n websocket: false,\n compression: false,\n ...capabilities,\n },\n }\n );\n\n const data = response.data;\n\n this.gatewayToken = data.gatewayToken;\n this.webhookSecret = data.webhookSecret;\n this.tokenExpiresAt = data.expiresAt;\n this.heartbeatInterval = data.serverConfig.heartbeatInterval;\n this.isRegistered = true;\n\n // 保存到存储\n await this.runtime.storage.set(this.storageKey('gatewayToken'), this.gatewayToken);\n await this.runtime.storage.set(this.storageKey('webhookSecret'), this.webhookSecret);\n await this.runtime.storage.set(this.storageKey('tokenExpiresAt'), this.tokenExpiresAt);\n await this.runtime.storage.set(this.storageKey('serverConfig'), data.serverConfig);\n\n this.runtime.logger.info('Gateway registered successfully', {\n expiresAt: new Date(this.tokenExpiresAt).toISOString(),\n heartbeatInterval: this.heartbeatInterval,\n });\n\n // 启动心跳\n this.startHeartbeat();\n\n return data;\n } catch (error: unknown) {\n if (isAxiosError(error)) {\n const axiosError = error as AxiosErrorLike;\n const status = axiosError.response?.status;\n const data = axiosError.response?.data as { code?: string; details?: string };\n\n if (status === 409) {\n throw new Error('Gateway already registered');\n } else if (status === 400) {\n throw new Error(`Invalid request: ${data?.details || 'Unknown error'}`);\n }\n\n throw new Error(`Registration failed: ${axiosError.message}`);\n }\n throw error;\n } finally {\n this.isConnecting = false;\n }\n }\n\n /**\n * 发送心跳\n */\n async heartbeat(\n status: GatewayStatus = 'online',\n activeConnections: number = 0\n ): Promise<HeartbeatResponse> {\n if (!this.isRegistered || !this.gatewayToken) {\n throw new Error('Gateway not registered');\n }\n\n try {\n const response = await this.axiosInstance.post<HeartbeatResponse>(\n '/gateway/heartbeat',\n {\n timestamp: Date.now(),\n status,\n activeConnections,\n }\n );\n\n return response.data;\n } catch (error: unknown) {\n if (isAxiosError(error)) {\n const axiosError = error as AxiosErrorLike;\n this.runtime.logger.error('Heartbeat failed', {\n status: axiosError.response?.status,\n data: axiosError.response?.data,\n });\n }\n throw error;\n }\n }\n\n /**\n * 发送消息到灵爻 App\n */\n async sendMessage(\n deviceId: string,\n messageType: 'notify_text' | 'notify_action',\n payload: SendMessageRequest['message']['payload'],\n options?: SendMessageRequest['options']\n ): Promise<SendMessageResponse> {\n if (!this.isRegistered || !this.gatewayToken) {\n throw new Error('Gateway not registered');\n }\n\n const messageId = this.generateMessageId();\n\n try {\n const response = await this.axiosInstance.post<SendMessageResponse>(\n '/gateway/messages',\n {\n deviceId,\n message: {\n id: messageId,\n type: messageType,\n timestamp: Date.now(),\n payload,\n },\n options: options || {},\n }\n );\n\n this.runtime.logger.debug('Message sent', {\n messageId,\n deviceId,\n status: response.data.status,\n });\n\n return response.data;\n } catch (error: unknown) {\n if (isAxiosError(error)) {\n const axiosError = error as AxiosErrorLike;\n const status = axiosError.response?.status;\n const data = axiosError.response?.data as { error?: string };\n\n if (status === 404) {\n throw new Error(`Device not found: ${deviceId}`);\n } else if (status === 429) {\n throw new Error('Message queue full, please retry later');\n }\n\n throw new Error(`Send message failed: ${data?.error || axiosError.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 启动心跳循环\n */\n private startHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n }\n\n this.heartbeatTimer = setInterval(\n async () => {\n try {\n await this.heartbeat();\n } catch (error) {\n this.runtime.logger.error('Heartbeat error', error);\n }\n },\n this.heartbeatInterval\n );\n\n this.runtime.logger.info('Heartbeat started', {\n interval: this.heartbeatInterval,\n });\n }\n\n /**\n * 停止心跳循环\n */\n stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n this.runtime.logger.info('Heartbeat stopped');\n }\n }\n\n /**\n * 获取 Webhook Secret\n */\n getWebhookSecret(): string | null {\n return this.webhookSecret;\n }\n\n /**\n * 获取 Gateway Token\n */\n getGatewayToken(): string | null {\n return this.gatewayToken;\n }\n\n /**\n * 检查 Token 是否即将过期\n */\n isTokenExpiringSoon(thresholdMs: number = 7 * 24 * 60 * 60 * 1000): boolean {\n return this.tokenExpiresAt - Date.now() < thresholdMs;\n }\n\n /**\n * 检查是否已注册\n */\n isReady(): boolean {\n return this.isRegistered && !!this.gatewayToken;\n }\n\n /**\n * 从存储恢复会话\n */\n async restoreFromStorage(): Promise<boolean> {\n try {\n const token = await this.runtime.storage.get(this.storageKey('gatewayToken'));\n const secret = await this.runtime.storage.get(this.storageKey('webhookSecret'));\n const expiresAt = await this.runtime.storage.get(this.storageKey('tokenExpiresAt')) as number | undefined;\n const serverConfig = await this.runtime.storage.get(this.storageKey('serverConfig')) as GatewayRegisterResponse['serverConfig'] | undefined;\n\n if (token && secret && expiresAt && serverConfig) {\n // 检查是否过期\n if (expiresAt > Date.now()) {\n this.gatewayToken = token as string;\n this.webhookSecret = secret as string;\n this.tokenExpiresAt = expiresAt;\n this.heartbeatInterval = serverConfig.heartbeatInterval;\n this.isRegistered = true;\n\n // 启动心跳\n this.startHeartbeat();\n\n this.runtime.logger.info('Session restored from storage', {\n expiresAt: new Date(this.tokenExpiresAt).toISOString(),\n });\n\n return true;\n } else {\n this.runtime.logger.warn('Stored token expired, need to re-register');\n }\n }\n } catch (error) {\n this.runtime.logger.error('Failed to restore session from storage', error);\n }\n\n return false;\n }\n\n /**\n * Build a namespaced storage key for multi-account support\n */\n private storageKey(name: string): string {\n return `${this.storagePrefix}:${name}`;\n }\n\n /**\n * 生成消息 ID\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n }\n\n}\n","/**\n * Lingyao WebSocket Client\n *\n * 主动连接到 lingyao.live 服务器的 WebSocket 客户端\n * 实现:\n * - 自动连接和重连\n * - 心跳机制\n * - 消息发送和接收\n * - 在线状态管理\n */\n\nimport WebSocket from \"ws\";\nimport type { LingyaoRuntime } from \"./types.js\";\n\n/**\n * WebSocket 连接状态\n */\nexport type ConnectionState = \"connecting\" | \"connected\" | \"disconnected\" | \"error\";\n\n/**\n * WebSocket 消息类型\n */\nexport enum WSMessageType {\n // 客户端 → 服务器\n REGISTER = \"register\",\n HEARTBEAT = \"heartbeat\",\n SEND_MESSAGE = \"send_message\",\n ACK = \"ack\",\n\n // 服务器 → 客户端\n REGISTERED = \"registered\",\n HEARTBEAT_ACK = \"heartbeat_ack\",\n MESSAGE_DELIVERED = \"message_delivered\",\n MESSAGE_FAILED = \"message_failed\",\n APP_MESSAGE = \"app_message\", // 来自 App 的消息\n DEVICE_ONLINE = \"device_online\",\n ERROR = \"error\",\n}\n\n/**\n * WebSocket 消息基础格式\n */\nexport interface WSMessage {\n type: WSMessageType | string;\n id: string;\n timestamp: number;\n payload?: any;\n}\n\n/**\n * 注册消息\n */\nexport interface RegisterMessage extends WSMessage {\n type: WSMessageType.REGISTER;\n payload: {\n gatewayId: string;\n version: string;\n capabilities: {\n websocket: boolean;\n compression: boolean;\n maxMessageSize: number;\n };\n };\n}\n\n/**\n * 心跳消息\n */\nexport interface HeartbeatMessage extends WSMessage {\n type: WSMessageType.HEARTBEAT;\n payload: {\n timestamp: number;\n status: \"online\";\n };\n}\n\n/**\n * 发送消息\n */\nexport interface SendMessage extends WSMessage {\n type: WSMessageType.SEND_MESSAGE;\n payload: {\n deviceId: string;\n message: {\n id: string;\n type: \"notify_text\" | \"notify_action\";\n timestamp: number;\n payload: any;\n };\n };\n}\n\n/**\n * 接收到的 App 消息\n */\nexport interface AppMessage extends WSMessage {\n type: WSMessageType.APP_MESSAGE;\n payload: {\n deviceId: string;\n message: {\n id: string;\n type: \"sync_diary\" | \"sync_memory\" | \"heartbeat\";\n timestamp: number;\n content: string;\n metadata?: Record<string, unknown>;\n };\n };\n}\n\n/**\n * WebSocket 客户端事件\n */\nexport type WSClientEvent =\n | { type: \"connected\"; connectionId: string }\n | { type: \"disconnected\"; code: number; reason: string }\n | { type: \"error\"; error: Error }\n | { type: \"message\"; message: WSMessage }\n | { type: \"appMessage\"; deviceId: string; message: AppMessage[\"payload\"][\"message\"] };\n\n/**\n * WebSocket 客户端配置\n */\nexport interface WSClientConfig {\n url: string;\n gatewayId: string;\n token?: string;\n reconnectInterval: number;\n heartbeatInterval: number;\n messageHandler?: (message: AppMessage) => void | Promise<void>;\n eventHandler?: (event: WSClientEvent) => void;\n}\n\n/**\n * Lingyao WebSocket Client\n *\n * 主动连接到 lingyao.live 服务器的 WebSocket 客户端\n */\nexport class LingyaoWSClient {\n private config: WSClientConfig;\n private ws: WebSocket | null = null;\n private state: ConnectionState = \"disconnected\";\n private connectionId: string | null = null;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private messageHandlers: Map<string, (msg: WSMessage) => void> = new Map();\n private logger: LingyaoRuntime[\"logger\"];\n\n constructor(runtime: LingyaoRuntime, config: WSClientConfig) {\n this.logger = runtime.logger;\n this.config = { ...config };\n\n this.registerMessageHandler(WSMessageType.REGISTERED, this.handleRegistered.bind(this));\n this.registerMessageHandler(WSMessageType.HEARTBEAT_ACK, this.handleHeartbeatAck.bind(this));\n this.registerMessageHandler(WSMessageType.MESSAGE_DELIVERED, this.handleMessageDelivered.bind(this));\n this.registerMessageHandler(WSMessageType.MESSAGE_FAILED, this.handleMessageFailed.bind(this));\n this.registerMessageHandler(WSMessageType.APP_MESSAGE, this.handleAppMessage.bind(this));\n this.registerMessageHandler(WSMessageType.ERROR, this.handleError.bind(this));\n }\n\n /**\n * 连接到服务器\n */\n async connect(): Promise<void> {\n if (this.state === \"connecting\" || this.state === \"connected\") {\n this.logger.warn(\"WebSocket already connecting or connected\");\n return;\n }\n\n this.state = \"connecting\";\n this.emitEvent({ type: \"disconnected\", code: 0, reason: \"Reconnecting\" });\n\n try {\n this.logger.info(`Connecting to Lingyao server: ${this.config.url}`);\n\n const wsUrl = this.config.token\n ? `${this.config.url}?token=${encodeURIComponent(this.config.token)}`\n : this.config.url;\n\n this.ws = new WebSocket(wsUrl, {\n headers: {\n \"X-Gateway-ID\": this.config.gatewayId,\n },\n });\n\n this.setupWebSocketHandlers();\n } catch (error) {\n this.state = \"error\";\n this.emitEvent({ type: \"error\", error: error as Error });\n this.scheduleReconnect();\n }\n }\n\n /**\n * 设置 WebSocket 事件处理器\n */\n private setupWebSocketHandlers(): void {\n if (!this.ws) return;\n\n this.ws.on(\"open\", () => {\n this.handleOpen();\n });\n\n this.ws.on(\"message\", async (data: Buffer) => {\n await this.handleMessage(data);\n });\n\n this.ws.on(\"error\", (error) => {\n this.handleErrorEvent(error);\n });\n\n this.ws.on(\"close\", (code: number, reason: Buffer) => {\n this.handleClose(code, reason.toString());\n });\n }\n\n /**\n * 处理连接打开\n */\n private handleOpen(): void {\n this.state = \"connected\";\n this.connectionId = this.generateConnectionId();\n\n this.logger.info(\"WebSocket connected to Lingyao server\", {\n connectionId: this.connectionId,\n });\n\n this.emitEvent({\n type: \"connected\",\n connectionId: this.connectionId!,\n });\n\n // 发送注册消息\n this.sendRegister();\n\n // 启动心跳\n this.startHeartbeat();\n\n // 清除重连定时器\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n /**\n * 处理接收消息\n */\n private async handleMessage(data: Buffer): Promise<void> {\n try {\n const message: WSMessage = JSON.parse(data.toString());\n this.logger.debug(\"Received message from server\", { type: message.type });\n\n const handler = this.messageHandlers.get(message.type);\n if (handler) {\n handler(message);\n } else {\n this.logger.warn(\"No handler for message type\", { type: message.type });\n }\n\n this.emitEvent({ type: \"message\", message });\n } catch (error) {\n this.logger.error(\"Error handling message\", error);\n }\n }\n\n /**\n * 处理连接错误\n */\n private handleErrorEvent(error: Error): void {\n this.logger.error(\"WebSocket error\", error);\n this.state = \"error\";\n this.emitEvent({ type: \"error\", error });\n }\n\n /**\n * 处理连接关闭\n */\n private handleClose(code: number, reason: string): void {\n this.logger.warn(\"WebSocket connection closed\", { code, reason });\n this.state = \"disconnected\";\n this.connectionId = null;\n\n this.stopHeartbeat();\n this.emitEvent({ type: \"disconnected\", code, reason });\n\n // 如果不是正常关闭,尝试重连\n if (code !== 1000) {\n this.scheduleReconnect();\n }\n }\n\n /**\n * 发送注册消息\n */\n private sendRegister(): void {\n const message: RegisterMessage = {\n type: WSMessageType.REGISTER,\n id: this.generateMessageId(),\n timestamp: Date.now(),\n payload: {\n gatewayId: this.config.gatewayId,\n version: \"0.2.0\",\n capabilities: {\n websocket: true,\n compression: false,\n maxMessageSize: 1048576, // 1MB\n },\n },\n };\n\n this.send(message);\n }\n\n /**\n * 处理注册响应\n */\n private handleRegistered(message: WSMessage): void {\n this.logger.info(\"Gateway registered to Lingyao server\", {\n messageId: message.id,\n });\n }\n\n /**\n * 发送心跳\n */\n private sendHeartbeat(): void {\n const message: HeartbeatMessage = {\n type: WSMessageType.HEARTBEAT,\n id: this.generateMessageId(),\n timestamp: Date.now(),\n payload: {\n timestamp: Date.now(),\n status: \"online\",\n },\n };\n\n this.send(message);\n }\n\n /**\n * 处理心跳确认\n */\n private handleHeartbeatAck(_message: WSMessage): void {\n this.logger.debug(\"Heartbeat acknowledged\");\n }\n\n /**\n * 启动心跳\n */\n private startHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n }\n\n this.heartbeatTimer = setInterval(() => {\n if (this.state === \"connected\") {\n this.sendHeartbeat();\n }\n }, this.config.heartbeatInterval);\n }\n\n /**\n * 停止心跳\n */\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n /**\n * 安排重连\n */\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return; // 已经安排了重连\n }\n\n this.logger.info(`Scheduling reconnect in ${this.config.reconnectInterval}ms`);\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, this.config.reconnectInterval);\n }\n\n /**\n * 发送消息到服务器\n */\n send(message: WSMessage): void {\n if (!this.ws || this.state !== \"connected\") {\n throw new Error(\"WebSocket not connected\");\n }\n\n try {\n this.ws.send(JSON.stringify(message));\n this.logger.debug(\"Sent message to server\", { type: message.type });\n } catch (error) {\n this.logger.error(\"Failed to send message\", error);\n throw error;\n }\n }\n\n /**\n * 发送通知到鸿蒙 App\n */\n sendNotification(deviceId: string, notification: any): void {\n const message: SendMessage = {\n type: WSMessageType.SEND_MESSAGE,\n id: this.generateMessageId(),\n timestamp: Date.now(),\n payload: {\n deviceId,\n message: {\n id: this.generateMessageId(),\n type: \"notify_action\",\n timestamp: Date.now(),\n payload: notification,\n },\n },\n };\n\n this.send(message);\n }\n\n /**\n * 处理 App 消息\n */\n private handleAppMessage(message: WSMessage): void {\n if (message.type !== WSMessageType.APP_MESSAGE) return;\n\n const appMessage = message as AppMessage;\n this.logger.info(\"Received message from App\", {\n deviceId: appMessage.payload.deviceId,\n messageType: appMessage.payload.message.type,\n });\n\n if (this.config.messageHandler) {\n // 异步处理,不阻塞 WebSocket\n Promise.resolve(this.config.messageHandler(appMessage)).catch((error: unknown) => {\n this.logger.error(\"Error handling App message\", error);\n });\n }\n }\n\n /**\n * 处理消息发送成功\n */\n private handleMessageDelivered(message: WSMessage): void {\n this.logger.debug(\"Message delivered successfully\", {\n messageId: message.id,\n });\n }\n\n /**\n * 处理消息发送失败\n */\n private handleMessageFailed(message: WSMessage): void {\n this.logger.warn(\"Message delivery failed\", {\n messageId: message.id,\n });\n }\n\n /**\n * 处理服务器错误\n */\n private handleError(message: WSMessage): void {\n this.logger.error(\"Server error\", message);\n }\n\n /**\n * 注册消息处理器\n */\n registerMessageHandler(\n type: string,\n handler: (message: WSMessage) => void\n ): void {\n this.messageHandlers.set(type, handler);\n }\n\n /**\n * 发送事件\n */\n private emitEvent(event: WSClientEvent): void {\n if (this.config.eventHandler) {\n this.config.eventHandler(event);\n }\n }\n\n /**\n * 断开连接\n */\n disconnect(): void {\n this.logger.info(\"Disconnecting WebSocket from Lingyao server\");\n\n this.stopHeartbeat();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, \"Client disconnect\");\n this.ws = null;\n }\n\n this.state = \"disconnected\";\n this.connectionId = null;\n }\n\n /**\n * 获取连接状态\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * 获取连接 ID\n */\n getConnectionId(): string | null {\n return this.connectionId;\n }\n\n /**\n * 是否已连接\n */\n isConnected(): boolean {\n return this.state === \"connected\";\n }\n\n /**\n * 生成消息 ID\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n }\n\n /**\n * 生成连接 ID\n */\n private generateConnectionId(): string {\n return `conn_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n }\n}\n","import type {\n LingyaoAccount,\n DeviceToken,\n DeviceInfo,\n LingyaoRuntime\n} from \"./types.js\";\n\nconst STORAGE_KEY_ACCOUNTS = \"lingyao:accounts\";\nconst STORAGE_KEY_PENDING_PAIRINGS = \"lingyao:pending_pairings\";\n\n/**\n * Account storage and management\n */\nexport class AccountManager {\n private runtime: LingyaoRuntime;\n private accounts: Map<string, LingyaoAccount> = new Map();\n private pendingPairings: Map<string, PairingSession> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n }\n\n /**\n * Initialize account manager from storage\n */\n async initialize(): Promise<void> {\n try {\n const stored = await this.runtime.storage.get(STORAGE_KEY_ACCOUNTS);\n if (stored && Array.isArray(stored)) {\n for (const account of stored) {\n this.accounts.set(account.deviceId, account);\n }\n }\n\n const pending = await this.runtime.storage.get(STORAGE_KEY_PENDING_PAIRINGS);\n if (pending && Array.isArray(pending)) {\n // Clean up expired pairings\n const now = Date.now();\n for (const session of pending) {\n if (session.expiresAt > now) {\n this.pendingPairings.set(session.code, session);\n }\n }\n }\n\n this.runtime.logger.info(\n `AccountManager initialized: ${this.accounts.size} accounts, ${this.pendingPairings.size} pending pairings`\n );\n } catch (error) {\n this.runtime.logger.error(\"Failed to initialize AccountManager\", error);\n }\n }\n\n /**\n * Get account by device ID\n */\n getAccount(deviceId: string): LingyaoAccount | undefined {\n return this.accounts.get(deviceId);\n }\n\n /**\n * Get account by device token\n */\n getAccountByToken(token: string): LingyaoAccount | undefined {\n for (const account of this.accounts.values()) {\n if (account.deviceToken.token === token) {\n return account;\n }\n }\n return undefined;\n }\n\n /**\n * Get all active accounts\n */\n getActiveAccounts(): LingyaoAccount[] {\n return Array.from(this.accounts.values()).filter(\n (acc) => acc.status === \"active\"\n );\n }\n\n /**\n * Create a new pairing session\n */\n async createPairingSession(\n code: string,\n expiresAt: number\n ): Promise<void> {\n const session: PairingSession = {\n code,\n createdAt: Date.now(),\n expiresAt,\n };\n\n this.pendingPairings.set(code, session);\n await this.savePendingPairings();\n }\n\n /**\n * Get pairing session by code\n */\n getPairingSession(code: string): PairingSession | undefined {\n return this.pendingPairings.get(code);\n }\n\n /**\n * Remove a pending pairing (e.g. expired or cancelled)\n */\n async deletePendingPairing(code: string): Promise<void> {\n if (!this.pendingPairings.delete(code)) {\n return;\n }\n await this.savePendingPairings();\n }\n\n /**\n * Confirm pairing and create account\n */\n async confirmPairing(\n pairingCode: string,\n deviceToken: DeviceToken,\n deviceInfo: DeviceInfo\n ): Promise<LingyaoAccount | null> {\n const session = this.pendingPairings.get(pairingCode);\n if (!session) {\n return null;\n }\n\n const now = Date.now();\n if (session.expiresAt < now) {\n this.pendingPairings.delete(pairingCode);\n await this.savePendingPairings();\n return null;\n }\n\n const account: LingyaoAccount = {\n deviceId: deviceToken.deviceId,\n deviceInfo,\n deviceToken,\n pairedAt: now,\n lastSeenAt: now,\n status: \"active\",\n };\n\n this.accounts.set(deviceToken.deviceId, account);\n this.pendingPairings.delete(pairingCode);\n\n await Promise.all([\n this.saveAccounts(),\n this.savePendingPairings(),\n ]);\n\n this.runtime.logger.info(\n `Account paired: ${deviceToken.deviceId} (${deviceInfo.name})`\n );\n\n return account;\n }\n\n /**\n * Update account's last seen timestamp\n */\n async updateLastSeen(deviceId: string): Promise<void> {\n const account = this.accounts.get(deviceId);\n if (account) {\n account.lastSeenAt = Date.now();\n await this.saveAccounts();\n }\n }\n\n /**\n * Revoke an account\n */\n async revokeAccount(deviceId: string): Promise<boolean> {\n const account = this.accounts.get(deviceId);\n if (!account) {\n return false;\n }\n\n account.status = \"revoked\";\n await this.saveAccounts();\n\n this.runtime.logger.info(`Account revoked: ${deviceId}`);\n return true;\n }\n\n /**\n * Refresh device token\n */\n async refreshDeviceToken(\n deviceId: string,\n newToken: DeviceToken\n ): Promise<boolean> {\n const account = this.accounts.get(deviceId);\n if (!account) {\n return false;\n }\n\n account.deviceToken = newToken;\n await this.saveAccounts();\n\n this.runtime.logger.info(`Token refreshed for: ${deviceId}`);\n return true;\n }\n\n /**\n * Clean up expired accounts\n */\n async cleanupExpired(): Promise<void> {\n const now = Date.now();\n const expired: string[] = [];\n\n for (const [deviceId, account] of this.accounts.entries()) {\n if (account.deviceToken.expiresAt < now) {\n expired.push(deviceId);\n }\n }\n\n for (const deviceId of expired) {\n this.accounts.delete(deviceId);\n }\n\n if (expired.length > 0) {\n await this.saveAccounts();\n this.runtime.logger.info(`Cleaned up ${expired.length} expired accounts`);\n }\n }\n\n /**\n * Save accounts to storage\n */\n private async saveAccounts(): Promise<void> {\n const accounts = Array.from(this.accounts.values());\n await this.runtime.storage.set(STORAGE_KEY_ACCOUNTS, accounts);\n }\n\n /**\n * Save pending pairings to storage\n */\n private async savePendingPairings(): Promise<void> {\n const sessions = Array.from(this.pendingPairings.values());\n await this.runtime.storage.set(STORAGE_KEY_PENDING_PAIRINGS, sessions);\n }\n}\n\ninterface PairingSession {\n code: string;\n createdAt: number;\n expiresAt: number;\n}\n","import { createHmac, createHash, randomBytes, timingSafeEqual } from \"crypto\";\nimport type { LingyaoMessage } from \"./types.js\";\n\n/**\n * Cryptographic utilities for message signing and verification\n */\nexport class CryptoManager {\n /**\n * Sign a message with HMAC-SHA256\n */\n static signMessage(message: LingyaoMessage, secret: string): string {\n const messageString = this.prepareMessageForSigning(message);\n return createHmac(\"sha256\", secret)\n .update(messageString)\n .digest(\"base64\");\n }\n\n /**\n * Verify a message signature\n */\n static verifyMessage(\n message: LingyaoMessage,\n signature: string,\n secret: string\n ): boolean {\n try {\n const expectedSignature = this.signMessage(message, secret);\n\n // Use timing-safe comparison to prevent timing attacks\n const expectedBuffer = Buffer.from(expectedSignature);\n const providedBuffer = Buffer.from(signature);\n\n if (expectedBuffer.length !== providedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(expectedBuffer, providedBuffer);\n } catch {\n return false;\n }\n }\n\n /**\n * Sign any data string\n */\n static sign(data: string, secret: string): string {\n return createHmac(\"sha256\", secret)\n .update(data)\n .digest(\"base64\");\n }\n\n /**\n * Verify data signature\n */\n static verify(\n data: string,\n signature: string,\n secret: string\n ): boolean {\n try {\n const expectedSignature = this.sign(data, secret);\n const expectedBuffer = Buffer.from(expectedSignature);\n const providedBuffer = Buffer.from(signature);\n\n if (expectedBuffer.length !== providedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(expectedBuffer, providedBuffer);\n } catch {\n return false;\n }\n }\n\n /**\n * Generate a random nonce\n */\n static generateNonce(): string {\n return randomBytes(16).toString(\"hex\");\n }\n\n /**\n * Hash data using SHA-256\n */\n static hash(data: string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n }\n\n /**\n * Generate a cryptographically random ID\n */\n static generateId(): string {\n return randomBytes(16).toString(\"hex\");\n }\n\n /**\n * Prepare message for signing by serializing in a deterministic way\n */\n private static prepareMessageForSigning(message: LingyaoMessage): string {\n // Create a canonical string representation\n const parts = [\n message.id,\n message.type,\n message.timestamp.toString(),\n message.from,\n message.to,\n JSON.stringify(message.payload),\n ];\n\n return parts.join(\"|\");\n }\n\n /**\n * Encrypt data (for future use)\n */\n static encrypt(data: string, _key: string): {\n encrypted: string;\n iv: string;\n } {\n const iv = randomBytes(16);\n // Note: This is a placeholder for future encryption implementation\n // In production, use proper encryption like AES-256-GCM\n return {\n encrypted: data, // Placeholder\n iv: iv.toString(\"hex\"),\n };\n }\n\n /**\n * Decrypt data (for future use)\n */\n static decrypt(encrypted: string, _key: string, _iv: string): string {\n // Note: This is a placeholder for future decryption implementation\n return encrypted;\n }\n\n /**\n * Derive a key from a password and salt\n */\n static deriveKey(password: string, salt: string): string {\n return createHmac(\"sha256\", salt)\n .update(password)\n .digest(\"hex\");\n }\n\n /**\n * Generate a fingerprint for a device\n */\n static generateDeviceFingerprint(deviceInfo: Record<string, unknown>): string {\n const data = JSON.stringify(deviceInfo, Object.keys(deviceInfo).sort());\n return this.hash(data).substring(0, 16);\n }\n\n /**\n * Verify message timestamp is within acceptable range\n */\n static verifyTimestamp(\n timestamp: number,\n maxDriftSeconds: number = 300\n ): boolean {\n const now = Date.now();\n const drift = Math.abs(now - timestamp);\n return drift <= maxDriftSeconds * 1000;\n }\n\n /**\n * Check if a message is a replay attack\n */\n static checkReplay(\n messageId: string,\n seenMessages: Set<string>,\n _maxAge: number = 3600000 // 1 hour\n ): boolean {\n return seenMessages.has(messageId);\n }\n\n /**\n * Mark a message as seen to prevent replay\n */\n static markMessageSeen(\n messageId: string,\n seenMessages: Set<string>,\n _maxAge: number = 3600000\n ): void {\n seenMessages.add(messageId);\n\n // Clean up old entries\n if (seenMessages.size > 10000) {\n // Keep set size manageable\n const entries = Array.from(seenMessages);\n // In production, use a proper TTL-based cache\n // For now, clear half the entries if we get too large\n for (let i = 0; i < entries.length / 2; i++) {\n seenMessages.delete(entries[i]);\n }\n }\n }\n}\n","import type {\n LingyaoRuntime,\n LingyaoMessage,\n DiarySyncPayload,\n MemorySyncPayload,\n SyncRequest,\n SyncResponse\n} from \"./types.js\";\nimport { MessageType } from \"./types.js\";\nimport { AccountManager } from \"./accounts.js\";\nimport { CryptoManager } from \"./crypto.js\";\n\n/**\n * Agent message format - messages passed directly to Agent\n */\nexport interface AgentMessage {\n id: string;\n type: \"diary\" | \"memory\" | \"heartbeat\";\n from: string;\n deviceId: string;\n content: string;\n metadata: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Message handler callback for delivering messages to Agent\n */\nexport type MessageHandler = (message: AgentMessage) => void | Promise<void>;\n\n/**\n * Message queue entry for polling\n */\ninterface QueuedMessage {\n message: LingyaoMessage;\n deviceId: string;\n createdAt: number;\n delivered: boolean;\n}\n\n/**\n * Message Processor - Handles incoming messages and routes them to Agent\n */\nexport class MessageProcessor {\n private runtime: LingyaoRuntime;\n private accountManager: AccountManager;\n private messageQueue: Map<string, QueuedMessage[]> = new Map();\n private seenMessages: Set<string> = new Set();\n private messageHandler: MessageHandler | null = null;\n private readonly maxQueueSize: number = 100;\n\n constructor(\n runtime: LingyaoRuntime,\n accountManager: AccountManager\n ) {\n this.runtime = runtime;\n this.accountManager = accountManager;\n }\n\n /**\n * Initialize the message processor\n */\n async initialize(): Promise<void> {\n this.runtime.logger.info(\"Message Processor initialized\");\n }\n\n /**\n * Set the message handler for delivering messages to Agent\n */\n setMessageHandler(handler: MessageHandler): void {\n this.messageHandler = handler;\n }\n\n /**\n * Get the currently registered Agent message handler.\n */\n getMessageHandler(): MessageHandler | null {\n return this.messageHandler;\n }\n\n /**\n * Deliver a normalized message directly to the registered Agent handler.\n */\n async deliverToAgent(message: AgentMessage): Promise<void> {\n if (!this.messageHandler) {\n this.runtime.logger.warn(\"No message handler set, message not delivered to Agent\");\n return;\n }\n\n await this.messageHandler(message);\n }\n\n /**\n * Process sync request from app\n */\n async processSync(\n deviceId: string,\n request: SyncRequest\n ): Promise<SyncResponse> {\n const account = this.accountManager.getAccount(deviceId);\n if (!account) {\n return {\n processed: [],\n failed: request.messages.map((m) => ({\n id: m.id,\n error: \"Device not found\",\n })),\n };\n }\n\n const processed: string[] = [];\n const failed: Array<{ id: string; error: string }> = [];\n\n for (const message of request.messages) {\n try {\n // Validate message signature if present\n if (message.signature) {\n const isValid = CryptoManager.verifyMessage(\n message,\n message.signature,\n account.deviceToken.secret\n );\n\n if (!isValid) {\n failed.push({ id: message.id, error: \"Invalid signature\" });\n continue;\n }\n }\n\n // Check for duplicates\n if (this.isMessageSeen(message.id)) {\n this.runtime.logger.debug(`Duplicate message ignored: ${message.id}`);\n processed.push(message.id);\n continue;\n }\n\n // Verify timestamp\n if (!CryptoManager.verifyTimestamp(message.timestamp)) {\n failed.push({ id: message.id, error: \"Invalid timestamp\" });\n continue;\n }\n\n // Process message based on type\n const result = await this.processMessage(deviceId, message);\n\n if (result.success) {\n processed.push(message.id);\n this.markMessageSeen(message.id);\n } else {\n failed.push({ id: message.id, error: result.error ?? \"Processing failed\" });\n }\n } catch (error) {\n this.runtime.logger.error(`Error processing message ${message.id}`, error);\n failed.push({ id: message.id, error: \"Internal error\" });\n }\n }\n\n return { processed, failed };\n }\n\n /**\n * Process a single message\n */\n private async processMessage(\n deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n this.runtime.logger.debug(\n `Processing message ${message.type} from ${deviceId}`\n );\n\n switch (message.type) {\n case MessageType.SYNC_DIARY:\n return await this.processDiarySync(deviceId, message);\n\n case MessageType.SYNC_MEMORY:\n return await this.processMemorySync(deviceId, message);\n\n case MessageType.SYNC_ACK:\n return await this.processSyncAck(deviceId, message);\n\n case MessageType.HEARTBEAT:\n return await this.processHeartbeat(deviceId, message);\n\n default:\n return { success: false, error: \"Unknown message type\" };\n }\n }\n\n /**\n * Process diary sync - Pass directly to Agent\n */\n private async processDiarySync(\n deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n const payload = message.payload as DiarySyncPayload;\n\n // Create Agent message format\n const agentMessage: AgentMessage = {\n id: message.id,\n type: \"diary\",\n from: `lingyao:${deviceId}`,\n deviceId,\n content: payload.content,\n metadata: {\n diaryId: payload.diaryId,\n title: payload.title,\n emotion: payload.emotion,\n tags: payload.tags,\n mediaUrls: payload.mediaUrls,\n createdAt: payload.createdAt,\n updatedAt: payload.updatedAt,\n },\n timestamp: message.timestamp,\n };\n\n // Pass directly to Agent via message handler\n await this.deliverToAgent(agentMessage);\n\n this.runtime.logger.info(\n `Diary message passed to Agent: ${payload.diaryId} from ${deviceId}`\n );\n\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Diary sync error\", error);\n return { success: false, error: \"Failed to sync diary\" };\n }\n }\n\n /**\n * Process memory sync - Pass directly to Agent\n */\n private async processMemorySync(\n deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n const payload = message.payload as MemorySyncPayload;\n\n // Create Agent message format\n const agentMessage: AgentMessage = {\n id: message.id,\n type: \"memory\",\n from: `lingyao:${deviceId}`,\n deviceId,\n content: payload.content,\n metadata: {\n memoryId: payload.memoryId,\n memoryType: payload.type,\n importance: payload.importance,\n ...payload.metadata,\n timestamp: payload.timestamp,\n },\n timestamp: message.timestamp,\n };\n\n // Pass directly to Agent via message handler\n await this.deliverToAgent(agentMessage);\n\n this.runtime.logger.info(\n `Memory message passed to Agent: ${payload.memoryId} from ${deviceId}`\n );\n\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Memory sync error\", error);\n return { success: false, error: \"Failed to sync memory\" };\n }\n }\n\n /**\n * Process sync acknowledgment\n */\n private async processSyncAck(\n _deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n // Handle acknowledgment of received messages\n this.runtime.logger.debug(`Sync ack received: ${message.id}`);\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Sync ack error\", error);\n return { success: false, error: \"Failed to process ack\" };\n }\n }\n\n /**\n * Process heartbeat\n */\n private async processHeartbeat(\n deviceId: string,\n _message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n await this.accountManager.updateLastSeen(deviceId);\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Heartbeat error\", error);\n return { success: false, error: \"Failed to process heartbeat\" };\n }\n }\n\n /**\n * Poll for new messages (long-polling)\n */\n async pollMessages(\n deviceId: string,\n timeout: number = 30000\n ): Promise<LingyaoMessage[]> {\n return new Promise((resolve) => {\n const startTime = Date.now();\n const checkInterval = 100; // Check every 100ms\n\n const checkForMessages = () => {\n const queue = this.messageQueue.get(deviceId);\n const messages = queue?.filter((m) => !m.delivered) ?? [];\n\n if (messages.length > 0) {\n // Mark messages as delivered\n for (const msg of messages) {\n msg.delivered = true;\n }\n resolve(messages.map((m) => m.message));\n return;\n }\n\n const elapsed = Date.now() - startTime;\n if (elapsed >= timeout) {\n resolve([]);\n return;\n }\n\n setTimeout(checkForMessages, checkInterval);\n };\n\n checkForMessages();\n });\n }\n\n /**\n * Queue a message for a device\n */\n queueMessage(deviceId: string, message: LingyaoMessage): boolean {\n let queue = this.messageQueue.get(deviceId);\n\n if (!queue) {\n queue = [];\n this.messageQueue.set(deviceId, queue);\n }\n\n // Check queue size limit\n if (queue.length >= this.maxQueueSize) {\n // Remove oldest undelivered message\n const oldestIndex = queue.findIndex((m) => !m.delivered);\n if (oldestIndex >= 0) {\n queue.splice(oldestIndex, 1);\n } else {\n this.runtime.logger.warn(\n `Message queue full for ${deviceId}, dropping message`\n );\n return false;\n }\n }\n\n queue.push({\n message,\n deviceId,\n createdAt: Date.now(),\n delivered: false,\n });\n\n this.runtime.logger.debug(\n `Message queued for ${deviceId}: ${message.id}`\n );\n\n return true;\n }\n\n /**\n * Acknowledge messages\n */\n async acknowledgeMessages(messageIds: string[]): Promise<void> {\n for (const deviceId of this.messageQueue.keys()) {\n const queue = this.messageQueue.get(deviceId);\n if (!queue) continue;\n\n for (const msgId of messageIds) {\n const index = queue.findIndex((m) => m.message.id === msgId);\n if (index >= 0) {\n queue.splice(index, 1);\n }\n }\n\n if (queue.length === 0) {\n this.messageQueue.delete(deviceId);\n }\n }\n\n this.runtime.logger.debug(`Acknowledged ${messageIds.length} messages`);\n }\n\n /**\n * Check if message has been seen (deduplication)\n */\n private isMessageSeen(messageId: string): boolean {\n return this.seenMessages.has(messageId);\n }\n\n /**\n * Mark message as seen\n */\n private markMessageSeen(messageId: string): void {\n this.seenMessages.add(messageId);\n\n // Clean up old entries periodically\n if (this.seenMessages.size > 10000) {\n const entries = Array.from(this.seenMessages);\n for (let i = 0; i < entries.length / 2; i++) {\n this.seenMessages.delete(entries[i]);\n }\n }\n }\n\n /**\n * Get queue size for a device\n */\n getQueueSize(deviceId: string): number {\n const queue = this.messageQueue.get(deviceId);\n return queue?.filter((m) => !m.delivered).length ?? 0;\n }\n\n /**\n * Get total queue size\n */\n getTotalQueueSize(): number {\n let total = 0;\n for (const queue of this.messageQueue.values()) {\n total += queue.filter((m) => !m.delivered).length;\n }\n return total;\n }\n}\n","import type { LingyaoRuntime, HealthStatus } from \"./types.js\";\n\n/**\n * Probe status levels\n */\nexport enum ProbeStatus {\n HEALTHY = \"healthy\",\n DEGRADED = \"degraded\",\n UNHEALTHY = \"unhealthy\",\n}\n\n/**\n * Health check result\n */\nexport interface HealthCheckResult {\n status: ProbeStatus;\n checks: Map<string, CheckResult>;\n timestamp: number;\n}\n\n/**\n * Individual check result\n */\nexport interface CheckResult {\n passed: boolean;\n message?: string;\n duration: number;\n error?: Error;\n}\n\n/**\n * Channel status for reporting\n */\nexport interface ChannelStatus {\n configured: boolean;\n running: boolean;\n lastError?: string;\n activeAccounts: number;\n uptime: number;\n status: ProbeStatus;\n}\n\n/**\n * Probe - Channel health status and monitoring\n */\nexport class Probe {\n private runtime: LingyaoRuntime;\n private startTime: number = Date.now();\n private lastError: string | null = null;\n private lastErrorTime: number | null = null;\n private errorCounts: Map<string, number> = new Map();\n private healthChecks: Map<string, HealthCheckFn> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n\n // Register default health checks\n this.registerHealthCheck(\"uptime\", this.checkUptime);\n this.registerHealthCheck(\"errors\", this.checkErrors);\n }\n\n /**\n * Register a custom health check\n */\n registerHealthCheck(name: string, check: HealthCheckFn): void {\n this.healthChecks.set(name, check);\n }\n\n /**\n * Run all health checks\n */\n async runHealthChecks(): Promise<HealthCheckResult> {\n const checks = new Map<string, CheckResult>();\n let overallStatus = ProbeStatus.HEALTHY;\n\n for (const [name, checkFn] of this.healthChecks.entries()) {\n const start = Date.now();\n\n try {\n const result = await checkFn();\n const duration = Date.now() - start;\n\n checks.set(name, {\n passed: result.passed,\n message: result.message,\n duration,\n });\n\n if (!result.passed && overallStatus === ProbeStatus.HEALTHY) {\n overallStatus = ProbeStatus.DEGRADED;\n }\n } catch (error) {\n const duration = Date.now() - start;\n checks.set(name, {\n passed: false,\n message: \"Health check failed with exception\",\n duration,\n error: error as Error,\n });\n overallStatus = ProbeStatus.UNHEALTHY;\n }\n }\n\n return {\n status: overallStatus,\n checks,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Get channel status for reporting\n */\n getChannelStatus(\n configured: boolean,\n running: boolean,\n activeAccounts: number = 0\n ): ChannelStatus {\n return {\n configured,\n running,\n lastError: this.lastError ?? undefined,\n activeAccounts,\n uptime: Date.now() - this.startTime,\n status: running ? ProbeStatus.HEALTHY : ProbeStatus.UNHEALTHY,\n };\n }\n\n /**\n * Get health status for API endpoint\n */\n async getHealthStatus(\n activeConnections: number = 0,\n queuedMessages: number = 0\n ): Promise<HealthStatus> {\n const healthResult = await this.runHealthChecks();\n\n let status: \"healthy\" | \"degraded\" | \"unhealthy\";\n switch (healthResult.status) {\n case ProbeStatus.HEALTHY:\n status = \"healthy\";\n break;\n case ProbeStatus.DEGRADED:\n status = \"degraded\";\n break;\n case ProbeStatus.UNHEALTHY:\n status = \"unhealthy\";\n break;\n }\n\n return {\n status,\n uptime: Date.now() - this.startTime,\n activeConnections,\n queuedMessages,\n lastError: this.lastError ?? undefined,\n };\n }\n\n /**\n * Record an error\n */\n recordError(error: string, category: string = \"general\"): void {\n this.lastError = error;\n this.lastErrorTime = Date.now();\n\n const count = this.errorCounts.get(category) ?? 0;\n this.errorCounts.set(category, count + 1);\n\n this.runtime.logger.error(`[${category}] ${error}`);\n }\n\n /**\n * Get last error\n */\n getLastError(): string | null {\n // Return error if it occurred within the last 5 minutes\n if (this.lastErrorTime && Date.now() - this.lastErrorTime < 300000) {\n return this.lastError;\n }\n return null;\n }\n\n /**\n * Clear last error\n */\n clearLastError(): void {\n this.lastError = null;\n this.lastErrorTime = null;\n }\n\n /**\n * Get error counts by category\n */\n getErrorCounts(): Record<string, number> {\n return Object.fromEntries(this.errorCounts);\n }\n\n /**\n * Reset error counts\n */\n resetErrorCounts(): void {\n this.errorCounts.clear();\n }\n\n /**\n * Get uptime in milliseconds\n */\n getUptime(): number {\n return Date.now() - this.startTime;\n }\n\n /**\n * Get uptime formatted as human-readable string\n */\n getUptimeString(): string {\n const uptime = this.getUptime();\n const seconds = Math.floor(uptime / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d ${hours % 24}h ${minutes % 60}m`;\n } else if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n } else if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n } else {\n return `${seconds}s`;\n }\n }\n\n /**\n * Health check: uptime\n */\n private checkUptime = async (): Promise<CheckResult> => {\n const uptime = this.getUptime();\n // Consider healthy if uptime > 0\n return {\n passed: uptime > 0,\n message: `Uptime: ${this.getUptimeString()}`,\n duration: 0,\n };\n };\n\n /**\n * Health check: errors\n */\n private checkErrors = async (): Promise<CheckResult> => {\n const recentErrors = this.lastErrorTime && Date.now() - this.lastErrorTime < 60000;\n\n return {\n passed: !recentErrors,\n message: recentErrors\n ? `Recent error: ${this.lastError}`\n : \"No recent errors\",\n duration: 0,\n };\n };\n\n /**\n * Create status adapter for OpenClaw integration\n */\n createStatusAdapter(configured: boolean) {\n return {\n getStatus: async (\n running: boolean,\n activeAccounts: number = 0,\n activeConnections: number = 0,\n queuedMessages: number = 0\n ) => ({\n ...this.getChannelStatus(configured, running, activeAccounts),\n activeConnections,\n queuedMessages,\n }),\n };\n }\n}\n\n/**\n * Health check function signature\n */\nexport type HealthCheckFn = () => Promise<{\n passed: boolean;\n message?: string;\n}>;\n","/**\n * 监控和指标收集模块\n */\n\nimport type { LingyaoRuntime } from './types.js';\n\n/**\n * 指标类型\n */\nexport enum MetricType {\n COUNTER = 'counter',\n GAUGE = 'gauge',\n HISTOGRAM = 'histogram',\n}\n\n/**\n * 指标数据\n */\nexport interface MetricData {\n name: string;\n type: MetricType;\n value: number;\n timestamp: number;\n labels?: Record<string, string>;\n}\n\n/**\n * 指标配置\n */\nexport interface MetricConfig {\n name: string;\n type: MetricType;\n description?: string;\n labels?: string[];\n buckets?: number[];\n}\n\n/**\n * 监控指标管理器\n */\nexport class MetricsManager {\n private metrics: Map<string, MetricData> = new Map();\n private counters: Map<string, number> = new Map();\n private gauges: Map<string, number> = new Map();\n private histograms: Map<string, number[]> = new Map();\n private histogramBuckets: Map<string, number[]> = new Map();\n\n constructor(_runtime: LingyaoRuntime) {\n // 初始化默认指标\n this.initializeDefaultMetrics();\n }\n\n /**\n * 初始化默认指标\n */\n private initializeDefaultMetrics(): void {\n // 连接指标\n this.declareMetric({\n name: 'lingyao_connection_count',\n type: MetricType.GAUGE,\n description: '当前活跃连接数',\n });\n\n this.declareMetric({\n name: 'lingyao_connection_total',\n type: MetricType.COUNTER,\n description: '总连接次数',\n });\n\n this.declareMetric({\n name: 'lingyao_disconnection_total',\n type: MetricType.COUNTER,\n description: '总断开连接次数',\n });\n\n // 消息指标\n this.declareMetric({\n name: 'lingyao_message_total',\n type: MetricType.COUNTER,\n description: '总消息数',\n labels: ['direction', 'type'],\n });\n\n this.declareMetric({\n name: 'lingyao_message_failed_total',\n type: MetricType.COUNTER,\n description: '失败消息总数',\n labels: ['direction', 'reason'],\n });\n\n // 延迟指标\n this.declareMetric({\n name: 'lingyao_message_latency',\n type: MetricType.HISTOGRAM,\n description: '消息处理延迟',\n buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],\n });\n\n // 错误指标\n this.declareMetric({\n name: 'lingyao_error_total',\n type: MetricType.COUNTER,\n description: '错误总数',\n labels: ['type', 'severity'],\n });\n\n // 心跳指标\n this.declareMetric({\n name: 'lingyao_heartbeat_total',\n type: MetricType.COUNTER,\n description: '心跳总数',\n });\n\n this.declareMetric({\n name: 'lingyao_heartbeat_missed_total',\n type: MetricType.COUNTER,\n description: '心跳丢失总数',\n });\n\n // 重连指标\n this.declareMetric({\n name: 'lingyao_reconnect_total',\n type: MetricType.COUNTER,\n description: '重连次数',\n });\n\n // 队列指标\n this.declareMetric({\n name: 'lingyao_queue_size',\n type: MetricType.GAUGE,\n description: '当前队列大小',\n });\n }\n\n /**\n * 声明指标\n */\n declareMetric(config: MetricConfig): void {\n if (config.type === MetricType.HISTOGRAM && config.buckets) {\n this.histogramBuckets.set(config.name, config.buckets);\n }\n }\n\n /**\n * 计数器增加\n */\n incrementCounter(name: string, value: number = 1, labels?: Record<string, string>): void {\n const current = this.counters.get(name) || 0;\n this.counters.set(name, current + value);\n\n this.recordMetric({\n name,\n type: MetricType.COUNTER,\n value: current + value,\n timestamp: Date.now(),\n labels,\n });\n }\n\n /**\n * 设置仪表盘值\n */\n setGauge(name: string, value: number, labels?: Record<string, string>): void {\n this.gauges.set(name, value);\n\n this.recordMetric({\n name,\n type: MetricType.GAUGE,\n value,\n timestamp: Date.now(),\n labels,\n });\n }\n\n /**\n * 记录直方图值\n */\n recordHistogram(name: string, value: number, labels?: Record<string, string>): void {\n let values = this.histograms.get(name);\n if (!values) {\n values = [];\n this.histograms.set(name, values);\n }\n values.push(value);\n\n this.recordMetric({\n name,\n type: MetricType.HISTOGRAM,\n value,\n timestamp: Date.now(),\n labels,\n });\n }\n\n /**\n * 记录指标\n */\n private recordMetric(data: MetricData): void {\n this.metrics.set(`${data.name}_${Date.now()}`, data);\n\n // 限制指标历史数量\n if (this.metrics.size > 10000) {\n const entries = Array.from(this.metrics.entries());\n entries.sort((a, b) => a[1].timestamp - b[1].timestamp);\n\n // 删除最旧的 10%\n for (let i = 0; i < 1000; i++) {\n this.metrics.delete(entries[i][0]);\n }\n }\n }\n\n /**\n * 获取所有指标\n */\n getMetrics(): MetricData[] {\n return Array.from(this.metrics.values());\n }\n\n /**\n * 获取特定指标的当前值\n */\n getMetricValue(name: string): number | undefined {\n if (this.counters.has(name)) {\n return this.counters.get(name);\n }\n if (this.gauges.has(name)) {\n return this.gauges.get(name);\n }\n return undefined;\n }\n\n /**\n * 获取直方图统计数据\n */\n getHistogramStats(name: string): {\n count: number;\n min: number;\n max: number;\n avg: number;\n p50: number;\n p95: number;\n p99: number;\n } | null {\n const values = this.histograms.get(name);\n if (!values || values.length === 0) {\n return null;\n }\n\n const sorted = [...values].sort((a, b) => a - b);\n const count = sorted.length;\n const sum = sorted.reduce((a, b) => a + b, 0);\n\n return {\n count,\n min: sorted[0],\n max: sorted[count - 1],\n avg: sum / count,\n p50: sorted[Math.floor(count * 0.5)],\n p95: sorted[Math.floor(count * 0.95)],\n p99: sorted[Math.floor(count * 0.99)],\n };\n }\n\n /**\n * 重置所有指标\n */\n reset(): void {\n this.metrics.clear();\n this.counters.clear();\n this.gauges.clear();\n this.histograms.clear();\n }\n\n /**\n * 生成 Prometheus 格式的指标导出\n */\n exportPrometheus(): string {\n const lines: string[] = [];\n\n // 导出计数器和仪表盘\n for (const [name, value] of [...this.counters, ...this.gauges]) {\n lines.push(`${name} ${value}`);\n }\n\n // 导出直方图\n for (const [name] of this.histograms) {\n const stats = this.getHistogramStats(name);\n if (stats) {\n lines.push(`${name}_count ${stats.count}`);\n lines.push(`${name}_sum ${stats.avg * stats.count}`);\n lines.push(`${name}_bucket{le=\\\"+Inf\\\"} ${stats.count}`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n\n/**\n * 监控事件\n */\nexport enum MonitoringEvent {\n // 连接事件\n CONNECTION_OPEN = 'connection_open',\n CONNECTION_CLOSE = 'connection_close',\n CONNECTION_ERROR = 'connection_error',\n RECONNECT = 'reconnect',\n\n // 消息事件\n MESSAGE_RECEIVED = 'message_received',\n MESSAGE_SENT = 'message_sent',\n MESSAGE_DELIVERED = 'message_delivered',\n MESSAGE_FAILED = 'message_failed',\n\n // 心跳事件\n HEARTBEAT_SENT = 'heartbeat_sent',\n HEARTBEAT_RECEIVED = 'heartbeat_received',\n HEARTBEAT_MISSED = 'heartbeat_missed',\n\n // 错误事件\n ERROR_OCCURRED = 'error_occurred',\n}\n\n/**\n * 监控事件数据\n */\nexport interface MonitoringEventData {\n event: MonitoringEvent;\n timestamp: number;\n data: Record<string, unknown>;\n}\n\n/**\n * 监控器\n */\nexport class Monitor {\n private runtime: LingyaoRuntime;\n private metrics: MetricsManager;\n private eventHandlers: Map<MonitoringEvent, ((data: MonitoringEventData) => void)[]> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n this.metrics = new MetricsManager(runtime);\n }\n\n /**\n * 记录事件\n */\n recordEvent(event: MonitoringEvent, data: Record<string, unknown> = {}): void {\n const eventData: MonitoringEventData = {\n event,\n timestamp: Date.now(),\n data,\n };\n\n // 更新指标\n this.updateMetricsForEvent(event, data);\n\n // 触发事件处理器\n const handlers = this.eventHandlers.get(event) || [];\n handlers.forEach(handler => {\n try {\n handler(eventData);\n } catch (error) {\n this.runtime.logger.error('Error in monitoring event handler', error);\n }\n });\n\n // 记录日志\n this.runtime.logger.debug(`Monitoring event: ${event}`, data);\n }\n\n /**\n * 为事件更新指标\n */\n private updateMetricsForEvent(event: MonitoringEvent, data: Record<string, unknown>): void {\n switch (event) {\n case MonitoringEvent.CONNECTION_OPEN:\n this.metrics.incrementCounter('lingyao_connection_total');\n this.metrics.setGauge('lingyao_connection_count', (data.activeConnections as number) || 1);\n break;\n\n case MonitoringEvent.CONNECTION_CLOSE:\n this.metrics.incrementCounter('lingyao_disconnection_total');\n this.metrics.setGauge('lingyao_connection_count', (data.activeConnections as number) || 0);\n break;\n\n case MonitoringEvent.RECONNECT:\n this.metrics.incrementCounter('lingyao_reconnect_total');\n break;\n\n case MonitoringEvent.MESSAGE_RECEIVED:\n this.metrics.incrementCounter('lingyao_message_total', 1, {\n direction: 'in',\n type: (data.messageType as string) || 'unknown',\n });\n break;\n\n case MonitoringEvent.MESSAGE_SENT:\n this.metrics.incrementCounter('lingyao_message_total', 1, {\n direction: 'out',\n type: (data.messageType as string) || 'unknown',\n });\n break;\n\n case MonitoringEvent.MESSAGE_DELIVERED:\n // 记录延迟\n if (data.latency) {\n this.metrics.recordHistogram('lingyao_message_latency', data.latency as number);\n }\n break;\n\n case MonitoringEvent.MESSAGE_FAILED:\n this.metrics.incrementCounter('lingyao_message_failed_total', 1, {\n direction: (data.direction as string) || 'unknown',\n reason: (data.reason as string) || 'unknown',\n });\n break;\n\n case MonitoringEvent.HEARTBEAT_SENT:\n this.metrics.incrementCounter('lingyao_heartbeat_total');\n break;\n\n case MonitoringEvent.HEARTBEAT_MISSED:\n this.metrics.incrementCounter('lingyao_heartbeat_missed_total');\n break;\n\n case MonitoringEvent.ERROR_OCCURRED:\n this.metrics.incrementCounter('lingyao_error_total', 1, {\n type: (data.errorType as string) || 'unknown',\n severity: (data.severity as string) || 'medium',\n });\n break;\n }\n }\n\n /**\n * 注册事件处理器\n */\n on(event: MonitoringEvent, handler: (data: MonitoringEventData) => void): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, []);\n }\n this.eventHandlers.get(event)!.push(handler);\n }\n\n /**\n * 移除事件处理器\n */\n off(event: MonitoringEvent, handler: (data: MonitoringEventData) => void): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n }\n }\n\n /**\n * 获取指标管理器\n */\n getMetrics(): MetricsManager {\n return this.metrics;\n }\n\n /**\n * 获取摘要报告\n */\n getSummary(): {\n uptime: number;\n connections: number;\n messages: {\n sent: number;\n received: number;\n failed: number;\n };\n errors: number;\n heartbeats: {\n sent: number;\n missed: number;\n };\n } {\n return {\n uptime: Date.now() - (this.runtime as any).startTime,\n connections: this.metrics.getMetricValue('lingyao_connection_total') || 0,\n messages: {\n sent: this.metrics.getMetricValue('lingyao_message_total') || 0,\n received: this.metrics.getMetricValue('lingyao_message_total') || 0,\n failed: this.metrics.getMetricValue('lingyao_message_failed_total') || 0,\n },\n errors: this.metrics.getMetricValue('lingyao_error_total') || 0,\n heartbeats: {\n sent: this.metrics.getMetricValue('lingyao_heartbeat_total') || 0,\n missed: this.metrics.getMetricValue('lingyao_heartbeat_missed_total') || 0,\n },\n };\n }\n}\n","/**\n * 错误处理模块\n */\n\nimport type { LingyaoRuntime } from './types.js';\n\n/**\n * 错误严重级别\n */\nexport enum ErrorSeverity {\n LOW = 'low',\n MEDIUM = 'medium',\n HIGH = 'high',\n CRITICAL = 'critical',\n}\n\n/**\n * Lingyao 错误基类\n */\nexport class LingyaoError extends Error {\n public readonly code: string;\n public readonly severity: ErrorSeverity;\n public readonly timestamp: number;\n public readonly context?: Record<string, unknown>;\n public readonly cause?: Error;\n\n constructor(\n message: string,\n code: string,\n severity: ErrorSeverity = ErrorSeverity.MEDIUM,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.severity = severity;\n this.timestamp = Date.now();\n this.context = context;\n this.cause = cause;\n\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * 转换为 JSON 可序列化格式\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n severity: this.severity,\n timestamp: this.timestamp,\n context: this.context,\n cause: this.cause?.message,\n stack: this.stack,\n };\n }\n}\n\n/**\n * 连接错误\n */\nexport class ConnectionError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'CONNECTION_ERROR', ErrorSeverity.HIGH, context, cause);\n }\n}\n\n/**\n * 认证错误\n */\nexport class AuthenticationError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'AUTHENTICATION_ERROR', ErrorSeverity.HIGH, context, cause);\n }\n}\n\n/**\n * 消息错误\n */\nexport class MessageError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'MESSAGE_ERROR', ErrorSeverity.MEDIUM, context, cause);\n }\n}\n\n/**\n * 验证错误\n */\nexport class ValidationError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'VALIDATION_ERROR', ErrorSeverity.LOW, context, cause);\n }\n}\n\n/**\n * 配置错误\n */\nexport class ConfigurationError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'CONFIGURATION_ERROR', ErrorSeverity.HIGH, context, cause);\n }\n}\n\n/**\n * 网络错误\n */\nexport class NetworkError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'NETWORK_ERROR', ErrorSeverity.MEDIUM, context, cause);\n }\n}\n\n/**\n * 超时错误\n */\nexport class TimeoutError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'TIMEOUT_ERROR', ErrorSeverity.MEDIUM, context, cause);\n }\n}\n\n/**\n * 设备离线错误\n */\nexport class DeviceOfflineError extends LingyaoError {\n public readonly deviceId: string;\n\n constructor(\n deviceId: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(\n `Device offline: ${deviceId}`,\n 'DEVICE_OFFLINE_ERROR',\n ErrorSeverity.MEDIUM,\n context,\n cause\n );\n this.deviceId = deviceId;\n }\n}\n\n/**\n * 重试错误\n */\nexport class RetryableError extends LingyaoError {\n public readonly retryable: boolean;\n public readonly retryAfter?: number;\n public readonly maxRetries?: number;\n\n constructor(\n message: string,\n context?: Record<string, unknown> & {\n retryAfter?: number;\n maxRetries?: number;\n },\n cause?: Error\n ) {\n super(message, 'RETRYABLE_ERROR', ErrorSeverity.LOW, context, cause);\n this.retryable = true;\n this.retryAfter = context?.retryAfter;\n this.maxRetries = context?.maxRetries;\n }\n}\n\n/**\n * 错误处理器\n */\nexport class ErrorHandler {\n private runtime: LingyaoRuntime;\n private errorCounts: Map<string, number> = new Map();\n private lastErrors: Map<string, { error: LingyaoError; timestamp: number }> = new Map();\n private errorThresholds: Map<string, { count: number; window: number }> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n\n // 设置默认错误阈值\n this.setErrorThreshold('CONNECTION_ERROR', { count: 5, window: 60000 });\n this.setErrorThreshold('AUTHENTICATION_ERROR', { count: 3, window: 60000 });\n this.setErrorThreshold('NETWORK_ERROR', { count: 10, window: 60000 });\n }\n\n /**\n * 处理错误\n */\n handleError(error: Error | LingyaoError): void {\n const lingyaoError = error instanceof LingyaoError\n ? error\n : new LingyaoError(error.message, 'UNKNOWN_ERROR', ErrorSeverity.MEDIUM, {}, error);\n\n // 记录错误\n this.recordError(lingyaoError);\n\n // 根据严重级别决定日志级别\n switch (lingyaoError.severity) {\n case ErrorSeverity.LOW:\n this.runtime.logger.debug(lingyaoError.message, lingyaoError.toJSON());\n break;\n case ErrorSeverity.MEDIUM:\n this.runtime.logger.warn(lingyaoError.message, lingyaoError.toJSON());\n break;\n case ErrorSeverity.HIGH:\n case ErrorSeverity.CRITICAL:\n this.runtime.logger.error(lingyaoError.message, lingyaoError.toJSON());\n break;\n }\n\n // 检查是否超过阈值\n this.checkThresholds(lingyaoError);\n }\n\n /**\n * 记录错误\n */\n private recordError(error: LingyaoError): void {\n const key = error.code;\n const count = (this.errorCounts.get(key) || 0) + 1;\n this.errorCounts.set(key, count);\n\n this.lastErrors.set(key, {\n error,\n timestamp: Date.now(),\n });\n\n // 清理旧的错误记录(1小时后)\n setTimeout(() => {\n const lastError = this.lastErrors.get(key);\n if (lastError && lastError.timestamp === error.timestamp) {\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) - 1);\n }\n }, 3600000);\n }\n\n /**\n * 检查错误阈值\n */\n private checkThresholds(error: LingyaoError): void {\n const threshold = this.errorThresholds.get(error.code);\n if (!threshold) {\n return;\n }\n\n const count = this.errorCounts.get(error.code) || 0;\n if (count >= threshold.count) {\n this.runtime.logger.error(\n `Error threshold exceeded for ${error.code}`,\n {\n code: error.code,\n count,\n threshold: threshold.count,\n window: threshold.window,\n }\n );\n\n // 触发警报\n this.triggerAlert(error, count);\n }\n }\n\n /**\n * 触发警报\n */\n private triggerAlert(error: LingyaoError, count: number): void {\n // 这里可以集成告警系统\n this.runtime.logger.error('ALERT', {\n type: 'error_threshold_exceeded',\n error: error.toJSON(),\n count,\n });\n }\n\n /**\n * 设置错误阈值\n */\n setErrorThreshold(code: string, threshold: { count: number; window: number }): void {\n this.errorThresholds.set(code, threshold);\n }\n\n /**\n * 获取错误统计\n */\n getErrorStats(): {\n byCode: Record<string, number>;\n total: number;\n recent: Array<{ code: string; error: LingyaoError; timestamp: number }>;\n } {\n const byCode: Record<string, number> = {};\n let total = 0;\n\n for (const [code, count] of this.errorCounts) {\n byCode[code] = count;\n total += count;\n }\n\n const recent = Array.from(this.lastErrors.entries())\n .map(([code, { error, timestamp }]) => ({ code, error, timestamp }))\n .sort((a, b) => b.timestamp - a.timestamp)\n .slice(0, 10);\n\n return { byCode, total, recent };\n }\n\n /**\n * 重置错误计数\n */\n resetErrorCounts(code?: string): void {\n if (code) {\n this.errorCounts.delete(code);\n this.lastErrors.delete(code);\n } else {\n this.errorCounts.clear();\n this.lastErrors.clear();\n }\n }\n\n /**\n * 包装异步函数以自动处理错误\n */\n async wrapAsync<T>(\n fn: () => Promise<T>,\n context?: {\n operation?: string;\n fallback?: T;\n retryable?: boolean;\n }\n ): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n const operation = context?.operation || 'unknown';\n\n if (error instanceof LingyaoError) {\n this.handleError(error);\n } else if (context?.retryable) {\n const retryableError = new RetryableError(\n `Operation \"${operation}\" failed`,\n { operation },\n error as Error\n );\n this.handleError(retryableError);\n } else {\n this.handleError(new LingyaoError(\n `Operation \"${operation}\" failed: ${(error as Error).message}`,\n 'OPERATION_FAILED',\n ErrorSeverity.MEDIUM,\n { operation },\n error as Error\n ));\n }\n\n if (context?.fallback !== undefined) {\n return context.fallback;\n }\n\n throw error;\n }\n }\n\n /**\n * 创建带有错误处理的重试逻辑\n */\n async retry<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n retryDelay?: number;\n backoff?: boolean;\n onRetry?: (error: Error, attempt: number) => void;\n } = {}\n ): Promise<T> {\n const {\n maxRetries = 3,\n retryDelay = 1000,\n backoff = true,\n onRetry,\n } = options;\n\n let lastError: Error | null = null;\n let delay = retryDelay;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt === maxRetries) {\n break;\n }\n\n if (onRetry) {\n onRetry(lastError, attempt + 1);\n }\n\n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, delay));\n\n if (backoff) {\n delay *= 2;\n }\n }\n }\n\n throw new RetryableError(\n `Operation failed after ${maxRetries + 1} attempts`,\n { maxRetries },\n lastError ?? new Error(\"Unknown retry failure\")\n );\n }\n\n /**\n * 判断错误是否可重试\n */\n isRetryable(error: Error): boolean {\n if (error instanceof RetryableError) {\n return error.retryable;\n }\n\n if (error instanceof LingyaoError) {\n switch (error.code) {\n case 'NETWORK_ERROR':\n case 'TIMEOUT_ERROR':\n case 'CONNECTION_ERROR':\n return true;\n default:\n return false;\n }\n }\n\n return false;\n }\n\n /**\n * 判断错误是否需要降级处理\n */\n shouldDegrade(error: Error): boolean {\n if (error instanceof LingyaoError) {\n return error.severity === ErrorSeverity.HIGH ||\n error.severity === ErrorSeverity.CRITICAL;\n }\n\n return false;\n }\n\n /**\n * 创建降级响应\n */\n createDegradedResponse<T>(fallback: T, error?: Error): {\n success: false;\n degraded: true;\n fallback: T;\n error?: Error;\n } {\n return {\n success: false,\n degraded: true,\n fallback,\n error,\n };\n }\n}\n\n/**\n * 错误恢复策略\n */\nexport enum RecoveryStrategy {\n RETRY = 'retry',\n FALLBACK = 'fallback',\n IGNORE = 'ignore',\n ESCALATE = 'escalate',\n}\n\n/**\n * 错误恢复配置\n */\nexport interface ErrorRecoveryConfig {\n strategy: RecoveryStrategy;\n maxRetries?: number;\n fallbackValue?: any;\n ignoreThreshold?: number;\n}\n\n/**\n * 错误恢复管理器\n */\nexport class ErrorRecoveryManager {\n private recoveryConfigs: Map<string, ErrorRecoveryConfig> = new Map();\n\n /**\n * 设置恢复配置\n */\n setRecoveryConfig(errorCode: string, config: ErrorRecoveryConfig): void {\n this.recoveryConfigs.set(errorCode, config);\n }\n\n /**\n * 获取恢复策略\n */\n getRecoveryStrategy(error: Error): ErrorRecoveryConfig | null {\n if (error instanceof LingyaoError) {\n return this.recoveryConfigs.get(error.code) || null;\n }\n\n return null;\n }\n\n /**\n * 应用恢复策略\n */\n async applyRecovery(\n error: Error,\n originalFn: () => Promise<any>\n ): Promise<any> {\n const config = this.getRecoveryStrategy(error);\n\n if (!config) {\n throw error;\n }\n\n switch (config.strategy) {\n case RecoveryStrategy.RETRY:\n const errorHandler = new ErrorHandler({} as any);\n return await errorHandler.retry(originalFn, {\n maxRetries: config.maxRetries || 3,\n });\n\n case RecoveryStrategy.FALLBACK:\n if (config.fallbackValue !== undefined) {\n return config.fallbackValue;\n }\n throw error;\n\n case RecoveryStrategy.IGNORE:\n return null;\n\n case RecoveryStrategy.ESCALATE:\n throw new LingyaoError(\n `Error escalation: ${error.message}`,\n 'ESCALATED_ERROR',\n ErrorSeverity.CRITICAL,\n { originalError: error }\n );\n\n default:\n throw error;\n }\n }\n}\n","/**\n * 灵爻频道插件 - 服务器中转模式\n *\n * 架构:\n * 1. OpenClaw 作为 WebSocket 客户端,主动连接到 lingyao.live 服务器\n * 2. 鸿蒙 App 也作为 WebSocket 客户端,主动连接到 lingyao.live 服务器\n * 3. lingyao.live 服务器作为消息中转站\n * 4. 双方都不需要公网 IP,也不需要开放端口\n */\n\nimport { hostname } from 'node:os';\nimport {\n LINGYAO_SERVER_URL,\n type LingyaoRuntime,\n LingyaoConfig,\n HealthStatus,\n NotifyPayload,\n} from \"./types.js\";\nimport { AccountManager } from \"./accounts.js\";\nimport { TokenManager } from \"./token.js\";\nimport { MessageProcessor, AgentMessage } from \"./bot.js\";\nimport { Probe } from \"./probe.js\";\nimport { setRuntime } from \"./runtime.js\";\nimport { ServerHttpClient } from \"./server-client.js\";\nimport { LingyaoWSClient } from \"./websocket-client.js\";\nimport { Monitor, MonitoringEvent } from \"./metrics.js\";\nimport { ErrorHandler, ConnectionError } from \"./errors.js\";\n\n/**\n * 灵爻频道插件 - 服务器中转模式\n */\nexport class LingyaoChannel {\n private runtime: LingyaoRuntime;\n private config: LingyaoConfig;\n private accountManager: AccountManager;\n private tokenManager: TokenManager;\n private serverClient: ServerHttpClient | null = null;\n private wsClient: LingyaoWSClient | null = null;\n private processor: MessageProcessor | null = null;\n private probe: Probe;\n private monitor: Monitor;\n private errorHandler: ErrorHandler;\n private startTime: number = 0;\n private gatewayId: string;\n private isRunning: boolean = false;\n private messageHandler: ((message: AgentMessage) => void | Promise<void>) | null = null;\n\n constructor(runtime: LingyaoRuntime, config: LingyaoConfig) {\n this.runtime = runtime;\n this.config = config;\n this.startTime = Date.now();\n\n // 生成 Gateway ID\n this.gatewayId = this.generateGatewayId();\n\n // Set global runtime\n setRuntime(runtime);\n\n // Initialize components\n this.accountManager = new AccountManager(runtime);\n this.tokenManager = new TokenManager(runtime);\n this.probe = new Probe(runtime);\n this.monitor = new Monitor(runtime);\n this.errorHandler = new ErrorHandler(runtime);\n\n // Initialize server client\n this.serverClient = new ServerHttpClient(runtime, this.gatewayId, {\n baseURL: LINGYAO_SERVER_URL,\n apiBase: '/v1',\n });\n }\n\n /**\n * 初始化频道\n */\n async initialize(): Promise<void> {\n this.runtime.logger.info(\"Initializing Lingyao Channel (Server Relay Mode)...\");\n\n // Initialize account manager\n await this.accountManager.initialize();\n\n // Initialize message processor\n this.processor = new MessageProcessor(\n this.runtime,\n this.accountManager\n );\n await this.processor.initialize();\n\n if (this.messageHandler) {\n this.processor.setMessageHandler(this.messageHandler);\n }\n\n this.runtime.logger.info(\"Lingyao Channel initialized successfully\");\n }\n\n /**\n * 启动频道\n */\n async start(): Promise<void> {\n if (this.isRunning) {\n this.runtime.logger.warn(\"Lingyao Channel is already running\");\n return;\n }\n\n this.runtime.logger.info(\"Starting Lingyao Channel...\");\n\n try {\n // 1. 向服务器注册\n await this.registerToServer();\n\n // 2. 创建 WebSocket 客户端\n this.wsClient = new LingyaoWSClient(this.runtime, {\n url: `${LINGYAO_SERVER_URL}/v1/gateway/ws`,\n gatewayId: this.gatewayId,\n token: this.serverClient?.getGatewayToken() ?? undefined,\n reconnectInterval: 5000,\n heartbeatInterval: 30000,\n messageHandler: this.handleAppMessage.bind(this),\n eventHandler: this.handleClientEvent.bind(this),\n });\n\n // 3. 连接到服务器\n await this.wsClient.connect();\n\n this.isRunning = true;\n this.runtime.logger.info(\"Lingyao Channel started successfully\");\n } catch (error) {\n this.runtime.logger.error(\"Failed to start Lingyao Channel\", error);\n throw error;\n }\n }\n\n /**\n * 向 lingyao 服务器注册 Gateway\n */\n private async registerToServer(): Promise<void> {\n if (!this.serverClient) {\n throw new Error('Server client not available');\n }\n\n try {\n // 尝试从存储恢复会话\n const restored = await this.serverClient.restoreFromStorage();\n\n if (restored) {\n this.runtime.logger.info('Previous server registration restored');\n return;\n }\n\n this.runtime.logger.info('Registering to lingyao server...', {\n gatewayId: this.gatewayId,\n });\n\n // 向服务器注册\n const registerResponse = await this.serverClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n\n this.runtime.logger.info('Registered to lingyao server successfully', {\n expiresAt: new Date(registerResponse.expiresAt).toISOString(),\n heartbeatInterval: registerResponse.serverConfig.heartbeatInterval,\n });\n } catch (error) {\n const err = error as Error;\n this.runtime.logger.error('Failed to register to server', err);\n\n // 注册失败不影响启动,WebSocket 客户端会自动重连\n this.runtime.logger.info('Will attempt WebSocket connection anyway');\n }\n }\n\n /**\n * 处理来自鸿蒙 App 的消息\n */\n private async handleAppMessage(message: any): Promise<void> {\n try {\n const appMessage = message.payload;\n const deviceId = appMessage.deviceId;\n const msg = appMessage.message;\n\n this.runtime.logger.info('Received message from App', {\n deviceId,\n messageType: msg.type,\n messageId: msg.id,\n });\n\n // 记录接收消息事件\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_RECEIVED, {\n deviceId,\n messageType: msg.type,\n messageId: msg.id,\n });\n\n // 处理不同类型的消息\n switch (msg.type) {\n case 'sync_diary':\n case 'sync_memory':\n await this.handleSyncMessage(deviceId, msg);\n break;\n case 'heartbeat':\n // 心跳消息,不需要特殊处理\n this.monitor.recordEvent(MonitoringEvent.HEARTBEAT_RECEIVED, {\n deviceId,\n });\n break;\n default:\n this.runtime.logger.warn('Unknown message type', { type: msg.type });\n }\n } catch (error) {\n this.runtime.logger.error('Error handling App message', error);\n this.monitor.recordEvent(MonitoringEvent.ERROR_OCCURRED, {\n errorType: 'message_handling',\n severity: 'medium',\n });\n }\n }\n\n /**\n * 处理同步消息(日记、记忆等)\n */\n private async handleSyncMessage(\n deviceId: string,\n message: {\n id: string;\n type: \"sync_diary\" | \"sync_memory\";\n timestamp: number;\n content: string;\n metadata?: Record<string, unknown>;\n }\n ): Promise<void> {\n if (!this.processor) {\n this.runtime.logger.warn('Message processor not initialized');\n return;\n }\n\n // 转换为 Agent 消息格式\n const agentMessage: AgentMessage = {\n id: message.id,\n type: this.mapMessageType(message.type),\n from: deviceId,\n deviceId,\n content: message.content,\n metadata: message.metadata || {},\n timestamp: message.timestamp,\n };\n\n await this.processor.deliverToAgent(agentMessage);\n }\n\n /**\n * 映射消息类型\n */\n private mapMessageType(appType: \"sync_diary\" | \"sync_memory\"): AgentMessage[\"type\"] {\n return appType === \"sync_diary\" ? \"diary\" : \"memory\";\n }\n\n /**\n * 处理 WebSocket 客户端事件\n */\n private handleClientEvent(event: any): void {\n this.runtime.logger.debug('WebSocket client event', { type: event.type });\n\n switch (event.type) {\n case 'connected':\n this.runtime.logger.info('Connected to Lingyao server', {\n connectionId: event.connectionId,\n });\n this.monitor.recordEvent(MonitoringEvent.CONNECTION_OPEN, {\n connectionId: event.connectionId,\n });\n break;\n case 'disconnected':\n this.runtime.logger.warn('Disconnected from Lingyao server', {\n code: event.code,\n reason: event.reason,\n });\n this.monitor.recordEvent(MonitoringEvent.CONNECTION_CLOSE, {\n code: event.code,\n reason: event.reason,\n });\n break;\n case 'error':\n this.runtime.logger.error('WebSocket client error', event.error);\n this.probe.recordError(event.error.message, \"websocket\");\n this.monitor.recordEvent(MonitoringEvent.CONNECTION_ERROR, {\n error: event.error,\n });\n this.errorHandler.handleError(\n new ConnectionError(\n `WebSocket error: ${event.error.message}`,\n { event: event.type },\n event.error\n )\n );\n break;\n }\n }\n\n /**\n * 停止频道\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n this.runtime.logger.info(\"Stopping Lingyao Channel...\");\n\n this.isRunning = false;\n\n // 断开 WebSocket 连接\n if (this.wsClient) {\n this.wsClient.disconnect();\n this.wsClient = null;\n }\n\n // 停止服务器心跳\n if (this.serverClient) {\n this.serverClient.stopHeartbeat();\n }\n\n this.runtime.logger.info(\"Lingyao Channel stopped\");\n }\n\n /**\n * 发送通知到设备\n */\n async sendNotification(\n deviceId: string,\n notification: NotifyPayload\n ): Promise<{ success: boolean; error?: string; queued?: boolean }> {\n if (!this.wsClient || !this.wsClient.isConnected()) {\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_FAILED, {\n deviceId,\n reason: 'not_connected',\n direction: 'out',\n });\n return {\n success: false,\n error: \"Not connected to Lingyao server\",\n };\n }\n\n try {\n this.wsClient.sendNotification(deviceId, notification);\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_SENT, {\n deviceId,\n messageType: 'notification',\n });\n return { success: true };\n } catch (error) {\n const err = error as Error;\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_FAILED, {\n deviceId,\n reason: err.message,\n direction: 'out',\n });\n return {\n success: false,\n error: err.message,\n };\n }\n }\n\n /**\n * 发送文本到设备\n */\n async sendText(\n deviceId: string,\n text: string\n ): Promise<{ success: boolean; error?: string; queued?: boolean }> {\n return await this.sendNotification(deviceId, {\n title: 'OpenClaw',\n body: text,\n });\n }\n\n /**\n * 获取健康状态\n */\n async getHealthStatus(): Promise<HealthStatus> {\n const activeConnections = this.wsClient?.isConnected() ? 1 : 0;\n const queuedMessages = this.processor?.getTotalQueueSize() ?? 0;\n const lastError = this.probe.getLastError() ?? undefined;\n\n let status: \"healthy\" | \"degraded\" | \"unhealthy\" = \"healthy\";\n\n if (lastError) {\n status = \"degraded\";\n }\n\n if (!this.config.enabled) {\n status = \"unhealthy\";\n }\n\n if (!this.wsClient?.isConnected()) {\n status = \"degraded\";\n }\n\n const uptime = Date.now() - this.startTime;\n\n return {\n status,\n uptime,\n activeConnections,\n queuedMessages,\n lastError,\n };\n }\n\n /**\n * 获取配置\n */\n getConfig(): LingyaoConfig {\n return { ...this.config };\n }\n\n /**\n * 更新配置\n */\n async updateConfig(updates: Partial<LingyaoConfig>): Promise<void> {\n this.config = { ...this.config, ...updates };\n this.runtime.logger.info(\"Configuration updated\", updates);\n }\n\n /**\n * 获取账号管理器\n */\n getAccountManager(): AccountManager {\n return this.accountManager;\n }\n\n /**\n * 获取 Token 管理器\n */\n getTokenManager(): TokenManager {\n return this.tokenManager;\n }\n\n /**\n * 获取服务器客户端\n */\n getServerClient(): ServerHttpClient | null {\n return this.serverClient;\n }\n\n /**\n /**\n * 获取 WebSocket 客户端\n */\n getWSClient(): LingyaoWSClient | null {\n return this.wsClient;\n }\n\n /**\n * 获取消息处理器\n */\n getMessageProcessor(): MessageProcessor | null {\n return this.processor;\n }\n\n /**\n * 设置消息处理器\n */\n setMessageHandler(handler: (message: AgentMessage) => void | Promise<void>): void {\n this.messageHandler = handler;\n if (this.processor) {\n this.processor.setMessageHandler(handler);\n }\n this.runtime.logger.info(\"Message handler registered for Agent integration\");\n }\n\n /**\n * 获取监控器\n */\n getMonitor(): Monitor {\n return this.monitor;\n }\n\n /**\n * 获取错误处理器\n */\n getErrorHandler(): ErrorHandler {\n return this.errorHandler;\n }\n\n /**\n * 获取监控摘要\n */\n getMonitoringSummary() {\n return this.monitor.getSummary();\n }\n\n /**\n * 获取错误统计\n */\n getErrorStats() {\n return this.errorHandler.getErrorStats();\n }\n\n /**\n * 生成 Gateway ID\n */\n private generateGatewayId(): string {\n const hostname = this.getRuntimeHostname();\n const randomSuffix = Math.random().toString(36).substring(2, 8);\n return `gw_openclaw_${hostname}_${randomSuffix}`;\n }\n\n /**\n * 获取运行时主机名\n */\n private getRuntimeHostname(): string {\n try {\n return hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();\n } catch {\n return 'unknown';\n }\n }\n}\n","import { randomBytes, createHash, timingSafeEqual } from \"crypto\";\nimport type { DeviceToken, DeviceInfo, LingyaoRuntime } from \"./types.js\";\n\n/**\n * Token management utilities\n */\nexport class TokenManager {\n constructor(_runtime: LingyaoRuntime) {\n void _runtime;\n }\n\n /**\n * Generate a new device token\n */\n generateDeviceToken(\n pairingId: string,\n deviceInfo: DeviceInfo,\n expiryDays: number = 30\n ): DeviceToken {\n const deviceId = this.generateDeviceId();\n const secret = this.generateSecret();\n const token = this.generateTokenString(deviceId, secret);\n\n const expiresAt = Date.now() + expiryDays * 24 * 60 * 60 * 1000;\n\n return {\n deviceId,\n pairingId,\n token,\n secret,\n expiresAt,\n deviceInfo,\n };\n }\n\n /**\n * Validate a device token\n */\n validateToken(token: string, storedSecret: string): boolean {\n try {\n // In production, use proper JWT validation\n // For now, simple token validation\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return false;\n }\n\n const [headerB64, payloadB64, signatureB64] = parts;\n\n // Verify signature\n const expectedSignature = this.sign(`${headerB64}.${payloadB64}`, storedSecret);\n const providedSignature = Buffer.from(signatureB64, \"base64url\").toString(\"utf-8\");\n\n // Use timing-safe comparison (signature segments are UTF-8 of base64 digest)\n return timingSafeEqual(\n Buffer.from(expectedSignature, \"utf-8\"),\n Buffer.from(providedSignature, \"utf-8\")\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Check if token is expired\n */\n isTokenExpired(token: DeviceToken): boolean {\n return token.expiresAt < Date.now();\n }\n\n /**\n * Refresh an existing token\n */\n refreshToken(\n oldToken: DeviceToken,\n expiryDays: number = 30\n ): DeviceToken {\n const newSecret = this.generateSecret();\n const newTokenString = this.generateTokenString(\n oldToken.deviceId,\n newSecret\n );\n\n const expiresAt = Date.now() + expiryDays * 24 * 60 * 60 * 1000;\n\n return {\n ...oldToken,\n token: newTokenString,\n secret: newSecret,\n expiresAt,\n };\n }\n\n /**\n * Extract device ID from token string\n */\n extractDeviceId(token: string): string | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n\n return payload.did || null;\n } catch {\n return null;\n }\n }\n\n /**\n * Generate a unique device ID\n */\n private generateDeviceId(): string {\n return `lingyao_${randomBytes(16).toString(\"hex\")}`;\n }\n\n /**\n * Generate a random secret key\n */\n private generateSecret(): string {\n return randomBytes(32).toString(\"hex\");\n }\n\n /**\n * Generate a JWT-like token string\n */\n private generateTokenString(deviceId: string, secret: string): string {\n const header = {\n alg: \"HS256\",\n typ: \"LingyaoToken\",\n };\n\n const payload = {\n did: deviceId,\n iat: Date.now(),\n };\n\n const headerB64 = this.base64UrlEncode(JSON.stringify(header));\n const payloadB64 = this.base64UrlEncode(JSON.stringify(payload));\n const signature = this.sign(`${headerB64}.${payloadB64}`, secret);\n const signatureB64 = this.base64UrlEncode(signature);\n\n return `${headerB64}.${payloadB64}.${signatureB64}`;\n }\n\n /**\n * Sign data with secret\n */\n private sign(data: string, secret: string): string {\n return createHash(\"sha256\")\n .update(data + secret)\n .digest(\"base64\");\n }\n\n /**\n * Base64URL encode without padding\n */\n private base64UrlEncode(data: string): string {\n return Buffer.from(data)\n .toString(\"base64url\")\n .replace(/=/g, \"\");\n }\n}\n\n/**\n * Generate a pairing code (6-digit numeric)\n */\nexport function generatePairingCode(): string {\n // Generate a 6-digit numeric code\n const min = 100000;\n const max = 999999;\n const code = Math.floor(Math.random() * (max - min + 1)) + min;\n return code.toString();\n}\n\n/**\n * Generate a nonce for pairing\n */\nexport function generateNonce(): string {\n return randomBytes(16).toString(\"hex\");\n}\n\n/**\n * Validate pairing code format\n */\nexport function isValidPairingCode(code: string): boolean {\n return /^\\d{6}$/.test(code);\n}\n","import { z } from \"zod\";\nimport type { LingyaoConfig } from \"./types.js\";\n\n/**\n * Zod schema for Lingyao plugin configuration\n */\nexport const lingyaoConfigSchema = z.object({\n enabled: z.boolean().default(true),\n maxOfflineMessages: z.number().int().min(1).max(1000).optional().default(100),\n tokenExpiryDays: z.number().int().min(1).max(365).optional().default(30),\n});\n\nexport type LingyaoConfigSchema = z.infer<typeof lingyaoConfigSchema>;\n\n/**\n * Validate configuration object\n */\nexport function validateConfig(config: unknown): LingyaoConfig {\n return lingyaoConfigSchema.parse(config);\n}\n\n/**\n * Safely parse configuration, returning null if invalid\n */\nexport function safeParseConfig(config: unknown): LingyaoConfig | null {\n const result = lingyaoConfigSchema.safeParse(config);\n return result.success ? result.data : null;\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): LingyaoConfig {\n return {\n enabled: true,\n maxOfflineMessages: 100,\n tokenExpiryDays: 30,\n };\n}\n","/**\n * Lingyao Channel Plugin for OpenClaw\n *\n * Entry point implementing the OpenClaw Channel Plugin SDK interface.\n *\n * Architecture:\n * pluginEntry.setRuntime(runtime) → MultiAccountOrchestrator\n * pluginEntry.plugin → ChannelPlugin object with all adapters\n * Adapters delegate to Orchestrator for per-account WS/HTTP management.\n *\n * When the OpenClaw SDK is available as a peer dependency, this module\n * exports via pluginEntry. Otherwise, it exports the raw plugin object\n * for development/testing via createPlugin().\n */\n\nimport type { LingyaoRuntime, LingyaoConfig } from './types.js';\nimport { setRuntime } from './runtime.js';\nimport { createConfigAdapter, type ResolvedAccount } from './adapters/config.js';\nimport { createGatewayAdapter } from './adapters/gateway.js';\nimport { createStatusAdapter } from './adapters/status.js';\nimport { createDirectoryAdapter } from './adapters/directory.js';\nimport { createMessagingAdapter } from './adapters/messaging.js';\nimport { createOutboundAdapter } from './adapters/outbound.js';\nimport { MultiAccountOrchestrator } from './orchestrator.js';\nimport { LingyaoChannel } from './channel.js';\nimport { validateConfig, getDefaultConfig } from './config-schema.js';\n\n// Re-export types for external consumers\nexport * from './types.js';\nexport type { AgentMessage } from './bot.js';\nexport { LingyaoChannel } from './channel.js';\nexport { validateConfig, getDefaultConfig } from './config-schema.js';\n\n/**\n * Orchestrator instance, created when setRuntime is called.\n */\nlet orchestrator: MultiAccountOrchestrator | null = null;\n\n/**\n * Lazy accessor for the orchestrator.\n */\nfunction getOrchestrator(): MultiAccountOrchestrator | null {\n return orchestrator;\n}\n\n// ---------------------------------------------------------------------------\n// Adapter instances (created lazily or at module load time)\n// ---------------------------------------------------------------------------\n\nconst configAdapter = createConfigAdapter();\nconst messagingAdapter = createMessagingAdapter();\n\n// These adapters need the orchestrator getter, created at module load time\nconst gatewayAdapter = createGatewayAdapter(getOrchestrator);\nconst directoryAdapter = createDirectoryAdapter(getOrchestrator);\nconst outboundAdapter = createOutboundAdapter(getOrchestrator);\n\n// statusAdapter needs runtime reference, set lazily\nlet statusAdapter: ReturnType<typeof createStatusAdapter> | null = null;\n\nfunction getStatusAdapter(runtime: LingyaoRuntime) {\n if (!statusAdapter) {\n statusAdapter = createStatusAdapter(getOrchestrator, runtime);\n }\n return statusAdapter;\n}\n\n// ---------------------------------------------------------------------------\n// Security options (declarative DM policy)\n// ---------------------------------------------------------------------------\n\nconst securityOptions = {\n dm: {\n channelKey: 'lingyao',\n resolvePolicy: (account: ResolvedAccount) => account.dmPolicy,\n resolveAllowFrom: (account: ResolvedAccount) => account.allowFrom,\n defaultPolicy: 'paired' as const,\n },\n};\n\n// ---------------------------------------------------------------------------\n// Pairing options\n// ---------------------------------------------------------------------------\n\nconst pairingOptions = {\n text: {\n idLabel: '设备 ID',\n message: '设备已批准配对',\n notify: async (params: { cfg: unknown; id: string }): Promise<void> => {\n const orc = getOrchestrator();\n if (!orc) return;\n\n const config = params.cfg as Record<string, unknown>;\n const channels = config.channels as Record<string, unknown> | undefined;\n const lingyao = channels?.lingyao as { accounts?: Record<string, unknown> } | undefined;\n const accountIds = lingyao?.accounts ? Object.keys(lingyao.accounts) : ['default'];\n\n for (const accountId of accountIds) {\n const sent = orc.sendNotification(accountId, params.id, {\n type: 'pairing_confirmed',\n message: pairingOptions.text.message,\n });\n if (sent) break;\n }\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Plugin base object (implements ChannelPlugin)\n// ---------------------------------------------------------------------------\n\nfunction buildPluginBase(runtime: LingyaoRuntime) {\n return {\n id: 'lingyao' as const,\n\n meta: {\n id: 'lingyao',\n label: '灵爻',\n selectionLabel: '灵爻 (HarmonyOS)',\n docsPath: '/channels/lingyao',\n docsLabel: '灵爻文档',\n blurb: '通过 lingyao.live 服务器中转与鸿蒙灵爻 App 双向同步日记和记忆',\n order: 50,\n aliases: ['lingyao', '灵爻'],\n },\n\n capabilities: {\n chatTypes: ['direct'] as const,\n media: false,\n reactions: false,\n threads: false,\n polls: false,\n edit: false,\n unsend: false,\n reply: false,\n effects: false,\n groupManagement: false,\n nativeCommands: false,\n blockStreaming: true,\n },\n\n config: configAdapter,\n gateway: gatewayAdapter,\n outbound: outboundAdapter,\n status: getStatusAdapter(runtime),\n directory: directoryAdapter,\n messaging: messagingAdapter,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legacy API (backward compatibility for non-SDK consumers)\n// ---------------------------------------------------------------------------\n\n/**\n * Create a LingyaoChannel instance (legacy API).\n * Use this for standalone usage without the OpenClaw SDK.\n */\nexport async function createPlugin(\n runtime: LingyaoRuntime,\n config: Partial<LingyaoConfig> = {}\n): Promise<LingyaoChannel> {\n const fullConfig = { ...getDefaultConfig(), ...config };\n const validatedConfig = validateConfig(fullConfig);\n const channel = new LingyaoChannel(runtime, validatedConfig);\n await channel.initialize();\n return channel;\n}\n\n/**\n * Plugin metadata (legacy API).\n */\nexport const pluginMetadata = {\n name: 'lingyao',\n version: '0.3.0',\n description: 'Lingyao Channel Plugin - bidirectional sync via lingyao.live server relay',\n type: 'channel',\n capabilities: {\n chatTypes: ['direct'],\n media: false,\n reactions: false,\n threads: false,\n },\n defaultConfig: getDefaultConfig(),\n};\n\n// ---------------------------------------------------------------------------\n// Default export - OpenClaw SDK entry point\n// ---------------------------------------------------------------------------\n\nconst pluginEntry = {\n id: 'lingyao',\n name: 'Lingyao',\n description: 'Lingyao Channel Plugin - bidirectional sync via lingyao.live',\n\n setRuntime(runtime: unknown): void {\n const rt = runtime as LingyaoRuntime;\n setRuntime(rt);\n orchestrator = new MultiAccountOrchestrator(rt);\n },\n\n get plugin() {\n const rt = (orchestrator as any)?.runtime;\n if (!rt) {\n throw new Error('Runtime not set. Call setRuntime() before accessing plugin.');\n }\n return buildPluginBase(rt);\n },\n\n // Security and pairing options for createChatChannelPlugin composition\n security: securityOptions,\n pairing: pairingOptions,\n};\n\nexport default pluginEntry;\n"],"mappings":"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","names":["getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","MessageType","hostname","randomBytes","createHash","timingSafeEqual","hostname"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/runtime.ts","../src/adapters/config.ts","../src/adapters/gateway.ts","../src/adapters/status.ts","../src/adapters/directory.ts","../src/adapters/messaging.ts","../src/adapters/outbound.ts","../src/adapters/setup.ts","../src/orchestrator.ts","../src/types.ts","../src/server-client.ts","../src/websocket-client.ts","../src/accounts.ts","../src/crypto.ts","../src/bot.ts","../src/probe.ts","../src/metrics.ts","../src/errors.ts","../src/channel.ts","../src/token.ts","../src/config-schema.ts"],"sourcesContent":["/**\n * Lingyao Channel Plugin for OpenClaw\n *\n * Entry point implementing the OpenClaw Channel Plugin SDK interface.\n *\n * Uses SDK composition helpers:\n * - defineChannelPluginEntry → auto-generates `register` export\n * - createChannelPluginBase → builds base with required `setup`\n * - createChatChannelPlugin → composes security/pairing/outbound\n */\n\nimport type { PluginRuntime, ChannelPlugin } from 'openclaw/plugin-sdk';\nimport {\n defineChannelPluginEntry,\n createChatChannelPlugin,\n} from 'openclaw/plugin-sdk/core';\n\nimport type { LingyaoRuntime, LingyaoConfig } from './types.js';\nimport { setRuntime } from './runtime.js';\nimport { adaptPluginRuntime } from './runtime.js';\nimport { createConfigAdapter, type ResolvedAccount } from './adapters/config.js';\nimport { createGatewayAdapter } from './adapters/gateway.js';\nimport { createStatusAdapter } from './adapters/status.js';\nimport { createDirectoryAdapter } from './adapters/directory.js';\nimport { createMessagingAdapter } from './adapters/messaging.js';\nimport { createOutboundAdapter } from './adapters/outbound.js';\nimport { createSetupAdapter } from './adapters/setup.js';\nimport { MultiAccountOrchestrator } from './orchestrator.js';\nimport { LingyaoChannel } from './channel.js';\nimport { validateConfig, getDefaultConfig } from './config-schema.js';\n\n// Re-export types for external consumers\nexport * from './types.js';\nexport type { AgentMessage } from './bot.js';\nexport { LingyaoChannel } from './channel.js';\nexport { validateConfig, getDefaultConfig } from './config-schema.js';\n\n// ---------------------------------------------------------------------------\n// Orchestrator instance, created when setRuntime is called.\n// ---------------------------------------------------------------------------\n\nlet orchestrator: MultiAccountOrchestrator | null = null;\n\nfunction getOrchestrator(): MultiAccountOrchestrator | null {\n return orchestrator;\n}\n\n// ---------------------------------------------------------------------------\n// Adapter instances\n// ---------------------------------------------------------------------------\n\nconst configAdapter = createConfigAdapter();\nconst setupAdapter = createSetupAdapter();\nconst messagingAdapter = createMessagingAdapter();\nconst gatewayAdapter = createGatewayAdapter(getOrchestrator);\nconst directoryAdapter = createDirectoryAdapter(getOrchestrator);\nconst outboundAdapter = createOutboundAdapter(getOrchestrator);\nlet statusAdapter: ReturnType<typeof createStatusAdapter> | null = null;\n\n// ---------------------------------------------------------------------------\n// Security & Pairing options\n// ---------------------------------------------------------------------------\n\nconst securityOptions = {\n dm: {\n channelKey: 'lingyao',\n resolvePolicy: (account: ResolvedAccount) => account.dmPolicy,\n resolveAllowFrom: (account: ResolvedAccount) => account.allowFrom,\n defaultPolicy: 'paired' as const,\n },\n};\n\nconst pairingOptions = {\n text: {\n idLabel: '设备 ID',\n message: '设备已批准配对',\n notify: async (params: { cfg: unknown; id: string }): Promise<void> => {\n const orc = getOrchestrator();\n if (!orc) return;\n\n const config = params.cfg as Record<string, unknown>;\n const channels = config.channels as Record<string, unknown> | undefined;\n const lingyao = channels?.lingyao as { accounts?: Record<string, unknown> } | undefined;\n const accountIds = lingyao?.accounts ? Object.keys(lingyao.accounts) : ['default'];\n\n for (const accountId of accountIds) {\n const sent = orc.sendNotification(accountId, params.id, {\n type: 'pairing_confirmed',\n message: pairingOptions.text.message,\n });\n if (sent) break;\n }\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Build the ChannelPlugin using SDK composition\n// ---------------------------------------------------------------------------\n\nconst capabilities = {\n chatTypes: ['direct'] as ('direct' | 'group' | 'channel' | 'thread')[],\n media: false,\n reactions: false,\n threads: false,\n polls: false,\n edit: false,\n unsend: false,\n reply: false,\n effects: false,\n groupManagement: false,\n nativeCommands: false,\n blockStreaming: true,\n};\n\nconst meta = {\n id: 'lingyao',\n label: '灵爻',\n selectionLabel: '灵爻 (HarmonyOS)',\n docsPath: '/channels/lingyao',\n docsLabel: '灵爻文档',\n blurb: '通过 lingyao.live 服务器中转与鸿蒙灵爻 App 双向同步日记和记忆',\n order: 50,\n aliases: ['lingyao', '灵爻'],\n};\n\nfunction buildPlugin(): ChannelPlugin<ResolvedAccount> {\n const composed = createChatChannelPlugin<ResolvedAccount>({\n base: {\n id: 'lingyao',\n meta,\n capabilities,\n config: configAdapter,\n setup: setupAdapter,\n },\n security: securityOptions,\n pairing: pairingOptions,\n outbound: outboundAdapter,\n });\n\n // Spread additional adapters that createChatChannelPlugin doesn't cover\n return {\n ...composed,\n gateway: gatewayAdapter,\n status: statusAdapter ?? undefined,\n directory: directoryAdapter,\n messaging: messagingAdapter,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Default export - OpenClaw SDK entry point\n// ---------------------------------------------------------------------------\n\nexport default defineChannelPluginEntry({\n id: 'lingyao',\n name: 'Lingyao',\n description: 'Lingyao Channel Plugin - bidirectional sync via lingyao.live server relay',\n plugin: {\n get id() { return 'lingyao'; },\n get meta() { return buildPlugin().meta; },\n get capabilities() { return buildPlugin().capabilities; },\n get config() { return buildPlugin().config; },\n get setup() { return buildPlugin().setup; },\n get security() { return buildPlugin().security; },\n get pairing() { return buildPlugin().pairing; },\n get outbound() { return buildPlugin().outbound; },\n get gateway() { return buildPlugin().gateway; },\n get status() {\n if (!statusAdapter) return undefined;\n return statusAdapter;\n },\n get directory() { return buildPlugin().directory; },\n get messaging() { return buildPlugin().messaging; },\n },\n setRuntime(runtime: PluginRuntime): void {\n const adapted = adaptPluginRuntime(runtime as Parameters<typeof adaptPluginRuntime>[0]);\n setRuntime(adapted);\n orchestrator = new MultiAccountOrchestrator(adapted);\n statusAdapter = createStatusAdapter(getOrchestrator, adapted);\n },\n});\n\n// ---------------------------------------------------------------------------\n// Legacy API (backward compatibility for non-SDK consumers)\n// ---------------------------------------------------------------------------\n\n/** @deprecated Use the default export (OpenClaw SDK entry) instead. */\nexport async function createPlugin(\n runtime: LingyaoRuntime,\n config: Partial<LingyaoConfig> = {}\n): Promise<LingyaoChannel> {\n const fullConfig = { ...getDefaultConfig(), ...config };\n const validatedConfig = validateConfig(fullConfig);\n const channel = new LingyaoChannel(runtime, validatedConfig);\n await channel.initialize();\n return channel;\n}\n\n/** @deprecated Use openclaw.plugin.json for plugin metadata. */\nexport const pluginMetadata = {\n name: 'lingyao',\n version: '0.4.0',\n description: 'Lingyao Channel Plugin - bidirectional sync via lingyao.live server relay',\n type: 'channel',\n capabilities: {\n chatTypes: ['direct'],\n media: false,\n reactions: false,\n threads: false,\n },\n defaultConfig: getDefaultConfig(),\n};\n","import type { LingyaoRuntime } from \"./types.js\";\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Global runtime instance storage\n */\nlet globalRuntime: LingyaoRuntime | null = null;\n\n/**\n * Set the global runtime instance\n */\nexport function setRuntime(runtime: LingyaoRuntime): void {\n globalRuntime = runtime;\n}\n\n/**\n * Get the global runtime instance\n */\nexport function getRuntime(): LingyaoRuntime {\n if (!globalRuntime) {\n throw new Error(\"Runtime not initialized. Call setRuntime() first.\");\n }\n return globalRuntime;\n}\n\n/**\n * Check if runtime is initialized\n */\nexport function hasRuntime(): boolean {\n return globalRuntime !== null;\n}\n\n/**\n * Clear the global runtime instance\n */\nexport function clearRuntime(): void {\n globalRuntime = null;\n}\n\n/**\n * Adapt OpenClaw PluginRuntime to LingyaoRuntime.\n *\n * Bridges the SDK's PluginRuntime (logger, state dir) to the\n * internal LingyaoRuntime interface used by orchestrator/bot/ws.\n */\nexport function adaptPluginRuntime(pr: {\n logging?: { getChildLogger?: () => { info: (msg: string, ...args: unknown[]) => void; warn: (msg: string, ...args: unknown[]) => void; error: (msg: string, ...args: unknown[]) => void; debug?: (msg: string, ...args: unknown[]) => void } };\n state?: { resolveStateDir?: () => string };\n}): LingyaoRuntime {\n const noop = (..._args: unknown[]) => {};\n const childLogger = pr.logging?.getChildLogger?.() ?? {\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: noop,\n };\n\n const stateDir = pr.state?.resolveStateDir?.() ?? join(process.cwd(), '.lingyao-data');\n const storeDir = join(stateDir, 'lingyao');\n\n return {\n config: { enabled: true },\n logger: childLogger,\n storage: {\n async get(key: string): Promise<unknown | null> {\n try {\n const filePath = join(storeDir, `${key}.json`);\n if (!existsSync(filePath)) return null;\n const data = readFileSync(filePath, 'utf-8');\n return JSON.parse(data);\n } catch {\n return null;\n }\n },\n async set(key: string, value: unknown): Promise<void> {\n if (!existsSync(storeDir)) {\n mkdirSync(storeDir, { recursive: true });\n }\n const filePath = join(storeDir, `${key}.json`);\n writeFileSync(filePath, JSON.stringify(value, null, 2), 'utf-8');\n },\n async delete(key: string): Promise<void> {\n const filePath = join(storeDir, `${key}.json`);\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n },\n },\n tools: {\n async call(): Promise<unknown> {\n throw new Error('Tool calls not available in SDK mode');\n },\n },\n };\n}\n","/**\n * Config Adapter - Account resolution, config validation\n *\n * serverUrl is NOT exposed to users — hardcoded as LINGYAO_SERVER_URL.\n */\n\nimport type { OpenClawConfig } from 'openclaw/plugin-sdk';\nimport type { LingyaoAccountConfig } from '../types.js';\n\n/**\n * Resolved account after config resolution.\n */\nexport interface ResolvedAccount {\n readonly id: string;\n readonly accountId?: string | null;\n readonly enabled: boolean;\n readonly dmPolicy: 'paired' | 'open' | 'deny';\n readonly allowFrom: string[];\n readonly rawConfig: LingyaoAccountConfig;\n}\n\n/**\n * Extract the lingyao accounts from OpenClaw config.\n */\nfunction extractAccounts(cfg: OpenClawConfig): Record<string, LingyaoAccountConfig> {\n const channels = (cfg as Record<string, unknown>)?.channels as Record<string, unknown> | undefined;\n const lingyao = channels?.lingyao as Record<string, unknown> | undefined;\n const accounts = lingyao?.accounts as Record<string, LingyaoAccountConfig> | undefined;\n\n if (!accounts) return {};\n return accounts;\n}\n\n/**\n * Create the config adapter.\n */\nexport function createConfigAdapter() {\n return {\n listAccountIds(cfg: OpenClawConfig): string[] {\n const accounts = extractAccounts(cfg);\n return Object.keys(accounts);\n },\n\n resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedAccount {\n const accounts = extractAccounts(cfg);\n const ids = Object.keys(accounts);\n\n if (ids.length === 0) {\n // No accounts configured — auto-create a default\n accounts['default'] = {};\n }\n\n const resolvedId = accountId ?? (ids.includes('default') ? 'default' : ids[0]);\n\n if (!resolvedId) {\n throw new Error('No lingyao accounts configured');\n }\n\n const accountConfig = accounts[resolvedId];\n if (!accountConfig) {\n throw new Error(`Account \"${resolvedId}\" not found`);\n }\n\n return {\n id: resolvedId,\n accountId: resolvedId,\n enabled: (accountConfig as Record<string, unknown>)?.enabled !== false,\n dmPolicy: ((accountConfig as Record<string, unknown>)?.dmPolicy as ResolvedAccount['dmPolicy']) ?? 'paired',\n allowFrom: ((accountConfig as Record<string, unknown>)?.allowFrom as string[]) ?? [],\n rawConfig: accountConfig as LingyaoAccountConfig,\n };\n },\n\n isConfigured(_account: ResolvedAccount, _cfg: OpenClawConfig): boolean {\n return true;\n },\n\n isEnabled(account: ResolvedAccount, _cfg: OpenClawConfig): boolean {\n return account.enabled;\n },\n };\n}\n","/**\n * Gateway Adapter - Account lifecycle management\n *\n * Implements ChannelGatewayAdapter:\n * - startAccount: create WS/HTTP connections for an account\n * - stopAccount: tear down connections for an account\n *\n * Delegates to MultiAccountOrchestrator for all operations.\n */\n\nimport type { ChannelGatewayContext } from 'openclaw/plugin-sdk';\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\nimport type { ResolvedAccount } from './config.js';\n\n/**\n * Create the gateway adapter.\n */\nexport function createGatewayAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null\n) {\n return {\n async startAccount(ctx: ChannelGatewayContext<ResolvedAccount>): Promise<void> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized. Ensure setRuntime was called.');\n }\n\n ctx.log?.info(`Starting account \"${ctx.accountId}\"`);\n\n await orchestrator.start(ctx.account);\n\n ctx.log?.info(`Account \"${ctx.accountId}\" started successfully`);\n },\n\n async stopAccount(ctx: ChannelGatewayContext<ResolvedAccount>): Promise<void> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized');\n }\n\n ctx.log?.info(`Stopping account \"${ctx.accountId}\"`);\n\n await orchestrator.stop(ctx.accountId);\n },\n };\n}\n","/**\n * Status Adapter - Health checks and channel summary\n *\n * Implements ChannelStatusAdapter:\n * - probeAccount: run health checks for a specific account\n * - buildChannelSummary: aggregate status for a single account\n */\n\nimport type { ChannelAccountSnapshot } from 'openclaw/plugin-sdk';\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\nimport type { ResolvedAccount } from './config.js';\n\n/**\n * Probe result structure.\n */\nexport interface LingyaoProbeResult {\n ok: boolean;\n status: 'healthy' | 'degraded' | 'unhealthy';\n wsConnected: boolean;\n uptime?: number;\n checks?: Record<string, { passed: boolean; message: string; duration?: number }>;\n error?: string;\n}\n\n/**\n * Create the status adapter.\n */\nexport function createStatusAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null,\n _runtime?: unknown\n) {\n return {\n async probeAccount(params: {\n account: ResolvedAccount;\n timeoutMs: number;\n cfg: import('openclaw/plugin-sdk').OpenClawConfig;\n }): Promise<LingyaoProbeResult> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n return {\n ok: false,\n status: 'unhealthy',\n wsConnected: false,\n error: 'Orchestrator not initialized',\n };\n }\n\n const state = orchestrator.getAccountState(params.account.id);\n if (!state) {\n return {\n ok: false,\n status: 'unhealthy',\n wsConnected: false,\n error: 'Account not started',\n };\n }\n\n try {\n const healthResult = await state.probe.runHealthChecks();\n const wsConnected = state.wsClient?.isConnected() ?? false;\n\n let status: 'healthy' | 'degraded' | 'unhealthy' = 'healthy';\n switch (healthResult.status) {\n case 'healthy':\n status = wsConnected ? 'healthy' : 'degraded';\n break;\n case 'degraded':\n status = 'degraded';\n break;\n case 'unhealthy':\n status = 'unhealthy';\n break;\n }\n\n const checks: Record<string, { passed: boolean; message: string; duration?: number }> = {};\n for (const [name, result] of healthResult.checks) {\n checks[name] = {\n passed: result.passed,\n message: result.message ?? '',\n duration: result.duration,\n };\n }\n\n return {\n ok: status !== 'unhealthy',\n status,\n wsConnected,\n uptime: Date.now() - state.startTime,\n checks,\n };\n } catch (error) {\n return {\n ok: false,\n status: 'unhealthy',\n wsConnected: false,\n error: (error as Error).message,\n };\n }\n },\n\n async buildChannelSummary(params: {\n account: ResolvedAccount;\n cfg: import('openclaw/plugin-sdk').OpenClawConfig;\n defaultAccountId: string;\n snapshot: ChannelAccountSnapshot;\n }): Promise<Record<string, unknown>> {\n const orchestrator = getOrchestrator();\n const accountId = params.account.id;\n const state = orchestrator?.getAccountState(accountId);\n const runningIds = orchestrator?.getRunningAccountIds() ?? [];\n\n return {\n accountId,\n status: state?.status ?? 'stopped',\n wsConnected: state?.wsClient?.isConnected() ?? false,\n isDefault: accountId === params.defaultAccountId,\n running: runningIds.includes(accountId),\n uptime: state ? Date.now() - state.startTime : 0,\n };\n },\n };\n}\n","/**\n * Directory Adapter - List paired devices (peers)\n *\n * Implements ChannelDirectoryAdapter:\n * - listPeers: return all active paired devices for an account\n */\n\nimport type { OpenClawConfig } from 'openclaw/plugin-sdk';\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\n\n/**\n * Directory types (not exported by SDK, defined locally to match contract).\n */\nexport interface ChannelDirectoryEntry {\n kind: 'user' | 'group' | 'channel';\n id: string;\n name?: string;\n handle?: string;\n avatarUrl?: string;\n rank?: number;\n raw?: unknown;\n}\n\nexport interface ChannelDirectoryListParams {\n cfg: OpenClawConfig;\n accountId?: string | null;\n query?: string | null;\n limit?: number | null;\n runtime: unknown;\n}\n\n/**\n * Create the directory adapter.\n */\nexport function createDirectoryAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null\n) {\n return {\n async listPeers(params: ChannelDirectoryListParams): Promise<ChannelDirectoryEntry[]> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n return [];\n }\n\n const accountId = params.accountId ?? 'default';\n const accountManager = orchestrator.getAccountManager(accountId);\n if (!accountManager) {\n return [];\n }\n\n const activeAccounts = accountManager.getActiveAccounts();\n\n let entries: ChannelDirectoryEntry[] = activeAccounts.map(account => ({\n kind: 'user' as const,\n id: account.deviceId,\n name: account.deviceInfo.name || account.deviceId,\n handle: account.deviceId,\n raw: account,\n }));\n\n if (params.query) {\n const q = params.query.toLowerCase();\n entries = entries.filter(\n e => e.id.toLowerCase().includes(q) || (e.name?.toLowerCase().includes(q) ?? false)\n );\n }\n\n if (params.limit != null && params.limit > 0) {\n entries = entries.slice(0, params.limit);\n }\n\n return entries;\n },\n };\n}\n","/**\n * Messaging Adapter - Target normalization and session resolution\n *\n * Implements ChannelMessagingAdapter:\n * - normalizeTarget: strip \"lingyao:\" prefix, return pure deviceId\n * - resolveSessionTarget: return \"lingyao:{id}\" format\n * - inferTargetChatType: always \"direct\" (Lingyao has no groups)\n */\n\nconst PREFIX = 'lingyao:';\n\nexport function createMessagingAdapter() {\n return {\n normalizeTarget(raw: string): string | undefined {\n if (!raw || typeof raw !== 'string') {\n return undefined;\n }\n\n const target = raw.startsWith(PREFIX)\n ? raw.slice(PREFIX.length)\n : raw;\n\n if (!target) {\n return undefined;\n }\n\n return target;\n },\n\n resolveSessionTarget(params: {\n kind: 'group' | 'channel';\n id: string;\n threadId?: string | null;\n }): string | undefined {\n return `${PREFIX}${params.id}`;\n },\n\n inferTargetChatType(_params: {\n to: string;\n }): 'direct' | undefined {\n return 'direct';\n },\n };\n}\n","/**\n * Outbound Adapter - Send messages from Agent to App devices\n *\n * Implements ChannelOutboundAdapter:\n * - deliveryMode: \"direct\" (synchronous via WS)\n * - sendText: send plain text notification\n * - sendPayload: send structured payload notification\n * - resolveTarget: validate and resolve target deviceId\n */\n\nimport type { OpenClawConfig } from 'openclaw/plugin-sdk';\nimport type { MultiAccountOrchestrator } from '../orchestrator.js';\n\n/**\n * Outbound types (not exported by SDK, defined locally to match contract).\n */\nexport interface ChannelOutboundContext {\n cfg: OpenClawConfig;\n to: string;\n text: string;\n mediaUrl?: string;\n accountId?: string | null;\n silent?: boolean;\n}\n\nexport interface ChannelOutboundPayloadContext extends ChannelOutboundContext {\n payload: unknown;\n}\n\nexport interface OutboundDeliveryResult {\n channel: string;\n messageId: string;\n chatId?: string;\n timestamp?: number;\n meta?: Record<string, unknown>;\n}\n\n/**\n * Create the outbound adapter.\n */\nexport function createOutboundAdapter(\n getOrchestrator: () => MultiAccountOrchestrator | null\n) {\n return {\n deliveryMode: 'direct' as const,\n\n async sendText(ctx: ChannelOutboundContext): Promise<OutboundDeliveryResult> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized');\n }\n\n const accountId = ctx.accountId ?? 'default';\n const sent = orchestrator.sendNotification(\n accountId,\n ctx.to,\n { title: 'OpenClaw', body: ctx.text }\n );\n\n if (!sent) {\n throw new Error(\n `Failed to send text to device \"${ctx.to}\" on account \"${accountId}\": not connected`\n );\n }\n\n return {\n channel: 'lingyao',\n messageId: `out_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,\n chatId: ctx.to,\n timestamp: Date.now(),\n };\n },\n\n async sendPayload(ctx: ChannelOutboundPayloadContext): Promise<OutboundDeliveryResult> {\n const orchestrator = getOrchestrator();\n if (!orchestrator) {\n throw new Error('Orchestrator not initialized');\n }\n\n const accountId = ctx.accountId ?? 'default';\n const sent = orchestrator.sendNotification(\n accountId,\n ctx.to,\n ctx.payload as Record<string, unknown>\n );\n\n if (!sent) {\n throw new Error(\n `Failed to send payload to device \"${ctx.to}\" on account \"${accountId}\": not connected`\n );\n }\n\n return {\n channel: 'lingyao',\n messageId: `out_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,\n chatId: ctx.to,\n timestamp: Date.now(),\n };\n },\n\n resolveTarget(params: {\n cfg?: OpenClawConfig;\n to?: string;\n accountId?: string | null;\n }): { ok: true; to: string } | { ok: false; error: Error } {\n const raw = params.to;\n if (!raw || typeof raw !== 'string' || raw.trim().length === 0) {\n return { ok: false, error: new Error('Target deviceId is empty or missing') };\n }\n return { ok: true, to: raw.trim() };\n },\n };\n}\n","/**\n * Setup adapter for Lingyao channel plugin.\n *\n * Lingyao has no tokens or bot credentials — setup simply enables\n * the channel and the default account. DM policy defaults to \"paired\".\n */\n\nimport { createPatchedAccountSetupAdapter } from 'openclaw/plugin-sdk/setup';\nimport type { ChannelSetupAdapter } from 'openclaw/plugin-sdk';\n\nexport function createSetupAdapter(): ChannelSetupAdapter {\n return createPatchedAccountSetupAdapter({\n channelKey: 'lingyao',\n alwaysUseAccounts: true,\n ensureChannelEnabled: true,\n ensureAccountEnabled: true,\n buildPatch() {\n // Lingyao uses device pairing via relay server, no credentials needed.\n // The default dmPolicy (\"paired\") and empty allowFrom are sufficient.\n return {};\n },\n });\n}\n","/**\n * Multi-Account Orchestrator\n *\n * Manages per-account WS/HTTP instances for multi-account support.\n * Each account gets independent LingyaoWSClient, ServerHttpClient,\n * AccountManager, MessageProcessor, Probe, and Monitor instances.\n *\n * Data flow:\n * Gateway Adapter → orchestrator.start(account) → WS connect\n * Inbound (App) → WS message → orchestrator → MessageProcessor → Agent\n * Outbound (Agent)→ orchestrator.sendNotification() → WS → App\n */\n\nimport { hostname } from 'node:os';\nimport { LINGYAO_SERVER_URL } from './types.js';\nimport type { LingyaoRuntime } from './types.js';\nimport type { ResolvedAccount } from './adapters/config.js';\nimport { ServerHttpClient } from './server-client.js';\nimport { LingyaoWSClient } from './websocket-client.js';\nimport { AccountManager } from './accounts.js';\nimport { MessageProcessor, type AgentMessage } from './bot.js';\nimport { Probe } from './probe.js';\nimport { Monitor, MonitoringEvent } from './metrics.js';\nimport { ErrorHandler } from './errors.js';\n\n/**\n * Per-account runtime state\n */\ninterface AccountState {\n accountId: string;\n wsClient: LingyaoWSClient | null;\n httpClient: ServerHttpClient | null;\n accountManager: AccountManager;\n messageProcessor: MessageProcessor | null;\n probe: Probe;\n monitor: Monitor;\n errorHandler: ErrorHandler;\n status: 'stopped' | 'starting' | 'running' | 'stopping' | 'error';\n startTime: number;\n gatewayId: string;\n}\n\n/**\n * Generate a gateway ID for an account\n */\nfunction generateGatewayId(accountId: string): string {\n const host = hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();\n const suffix = Math.random().toString(36).substring(2, 8);\n return `gw_openclaw_${host}_${accountId}_${suffix}`;\n}\n\nexport class MultiAccountOrchestrator {\n private runtime: LingyaoRuntime;\n private accounts: Map<string, AccountState> = new Map();\n private messageHandler: ((message: AgentMessage) => void | Promise<void>) | null = null;\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n }\n\n /**\n * Set the message handler for delivering messages to the Agent.\n * Propagates to all running accounts.\n */\n setMessageHandler(handler: (message: AgentMessage) => void | Promise<void>): void {\n this.messageHandler = handler;\n for (const state of this.accounts.values()) {\n if (state.messageProcessor) {\n state.messageProcessor.setMessageHandler(handler);\n }\n }\n }\n\n /**\n * Get the current message handler (for gateway adapter injection).\n */\n getMessageHandler(): ((message: AgentMessage) => void | Promise<void>) | null {\n return this.messageHandler;\n }\n\n /**\n * Start an account: create components, register to server, connect WS.\n */\n async start(account: ResolvedAccount): Promise<void> {\n const { id: accountId } = account;\n\n const existing = this.accounts.get(accountId);\n if (existing?.status === 'running') {\n this.runtime.logger.warn(`Account \"${accountId}\" is already running`);\n return;\n }\n\n this.runtime.logger.info(`Starting account \"${accountId}\"`);\n\n const gatewayId = generateGatewayId(accountId);\n const storagePrefix = `lingyao:${accountId}`;\n\n const accountManager = new AccountManager(this.runtime);\n const messageProcessor = new MessageProcessor(this.runtime, accountManager);\n const probe = new Probe(this.runtime);\n const monitor = new Monitor(this.runtime);\n const errorHandler = new ErrorHandler(this.runtime);\n const httpClient = new ServerHttpClient(\n this.runtime,\n gatewayId,\n { baseURL: LINGYAO_SERVER_URL },\n storagePrefix\n );\n\n const state: AccountState = {\n accountId,\n wsClient: null,\n httpClient,\n accountManager,\n messageProcessor,\n probe,\n monitor,\n errorHandler,\n status: 'starting',\n startTime: Date.now(),\n gatewayId,\n };\n\n this.accounts.set(accountId, state);\n\n try {\n await accountManager.initialize();\n await messageProcessor.initialize();\n\n if (this.messageHandler) {\n messageProcessor.setMessageHandler(this.messageHandler);\n }\n\n // Register to server (restore from storage or fresh register)\n await this.registerToServer(state);\n\n // Create and connect WebSocket client\n const wsClient = new LingyaoWSClient(this.runtime, {\n url: `${LINGYAO_SERVER_URL}/v1/gateway/ws`,\n gatewayId,\n token: httpClient.getGatewayToken() ?? undefined,\n reconnectInterval: 5000,\n heartbeatInterval: 30000,\n messageHandler: this.createMessageHandler(state),\n eventHandler: this.createEventHandler(state),\n });\n\n await wsClient.connect();\n state.wsClient = wsClient;\n state.status = 'running';\n\n this.runtime.logger.info(`Account \"${accountId}\" started successfully`);\n } catch (error) {\n state.status = 'error';\n this.runtime.logger.error(`Failed to start account \"${accountId}\"`, error);\n throw error;\n }\n }\n\n /**\n * Stop an account: disconnect WS, stop heartbeat.\n */\n async stop(accountId: string): Promise<void> {\n const state = this.accounts.get(accountId);\n if (!state || state.status === 'stopped') {\n return;\n }\n\n this.runtime.logger.info(`Stopping account \"${accountId}\"`);\n state.status = 'stopping';\n\n if (state.wsClient) {\n state.wsClient.disconnect();\n state.wsClient = null;\n }\n\n if (state.httpClient) {\n state.httpClient.stopHeartbeat();\n }\n\n state.status = 'stopped';\n this.runtime.logger.info(`Account \"${accountId}\" stopped`);\n }\n\n /**\n * Stop all running accounts.\n */\n async stopAll(): Promise<void> {\n const stops = Array.from(this.accounts.keys()).map(id => this.stop(id));\n await Promise.all(stops);\n }\n\n /**\n * Get account state by ID.\n */\n getAccountState(accountId: string): AccountState | undefined {\n return this.accounts.get(accountId);\n }\n\n /**\n * Get account's WS client.\n */\n getWSClient(accountId: string): LingyaoWSClient | null {\n return this.accounts.get(accountId)?.wsClient ?? null;\n }\n\n /**\n * Get account's HTTP client.\n */\n getHttpClient(accountId: string): ServerHttpClient | null {\n return this.accounts.get(accountId)?.httpClient ?? null;\n }\n\n /**\n * Get account's AccountManager.\n */\n getAccountManager(accountId: string): AccountManager | null {\n return this.accounts.get(accountId)?.accountManager ?? null;\n }\n\n /**\n * Get account's Probe.\n */\n getProbe(accountId: string): Probe | null {\n return this.accounts.get(accountId)?.probe ?? null;\n }\n\n /**\n * Get account's Monitor.\n */\n getMonitor(accountId: string): Monitor | null {\n return this.accounts.get(accountId)?.monitor ?? null;\n }\n\n /**\n * Send notification to a device on a specific account.\n * Returns true if sent, false if WS not connected.\n */\n sendNotification(\n accountId: string,\n deviceId: string,\n notification: Record<string, unknown>\n ): boolean {\n const wsClient = this.getWSClient(accountId);\n if (!wsClient || !wsClient.isConnected()) {\n return false;\n }\n\n wsClient.sendNotification(deviceId, notification);\n return true;\n }\n\n /**\n * List all running account IDs.\n */\n getRunningAccountIds(): string[] {\n return Array.from(this.accounts.entries())\n .filter(([, state]) => state.status === 'running')\n .map(([id]) => id);\n }\n\n /**\n * Register to lingyao server for a specific account.\n */\n private async registerToServer(state: AccountState): Promise<void> {\n if (!state.httpClient) {\n throw new Error('HTTP client not available');\n }\n\n try {\n const restored = await state.httpClient.restoreFromStorage();\n if (restored) {\n this.runtime.logger.info(`Account \"${state.accountId}\": session restored from storage`);\n return;\n }\n\n this.runtime.logger.info(`Account \"${state.accountId}\": registering to server...`, {\n gatewayId: state.gatewayId,\n });\n\n const response = await state.httpClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n\n this.runtime.logger.info(`Account \"${state.accountId}\": registered successfully`, {\n expiresAt: new Date(response.expiresAt).toISOString(),\n });\n } catch (error) {\n this.runtime.logger.error(`Account \"${state.accountId}\": registration failed`, error);\n // Don't throw - WS client will attempt connection anyway and auto-reconnect\n }\n }\n\n /**\n * Create message handler for inbound App messages on a specific account.\n */\n private createMessageHandler(state: AccountState) {\n return async (message: any): Promise<void> => {\n try {\n const appMessage = message.payload;\n const deviceId = appMessage.deviceId;\n const msg = appMessage.message;\n\n this.runtime.logger.info(`[${state.accountId}] Received message from App`, {\n deviceId,\n messageType: msg.type,\n messageId: msg.id,\n });\n\n state.monitor.recordEvent(MonitoringEvent.MESSAGE_RECEIVED, {\n deviceId,\n messageType: msg.type,\n });\n\n switch (msg.type) {\n case 'sync_diary':\n case 'sync_memory':\n await this.handleSyncMessage(state, deviceId, msg);\n break;\n case 'heartbeat':\n await state.accountManager.updateLastSeen(deviceId);\n state.monitor.recordEvent(MonitoringEvent.HEARTBEAT_RECEIVED, { deviceId });\n break;\n default:\n this.runtime.logger.warn(`[${state.accountId}] Unknown message type`, { type: msg.type });\n }\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] Error handling App message`, error);\n state.monitor.recordEvent(MonitoringEvent.ERROR_OCCURRED, {\n errorType: 'message_handling',\n });\n }\n };\n }\n\n /**\n * Handle sync message (diary or memory).\n */\n private async handleSyncMessage(\n state: AccountState,\n deviceId: string,\n message: {\n id: string;\n type: 'sync_diary' | 'sync_memory';\n timestamp: number;\n content: string;\n metadata?: Record<string, unknown>;\n }\n ): Promise<void> {\n if (!state.messageProcessor) {\n this.runtime.logger.warn(`[${state.accountId}] Message processor not initialized`);\n return;\n }\n\n const agentMessage: AgentMessage = {\n id: message.id,\n type: message.type === 'sync_diary' ? 'diary' : 'memory',\n from: deviceId,\n deviceId,\n content: message.content,\n metadata: message.metadata || {},\n timestamp: message.timestamp,\n };\n\n await state.messageProcessor.deliverToAgent(agentMessage);\n }\n\n /**\n * Create event handler for WS connection events on a specific account.\n */\n private createEventHandler(state: AccountState) {\n return (event: any): void => {\n switch (event.type) {\n case 'connected':\n this.runtime.logger.info(`[${state.accountId}] WS connected`, {\n connectionId: event.connectionId,\n });\n state.monitor.recordEvent(MonitoringEvent.CONNECTION_OPEN, {\n connectionId: event.connectionId,\n });\n break;\n case 'disconnected':\n this.runtime.logger.warn(`[${state.accountId}] WS disconnected`, {\n code: event.code,\n reason: event.reason,\n });\n state.monitor.recordEvent(MonitoringEvent.CONNECTION_CLOSE, {\n code: event.code,\n reason: event.reason,\n });\n break;\n case 'error':\n this.runtime.logger.error(`[${state.accountId}] WS error`, event.error);\n state.probe.recordError(event.error.message, 'websocket');\n state.monitor.recordEvent(MonitoringEvent.CONNECTION_ERROR, {\n error: event.error,\n });\n state.errorHandler.handleError(event.error);\n break;\n }\n };\n }\n}\n","/**\n * Lingyao relay server URL (internal constant, not user-configurable)\n */\nexport const LINGYAO_SERVER_URL = 'https://api.lingyao.live';\n\n/**\n * Message type enumeration for all Lingyao message types\n */\nexport enum MessageType {\n // Sync types - App to Gateway\n SYNC_DIARY = \"sync_diary\",\n SYNC_MEMORY = \"sync_memory\",\n SYNC_ACK = \"sync_ack\",\n\n // Notify types - Gateway to App\n NOTIFY_TEXT = \"notify_text\",\n NOTIFY_ACTION = \"notify_action\",\n\n // Control types\n HEARTBEAT = \"heartbeat\",\n PAIRING_REQUEST = \"pairing_request\",\n PAIRING_CONFIRM = \"pairing_confirm\",\n}\n\n/**\n * Base message structure for all Lingyao messages\n */\nexport interface LingyaoMessage {\n id: string;\n type: MessageType;\n timestamp: number;\n from: string;\n to: string;\n payload: unknown;\n signature?: string;\n}\n\n/**\n * Diary sync payload\n */\nexport interface DiarySyncPayload {\n diaryId: string;\n title?: string;\n content: string;\n emotion?: string;\n tags?: string[];\n mediaUrls?: string[];\n createdAt: number;\n updatedAt: number;\n}\n\n/**\n * Memory sync payload\n */\nexport interface MemorySyncPayload {\n memoryId: string;\n type: \"diary\" | \"fact\" | \"preference\" | \"decision\";\n content: string;\n importance: number;\n metadata?: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Notification payload\n */\nexport interface NotifyPayload {\n title: string;\n body: string;\n action?: NotifyAction;\n}\n\n/**\n * Notification action descriptor\n */\nexport interface NotifyAction {\n type: \"open_memory\" | \"view_diary\" | \"custom\";\n params: Record<string, unknown>;\n}\n\n/**\n * Device token structure\n */\nexport interface DeviceToken {\n deviceId: string;\n pairingId: string;\n token: string;\n secret: string;\n expiresAt: number;\n deviceInfo: DeviceInfo;\n}\n\n/**\n * Device information\n */\nexport interface DeviceInfo {\n name: string;\n platform: string;\n version: string;\n}\n\n/**\n * Pairing code structure\n */\nexport interface PairingCode {\n code: string;\n timestamp: number;\n nonce: string;\n expiresAt: number;\n}\n\n/**\n * Sync request from App\n */\nexport interface SyncRequest {\n deviceToken: string;\n messages: LingyaoMessage[];\n lastSyncAt?: number;\n}\n\n/**\n * Sync response from Gateway\n */\nexport interface SyncResponse {\n processed: string[];\n failed: FailedEntry[];\n}\n\n/**\n * Failed sync entry\n */\nexport interface FailedEntry {\n id: string;\n error: string;\n}\n\n/**\n * Poll request from App\n */\nexport interface PollRequest {\n deviceToken: string;\n timeout?: number;\n}\n\n/**\n * Poll response from Gateway\n */\nexport interface PollResponse {\n messages: LingyaoMessage[];\n hasMore: boolean;\n}\n\n/**\n * Ack request from App\n */\nexport interface AckRequest {\n deviceToken: string;\n messageIds: string[];\n}\n\n/**\n * Pairing confirm request from App\n */\nexport interface PairingConfirmRequest {\n pairingCode: string;\n deviceInfo: DeviceInfo;\n}\n\n/**\n * Pairing confirm response from Gateway\n */\nexport interface PairingConfirmResponse {\n pairingId: string;\n deviceToken: DeviceToken;\n}\n\n/**\n * Token refresh request\n */\nexport interface TokenRefreshRequest {\n currentToken: string;\n}\n\n/**\n * Token refresh response\n */\nexport interface TokenRefreshResponse {\n deviceToken: DeviceToken;\n}\n\n/**\n * Notify request (Agent to Gateway)\n */\nexport interface NotifyRequest {\n deviceId: string;\n notification: NotifyPayload;\n}\n\n/**\n * Per-account configuration (under channels.lingyao.accounts.<id>)\n */\nexport interface LingyaoAccountConfig {\n enabled?: boolean;\n dmPolicy?: \"paired\" | \"open\" | \"deny\";\n allowFrom?: string[];\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n}\n\n/**\n * Channel configuration\n */\nexport interface LingyaoConfig {\n enabled: boolean;\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n dmPolicy?: \"paired\" | \"open\" | \"deny\";\n allowFrom?: string[];\n accounts?: Record<string, LingyaoAccountConfig>;\n}\n\n/**\n * Plugin runtime API\n */\nexport interface LingyaoRuntime {\n config: LingyaoConfig;\n logger: {\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n debug: (message: string, ...args: unknown[]) => void;\n };\n storage: {\n get: (key: string) => Promise<unknown | null>;\n set: (key: string, value: unknown) => Promise<void>;\n delete: (key: string) => Promise<void>;\n };\n tools: {\n call: (name: string, params: Record<string, unknown>) => Promise<unknown>;\n };\n}\n\n/**\n * Account information\n */\nexport interface LingyaoAccount {\n deviceId: string;\n deviceInfo: DeviceInfo;\n deviceToken: DeviceToken;\n pairedAt: number;\n lastSeenAt: number;\n status: \"active\" | \"inactive\" | \"revoked\";\n}\n\n/**\n * Message queue entry\n */\nexport interface QueuedMessage {\n message: LingyaoMessage;\n status: \"pending\" | \"delivered\" | \"failed\";\n retryCount: number;\n createdAt: number;\n}\n\n/**\n * WebSocket connection info\n */\nexport interface WebSocketConnection {\n deviceId: string;\n ws: unknown;\n connectedAt: number;\n lastHeartbeat: number;\n}\n\n/**\n * Health status\n */\nexport interface HealthStatus {\n status: \"healthy\" | \"degraded\" | \"unhealthy\";\n uptime: number;\n activeConnections: number;\n queuedMessages: number;\n lastError?: string;\n}\n","/**\n * 灵爻服务器 HTTP 客户端\n *\n * 主动连接到灵爻服务器,实现 Gateway 注册、心跳、消息推送\n * 符合 openapi.yaml 规范\n */\n\nimport axios from 'axios';\nimport type { LingyaoRuntime } from './types.js';\n\n// 类型定义 - 避免 axios 类型导出在 DTS 构建中的问题\ntype AxiosInstance = ReturnType<typeof axios.create>;\n\ninterface AxiosErrorLike extends Error {\n response?: {\n status?: number;\n data?: any;\n };\n config?: any;\n code?: string;\n isAxiosError?: boolean;\n}\n\n/**\n * axios 错误类型守卫\n */\nfunction isAxiosError(error: unknown): error is AxiosErrorLike {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'isAxiosError' in error &&\n (error as AxiosErrorLike).isAxiosError === true\n );\n}\n\n/**\n * 服务器 API 配置\n */\nexport interface ServerConfig {\n baseURL: string;\n apiBase: string;\n timeout: number;\n connectionTimeout: number;\n}\n\n/**\n * Gateway 注册响应\n */\nexport interface GatewayRegisterResponse {\n gatewayToken: string;\n expiresAt: number;\n webhookSecret: string;\n serverConfig: {\n heartbeatInterval: number;\n maxOfflineMessages: number;\n supportedMessageTypes: string[];\n };\n}\n\n/**\n * 心跳响应\n */\nexport interface HeartbeatResponse {\n serverTime: number;\n pendingMessages: number;\n}\n\n/**\n * 发送消息请求\n */\nexport interface SendMessageRequest {\n deviceId: string;\n message: {\n id: string;\n type: 'notify_text' | 'notify_action';\n timestamp: number;\n payload: {\n title?: string;\n body?: string;\n action?: {\n type: 'open_memory' | 'view_diary' | 'custom';\n params?: Record<string, unknown>;\n };\n };\n };\n options?: {\n priority?: 'normal' | 'low' | 'high';\n ttl?: number;\n };\n}\n\n/**\n * 发送消息响应\n */\nexport interface SendMessageResponse {\n messageId: string;\n status: 'queued' | 'delivered' | 'failed';\n deliveredAt: number | null;\n queued: boolean;\n}\n\n/**\n * Gateway 状态\n */\nexport type GatewayStatus = 'online' | 'offline' | 'maintenance';\n\n/**\n * HTTP 客户端实现\n */\nexport class ServerHttpClient {\n private runtime: LingyaoRuntime;\n private config: ServerConfig;\n private axiosInstance: AxiosInstance;\n private gatewayToken: string | null = null;\n private webhookSecret: string | null = null;\n private tokenExpiresAt: number = 0;\n private heartbeatInterval: number = 30000;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private gatewayId: string;\n private isRegistered: boolean = false;\n private isConnecting: boolean = false;\n\n private storagePrefix: string;\n\n constructor(\n runtime: LingyaoRuntime,\n gatewayId: string,\n serverConfig: Partial<ServerConfig> = {},\n storagePrefix: string = 'lingyao'\n ) {\n this.runtime = runtime;\n this.gatewayId = gatewayId;\n this.storagePrefix = storagePrefix;\n this.config = {\n baseURL: serverConfig.baseURL || 'https://api.lingyao.live',\n apiBase: serverConfig.apiBase || '/v1',\n timeout: serverConfig.timeout || 30000,\n connectionTimeout: serverConfig.connectionTimeout || 5000,\n };\n\n // 创建 axios 实例\n this.axiosInstance = axios.create({\n baseURL: this.config.baseURL + this.config.apiBase,\n timeout: this.config.timeout,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n // 请求拦截器 - 添加 Token\n this.axiosInstance.interceptors.request.use(\n (config) => {\n if (this.gatewayToken && config.headers) {\n config.headers.Authorization = `Bearer ${this.gatewayToken}`;\n }\n return config;\n },\n (error) => Promise.reject(error)\n );\n\n // 响应拦截器 - 处理错误\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n async (error: unknown) => {\n if (isAxiosError(error)) {\n if (error.response?.status === 401) {\n // Token 过期,尝试刷新\n this.runtime.logger.warn('Token expired, attempting to re-register...');\n await this.register();\n }\n }\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * 注册 Gateway 到服务器\n */\n async register(\n capabilities: {\n websocket?: boolean;\n compression?: boolean;\n maxMessageSize?: number;\n } = {}\n ): Promise<GatewayRegisterResponse> {\n if (this.isConnecting) {\n throw new Error('Registration already in progress');\n }\n\n this.isConnecting = true;\n\n try {\n this.runtime.logger.info(`Registering gateway ${this.gatewayId} to server...`);\n\n const response = await this.axiosInstance.post<GatewayRegisterResponse>(\n '/gateway/register',\n {\n gatewayId: this.gatewayId,\n version: '0.1.0',\n capabilities: {\n websocket: false,\n compression: false,\n ...capabilities,\n },\n }\n );\n\n const data = response.data;\n\n this.gatewayToken = data.gatewayToken;\n this.webhookSecret = data.webhookSecret;\n this.tokenExpiresAt = data.expiresAt;\n this.heartbeatInterval = data.serverConfig.heartbeatInterval;\n this.isRegistered = true;\n\n // 保存到存储\n await this.runtime.storage.set(this.storageKey('gatewayToken'), this.gatewayToken);\n await this.runtime.storage.set(this.storageKey('webhookSecret'), this.webhookSecret);\n await this.runtime.storage.set(this.storageKey('tokenExpiresAt'), this.tokenExpiresAt);\n await this.runtime.storage.set(this.storageKey('serverConfig'), data.serverConfig);\n\n this.runtime.logger.info('Gateway registered successfully', {\n expiresAt: new Date(this.tokenExpiresAt).toISOString(),\n heartbeatInterval: this.heartbeatInterval,\n });\n\n // 启动心跳\n this.startHeartbeat();\n\n return data;\n } catch (error: unknown) {\n if (isAxiosError(error)) {\n const axiosError = error as AxiosErrorLike;\n const status = axiosError.response?.status;\n const data = axiosError.response?.data as { code?: string; details?: string };\n\n if (status === 409) {\n throw new Error('Gateway already registered');\n } else if (status === 400) {\n throw new Error(`Invalid request: ${data?.details || 'Unknown error'}`);\n }\n\n throw new Error(`Registration failed: ${axiosError.message}`);\n }\n throw error;\n } finally {\n this.isConnecting = false;\n }\n }\n\n /**\n * 发送心跳\n */\n async heartbeat(\n status: GatewayStatus = 'online',\n activeConnections: number = 0\n ): Promise<HeartbeatResponse> {\n if (!this.isRegistered || !this.gatewayToken) {\n throw new Error('Gateway not registered');\n }\n\n try {\n const response = await this.axiosInstance.post<HeartbeatResponse>(\n '/gateway/heartbeat',\n {\n timestamp: Date.now(),\n status,\n activeConnections,\n }\n );\n\n return response.data;\n } catch (error: unknown) {\n if (isAxiosError(error)) {\n const axiosError = error as AxiosErrorLike;\n this.runtime.logger.error('Heartbeat failed', {\n status: axiosError.response?.status,\n data: axiosError.response?.data,\n });\n }\n throw error;\n }\n }\n\n /**\n * 发送消息到灵爻 App\n */\n async sendMessage(\n deviceId: string,\n messageType: 'notify_text' | 'notify_action',\n payload: SendMessageRequest['message']['payload'],\n options?: SendMessageRequest['options']\n ): Promise<SendMessageResponse> {\n if (!this.isRegistered || !this.gatewayToken) {\n throw new Error('Gateway not registered');\n }\n\n const messageId = this.generateMessageId();\n\n try {\n const response = await this.axiosInstance.post<SendMessageResponse>(\n '/gateway/messages',\n {\n deviceId,\n message: {\n id: messageId,\n type: messageType,\n timestamp: Date.now(),\n payload,\n },\n options: options || {},\n }\n );\n\n this.runtime.logger.debug('Message sent', {\n messageId,\n deviceId,\n status: response.data.status,\n });\n\n return response.data;\n } catch (error: unknown) {\n if (isAxiosError(error)) {\n const axiosError = error as AxiosErrorLike;\n const status = axiosError.response?.status;\n const data = axiosError.response?.data as { error?: string };\n\n if (status === 404) {\n throw new Error(`Device not found: ${deviceId}`);\n } else if (status === 429) {\n throw new Error('Message queue full, please retry later');\n }\n\n throw new Error(`Send message failed: ${data?.error || axiosError.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 启动心跳循环\n */\n private startHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n }\n\n this.heartbeatTimer = setInterval(\n async () => {\n try {\n await this.heartbeat();\n } catch (error) {\n this.runtime.logger.error('Heartbeat error', error);\n }\n },\n this.heartbeatInterval\n );\n\n this.runtime.logger.info('Heartbeat started', {\n interval: this.heartbeatInterval,\n });\n }\n\n /**\n * 停止心跳循环\n */\n stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n this.runtime.logger.info('Heartbeat stopped');\n }\n }\n\n /**\n * 获取 Webhook Secret\n */\n getWebhookSecret(): string | null {\n return this.webhookSecret;\n }\n\n /**\n * 获取 Gateway Token\n */\n getGatewayToken(): string | null {\n return this.gatewayToken;\n }\n\n /**\n * 检查 Token 是否即将过期\n */\n isTokenExpiringSoon(thresholdMs: number = 7 * 24 * 60 * 60 * 1000): boolean {\n return this.tokenExpiresAt - Date.now() < thresholdMs;\n }\n\n /**\n * 检查是否已注册\n */\n isReady(): boolean {\n return this.isRegistered && !!this.gatewayToken;\n }\n\n /**\n * 从存储恢复会话\n */\n async restoreFromStorage(): Promise<boolean> {\n try {\n const token = await this.runtime.storage.get(this.storageKey('gatewayToken'));\n const secret = await this.runtime.storage.get(this.storageKey('webhookSecret'));\n const expiresAt = await this.runtime.storage.get(this.storageKey('tokenExpiresAt')) as number | undefined;\n const serverConfig = await this.runtime.storage.get(this.storageKey('serverConfig')) as GatewayRegisterResponse['serverConfig'] | undefined;\n\n if (token && secret && expiresAt && serverConfig) {\n // 检查是否过期\n if (expiresAt > Date.now()) {\n this.gatewayToken = token as string;\n this.webhookSecret = secret as string;\n this.tokenExpiresAt = expiresAt;\n this.heartbeatInterval = serverConfig.heartbeatInterval;\n this.isRegistered = true;\n\n // 启动心跳\n this.startHeartbeat();\n\n this.runtime.logger.info('Session restored from storage', {\n expiresAt: new Date(this.tokenExpiresAt).toISOString(),\n });\n\n return true;\n } else {\n this.runtime.logger.warn('Stored token expired, need to re-register');\n }\n }\n } catch (error) {\n this.runtime.logger.error('Failed to restore session from storage', error);\n }\n\n return false;\n }\n\n /**\n * Build a namespaced storage key for multi-account support\n */\n private storageKey(name: string): string {\n return `${this.storagePrefix}:${name}`;\n }\n\n /**\n * 生成消息 ID\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n }\n\n}\n","/**\n * Lingyao WebSocket Client\n *\n * 主动连接到 lingyao.live 服务器的 WebSocket 客户端\n * 实现:\n * - 自动连接和重连\n * - 心跳机制\n * - 消息发送和接收\n * - 在线状态管理\n */\n\nimport WebSocket from \"ws\";\nimport type { LingyaoRuntime } from \"./types.js\";\n\n/**\n * WebSocket 连接状态\n */\nexport type ConnectionState = \"connecting\" | \"connected\" | \"disconnected\" | \"error\";\n\n/**\n * WebSocket 消息类型\n */\nexport enum WSMessageType {\n // 客户端 → 服务器\n REGISTER = \"register\",\n HEARTBEAT = \"heartbeat\",\n SEND_MESSAGE = \"send_message\",\n ACK = \"ack\",\n\n // 服务器 → 客户端\n REGISTERED = \"registered\",\n HEARTBEAT_ACK = \"heartbeat_ack\",\n MESSAGE_DELIVERED = \"message_delivered\",\n MESSAGE_FAILED = \"message_failed\",\n APP_MESSAGE = \"app_message\", // 来自 App 的消息\n DEVICE_ONLINE = \"device_online\",\n ERROR = \"error\",\n}\n\n/**\n * WebSocket 消息基础格式\n */\nexport interface WSMessage {\n type: WSMessageType | string;\n id: string;\n timestamp: number;\n payload?: any;\n}\n\n/**\n * 注册消息\n */\nexport interface RegisterMessage extends WSMessage {\n type: WSMessageType.REGISTER;\n payload: {\n gatewayId: string;\n version: string;\n capabilities: {\n websocket: boolean;\n compression: boolean;\n maxMessageSize: number;\n };\n };\n}\n\n/**\n * 心跳消息\n */\nexport interface HeartbeatMessage extends WSMessage {\n type: WSMessageType.HEARTBEAT;\n payload: {\n timestamp: number;\n status: \"online\";\n };\n}\n\n/**\n * 发送消息\n */\nexport interface SendMessage extends WSMessage {\n type: WSMessageType.SEND_MESSAGE;\n payload: {\n deviceId: string;\n message: {\n id: string;\n type: \"notify_text\" | \"notify_action\";\n timestamp: number;\n payload: any;\n };\n };\n}\n\n/**\n * 接收到的 App 消息\n */\nexport interface AppMessage extends WSMessage {\n type: WSMessageType.APP_MESSAGE;\n payload: {\n deviceId: string;\n message: {\n id: string;\n type: \"sync_diary\" | \"sync_memory\" | \"heartbeat\";\n timestamp: number;\n content: string;\n metadata?: Record<string, unknown>;\n };\n };\n}\n\n/**\n * WebSocket 客户端事件\n */\nexport type WSClientEvent =\n | { type: \"connected\"; connectionId: string }\n | { type: \"disconnected\"; code: number; reason: string }\n | { type: \"error\"; error: Error }\n | { type: \"message\"; message: WSMessage }\n | { type: \"appMessage\"; deviceId: string; message: AppMessage[\"payload\"][\"message\"] };\n\n/**\n * WebSocket 客户端配置\n */\nexport interface WSClientConfig {\n url: string;\n gatewayId: string;\n token?: string;\n reconnectInterval: number;\n heartbeatInterval: number;\n messageHandler?: (message: AppMessage) => void | Promise<void>;\n eventHandler?: (event: WSClientEvent) => void;\n}\n\n/**\n * Lingyao WebSocket Client\n *\n * 主动连接到 lingyao.live 服务器的 WebSocket 客户端\n */\nexport class LingyaoWSClient {\n private config: WSClientConfig;\n private ws: WebSocket | null = null;\n private state: ConnectionState = \"disconnected\";\n private connectionId: string | null = null;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private messageHandlers: Map<string, (msg: WSMessage) => void> = new Map();\n private logger: LingyaoRuntime[\"logger\"];\n\n constructor(runtime: LingyaoRuntime, config: WSClientConfig) {\n this.logger = runtime.logger;\n this.config = { ...config };\n\n this.registerMessageHandler(WSMessageType.REGISTERED, this.handleRegistered.bind(this));\n this.registerMessageHandler(WSMessageType.HEARTBEAT_ACK, this.handleHeartbeatAck.bind(this));\n this.registerMessageHandler(WSMessageType.MESSAGE_DELIVERED, this.handleMessageDelivered.bind(this));\n this.registerMessageHandler(WSMessageType.MESSAGE_FAILED, this.handleMessageFailed.bind(this));\n this.registerMessageHandler(WSMessageType.APP_MESSAGE, this.handleAppMessage.bind(this));\n this.registerMessageHandler(WSMessageType.ERROR, this.handleError.bind(this));\n }\n\n /**\n * 连接到服务器\n */\n async connect(): Promise<void> {\n if (this.state === \"connecting\" || this.state === \"connected\") {\n this.logger.warn(\"WebSocket already connecting or connected\");\n return;\n }\n\n this.state = \"connecting\";\n this.emitEvent({ type: \"disconnected\", code: 0, reason: \"Reconnecting\" });\n\n try {\n this.logger.info(`Connecting to Lingyao server: ${this.config.url}`);\n\n const wsUrl = this.config.token\n ? `${this.config.url}?token=${encodeURIComponent(this.config.token)}`\n : this.config.url;\n\n this.ws = new WebSocket(wsUrl, {\n headers: {\n \"X-Gateway-ID\": this.config.gatewayId,\n },\n });\n\n this.setupWebSocketHandlers();\n } catch (error) {\n this.state = \"error\";\n this.emitEvent({ type: \"error\", error: error as Error });\n this.scheduleReconnect();\n }\n }\n\n /**\n * 设置 WebSocket 事件处理器\n */\n private setupWebSocketHandlers(): void {\n if (!this.ws) return;\n\n this.ws.on(\"open\", () => {\n this.handleOpen();\n });\n\n this.ws.on(\"message\", async (data: Buffer) => {\n await this.handleMessage(data);\n });\n\n this.ws.on(\"error\", (error) => {\n this.handleErrorEvent(error);\n });\n\n this.ws.on(\"close\", (code: number, reason: Buffer) => {\n this.handleClose(code, reason.toString());\n });\n }\n\n /**\n * 处理连接打开\n */\n private handleOpen(): void {\n this.state = \"connected\";\n this.connectionId = this.generateConnectionId();\n\n this.logger.info(\"WebSocket connected to Lingyao server\", {\n connectionId: this.connectionId,\n });\n\n this.emitEvent({\n type: \"connected\",\n connectionId: this.connectionId!,\n });\n\n // 发送注册消息\n this.sendRegister();\n\n // 启动心跳\n this.startHeartbeat();\n\n // 清除重连定时器\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n /**\n * 处理接收消息\n */\n private async handleMessage(data: Buffer): Promise<void> {\n try {\n const message: WSMessage = JSON.parse(data.toString());\n this.logger.debug(\"Received message from server\", { type: message.type });\n\n const handler = this.messageHandlers.get(message.type);\n if (handler) {\n handler(message);\n } else {\n this.logger.warn(\"No handler for message type\", { type: message.type });\n }\n\n this.emitEvent({ type: \"message\", message });\n } catch (error) {\n this.logger.error(\"Error handling message\", error);\n }\n }\n\n /**\n * 处理连接错误\n */\n private handleErrorEvent(error: Error): void {\n this.logger.error(\"WebSocket error\", error);\n this.state = \"error\";\n this.emitEvent({ type: \"error\", error });\n }\n\n /**\n * 处理连接关闭\n */\n private handleClose(code: number, reason: string): void {\n this.logger.warn(\"WebSocket connection closed\", { code, reason });\n this.state = \"disconnected\";\n this.connectionId = null;\n\n this.stopHeartbeat();\n this.emitEvent({ type: \"disconnected\", code, reason });\n\n // 如果不是正常关闭,尝试重连\n if (code !== 1000) {\n this.scheduleReconnect();\n }\n }\n\n /**\n * 发送注册消息\n */\n private sendRegister(): void {\n const message: RegisterMessage = {\n type: WSMessageType.REGISTER,\n id: this.generateMessageId(),\n timestamp: Date.now(),\n payload: {\n gatewayId: this.config.gatewayId,\n version: \"0.2.0\",\n capabilities: {\n websocket: true,\n compression: false,\n maxMessageSize: 1048576, // 1MB\n },\n },\n };\n\n this.send(message);\n }\n\n /**\n * 处理注册响应\n */\n private handleRegistered(message: WSMessage): void {\n this.logger.info(\"Gateway registered to Lingyao server\", {\n messageId: message.id,\n });\n }\n\n /**\n * 发送心跳\n */\n private sendHeartbeat(): void {\n const message: HeartbeatMessage = {\n type: WSMessageType.HEARTBEAT,\n id: this.generateMessageId(),\n timestamp: Date.now(),\n payload: {\n timestamp: Date.now(),\n status: \"online\",\n },\n };\n\n this.send(message);\n }\n\n /**\n * 处理心跳确认\n */\n private handleHeartbeatAck(_message: WSMessage): void {\n this.logger.debug(\"Heartbeat acknowledged\");\n }\n\n /**\n * 启动心跳\n */\n private startHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n }\n\n this.heartbeatTimer = setInterval(() => {\n if (this.state === \"connected\") {\n this.sendHeartbeat();\n }\n }, this.config.heartbeatInterval);\n }\n\n /**\n * 停止心跳\n */\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n /**\n * 安排重连\n */\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return; // 已经安排了重连\n }\n\n this.logger.info(`Scheduling reconnect in ${this.config.reconnectInterval}ms`);\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, this.config.reconnectInterval);\n }\n\n /**\n * 发送消息到服务器\n */\n send(message: WSMessage): void {\n if (!this.ws || this.state !== \"connected\") {\n throw new Error(\"WebSocket not connected\");\n }\n\n try {\n this.ws.send(JSON.stringify(message));\n this.logger.debug(\"Sent message to server\", { type: message.type });\n } catch (error) {\n this.logger.error(\"Failed to send message\", error);\n throw error;\n }\n }\n\n /**\n * 发送通知到鸿蒙 App\n */\n sendNotification(deviceId: string, notification: any): void {\n const message: SendMessage = {\n type: WSMessageType.SEND_MESSAGE,\n id: this.generateMessageId(),\n timestamp: Date.now(),\n payload: {\n deviceId,\n message: {\n id: this.generateMessageId(),\n type: \"notify_action\",\n timestamp: Date.now(),\n payload: notification,\n },\n },\n };\n\n this.send(message);\n }\n\n /**\n * 处理 App 消息\n */\n private handleAppMessage(message: WSMessage): void {\n if (message.type !== WSMessageType.APP_MESSAGE) return;\n\n const appMessage = message as AppMessage;\n this.logger.info(\"Received message from App\", {\n deviceId: appMessage.payload.deviceId,\n messageType: appMessage.payload.message.type,\n });\n\n if (this.config.messageHandler) {\n // 异步处理,不阻塞 WebSocket\n Promise.resolve(this.config.messageHandler(appMessage)).catch((error: unknown) => {\n this.logger.error(\"Error handling App message\", error);\n });\n }\n }\n\n /**\n * 处理消息发送成功\n */\n private handleMessageDelivered(message: WSMessage): void {\n this.logger.debug(\"Message delivered successfully\", {\n messageId: message.id,\n });\n }\n\n /**\n * 处理消息发送失败\n */\n private handleMessageFailed(message: WSMessage): void {\n this.logger.warn(\"Message delivery failed\", {\n messageId: message.id,\n });\n }\n\n /**\n * 处理服务器错误\n */\n private handleError(message: WSMessage): void {\n this.logger.error(\"Server error\", message);\n }\n\n /**\n * 注册消息处理器\n */\n registerMessageHandler(\n type: string,\n handler: (message: WSMessage) => void\n ): void {\n this.messageHandlers.set(type, handler);\n }\n\n /**\n * 发送事件\n */\n private emitEvent(event: WSClientEvent): void {\n if (this.config.eventHandler) {\n this.config.eventHandler(event);\n }\n }\n\n /**\n * 断开连接\n */\n disconnect(): void {\n this.logger.info(\"Disconnecting WebSocket from Lingyao server\");\n\n this.stopHeartbeat();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, \"Client disconnect\");\n this.ws = null;\n }\n\n this.state = \"disconnected\";\n this.connectionId = null;\n }\n\n /**\n * 获取连接状态\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * 获取连接 ID\n */\n getConnectionId(): string | null {\n return this.connectionId;\n }\n\n /**\n * 是否已连接\n */\n isConnected(): boolean {\n return this.state === \"connected\";\n }\n\n /**\n * 生成消息 ID\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n }\n\n /**\n * 生成连接 ID\n */\n private generateConnectionId(): string {\n return `conn_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n }\n}\n","import type {\n LingyaoAccount,\n DeviceToken,\n DeviceInfo,\n LingyaoRuntime\n} from \"./types.js\";\n\nconst STORAGE_KEY_ACCOUNTS = \"lingyao:accounts\";\nconst STORAGE_KEY_PENDING_PAIRINGS = \"lingyao:pending_pairings\";\n\n/**\n * Account storage and management\n */\nexport class AccountManager {\n private runtime: LingyaoRuntime;\n private accounts: Map<string, LingyaoAccount> = new Map();\n private pendingPairings: Map<string, PairingSession> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n }\n\n /**\n * Initialize account manager from storage\n */\n async initialize(): Promise<void> {\n try {\n const stored = await this.runtime.storage.get(STORAGE_KEY_ACCOUNTS);\n if (stored && Array.isArray(stored)) {\n for (const account of stored) {\n this.accounts.set(account.deviceId, account);\n }\n }\n\n const pending = await this.runtime.storage.get(STORAGE_KEY_PENDING_PAIRINGS);\n if (pending && Array.isArray(pending)) {\n // Clean up expired pairings\n const now = Date.now();\n for (const session of pending) {\n if (session.expiresAt > now) {\n this.pendingPairings.set(session.code, session);\n }\n }\n }\n\n this.runtime.logger.info(\n `AccountManager initialized: ${this.accounts.size} accounts, ${this.pendingPairings.size} pending pairings`\n );\n } catch (error) {\n this.runtime.logger.error(\"Failed to initialize AccountManager\", error);\n }\n }\n\n /**\n * Get account by device ID\n */\n getAccount(deviceId: string): LingyaoAccount | undefined {\n return this.accounts.get(deviceId);\n }\n\n /**\n * Get account by device token\n */\n getAccountByToken(token: string): LingyaoAccount | undefined {\n for (const account of this.accounts.values()) {\n if (account.deviceToken.token === token) {\n return account;\n }\n }\n return undefined;\n }\n\n /**\n * Get all active accounts\n */\n getActiveAccounts(): LingyaoAccount[] {\n return Array.from(this.accounts.values()).filter(\n (acc) => acc.status === \"active\"\n );\n }\n\n /**\n * Create a new pairing session\n */\n async createPairingSession(\n code: string,\n expiresAt: number\n ): Promise<void> {\n const session: PairingSession = {\n code,\n createdAt: Date.now(),\n expiresAt,\n };\n\n this.pendingPairings.set(code, session);\n await this.savePendingPairings();\n }\n\n /**\n * Get pairing session by code\n */\n getPairingSession(code: string): PairingSession | undefined {\n return this.pendingPairings.get(code);\n }\n\n /**\n * Remove a pending pairing (e.g. expired or cancelled)\n */\n async deletePendingPairing(code: string): Promise<void> {\n if (!this.pendingPairings.delete(code)) {\n return;\n }\n await this.savePendingPairings();\n }\n\n /**\n * Confirm pairing and create account\n */\n async confirmPairing(\n pairingCode: string,\n deviceToken: DeviceToken,\n deviceInfo: DeviceInfo\n ): Promise<LingyaoAccount | null> {\n const session = this.pendingPairings.get(pairingCode);\n if (!session) {\n return null;\n }\n\n const now = Date.now();\n if (session.expiresAt < now) {\n this.pendingPairings.delete(pairingCode);\n await this.savePendingPairings();\n return null;\n }\n\n const account: LingyaoAccount = {\n deviceId: deviceToken.deviceId,\n deviceInfo,\n deviceToken,\n pairedAt: now,\n lastSeenAt: now,\n status: \"active\",\n };\n\n this.accounts.set(deviceToken.deviceId, account);\n this.pendingPairings.delete(pairingCode);\n\n await Promise.all([\n this.saveAccounts(),\n this.savePendingPairings(),\n ]);\n\n this.runtime.logger.info(\n `Account paired: ${deviceToken.deviceId} (${deviceInfo.name})`\n );\n\n return account;\n }\n\n /**\n * Update account's last seen timestamp\n */\n async updateLastSeen(deviceId: string): Promise<void> {\n const account = this.accounts.get(deviceId);\n if (account) {\n account.lastSeenAt = Date.now();\n await this.saveAccounts();\n }\n }\n\n /**\n * Revoke an account\n */\n async revokeAccount(deviceId: string): Promise<boolean> {\n const account = this.accounts.get(deviceId);\n if (!account) {\n return false;\n }\n\n account.status = \"revoked\";\n await this.saveAccounts();\n\n this.runtime.logger.info(`Account revoked: ${deviceId}`);\n return true;\n }\n\n /**\n * Refresh device token\n */\n async refreshDeviceToken(\n deviceId: string,\n newToken: DeviceToken\n ): Promise<boolean> {\n const account = this.accounts.get(deviceId);\n if (!account) {\n return false;\n }\n\n account.deviceToken = newToken;\n await this.saveAccounts();\n\n this.runtime.logger.info(`Token refreshed for: ${deviceId}`);\n return true;\n }\n\n /**\n * Clean up expired accounts\n */\n async cleanupExpired(): Promise<void> {\n const now = Date.now();\n const expired: string[] = [];\n\n for (const [deviceId, account] of this.accounts.entries()) {\n if (account.deviceToken.expiresAt < now) {\n expired.push(deviceId);\n }\n }\n\n for (const deviceId of expired) {\n this.accounts.delete(deviceId);\n }\n\n if (expired.length > 0) {\n await this.saveAccounts();\n this.runtime.logger.info(`Cleaned up ${expired.length} expired accounts`);\n }\n }\n\n /**\n * Save accounts to storage\n */\n private async saveAccounts(): Promise<void> {\n const accounts = Array.from(this.accounts.values());\n await this.runtime.storage.set(STORAGE_KEY_ACCOUNTS, accounts);\n }\n\n /**\n * Save pending pairings to storage\n */\n private async savePendingPairings(): Promise<void> {\n const sessions = Array.from(this.pendingPairings.values());\n await this.runtime.storage.set(STORAGE_KEY_PENDING_PAIRINGS, sessions);\n }\n}\n\ninterface PairingSession {\n code: string;\n createdAt: number;\n expiresAt: number;\n}\n","import { createHmac, createHash, randomBytes, timingSafeEqual } from \"crypto\";\nimport type { LingyaoMessage } from \"./types.js\";\n\n/**\n * Cryptographic utilities for message signing and verification\n */\nexport class CryptoManager {\n /**\n * Sign a message with HMAC-SHA256\n */\n static signMessage(message: LingyaoMessage, secret: string): string {\n const messageString = this.prepareMessageForSigning(message);\n return createHmac(\"sha256\", secret)\n .update(messageString)\n .digest(\"base64\");\n }\n\n /**\n * Verify a message signature\n */\n static verifyMessage(\n message: LingyaoMessage,\n signature: string,\n secret: string\n ): boolean {\n try {\n const expectedSignature = this.signMessage(message, secret);\n\n // Use timing-safe comparison to prevent timing attacks\n const expectedBuffer = Buffer.from(expectedSignature);\n const providedBuffer = Buffer.from(signature);\n\n if (expectedBuffer.length !== providedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(expectedBuffer, providedBuffer);\n } catch {\n return false;\n }\n }\n\n /**\n * Sign any data string\n */\n static sign(data: string, secret: string): string {\n return createHmac(\"sha256\", secret)\n .update(data)\n .digest(\"base64\");\n }\n\n /**\n * Verify data signature\n */\n static verify(\n data: string,\n signature: string,\n secret: string\n ): boolean {\n try {\n const expectedSignature = this.sign(data, secret);\n const expectedBuffer = Buffer.from(expectedSignature);\n const providedBuffer = Buffer.from(signature);\n\n if (expectedBuffer.length !== providedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(expectedBuffer, providedBuffer);\n } catch {\n return false;\n }\n }\n\n /**\n * Generate a random nonce\n */\n static generateNonce(): string {\n return randomBytes(16).toString(\"hex\");\n }\n\n /**\n * Hash data using SHA-256\n */\n static hash(data: string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n }\n\n /**\n * Generate a cryptographically random ID\n */\n static generateId(): string {\n return randomBytes(16).toString(\"hex\");\n }\n\n /**\n * Prepare message for signing by serializing in a deterministic way\n */\n private static prepareMessageForSigning(message: LingyaoMessage): string {\n // Create a canonical string representation\n const parts = [\n message.id,\n message.type,\n message.timestamp.toString(),\n message.from,\n message.to,\n JSON.stringify(message.payload),\n ];\n\n return parts.join(\"|\");\n }\n\n /**\n * Encrypt data (for future use)\n */\n static encrypt(data: string, _key: string): {\n encrypted: string;\n iv: string;\n } {\n const iv = randomBytes(16);\n // Note: This is a placeholder for future encryption implementation\n // In production, use proper encryption like AES-256-GCM\n return {\n encrypted: data, // Placeholder\n iv: iv.toString(\"hex\"),\n };\n }\n\n /**\n * Decrypt data (for future use)\n */\n static decrypt(encrypted: string, _key: string, _iv: string): string {\n // Note: This is a placeholder for future decryption implementation\n return encrypted;\n }\n\n /**\n * Derive a key from a password and salt\n */\n static deriveKey(password: string, salt: string): string {\n return createHmac(\"sha256\", salt)\n .update(password)\n .digest(\"hex\");\n }\n\n /**\n * Generate a fingerprint for a device\n */\n static generateDeviceFingerprint(deviceInfo: Record<string, unknown>): string {\n const data = JSON.stringify(deviceInfo, Object.keys(deviceInfo).sort());\n return this.hash(data).substring(0, 16);\n }\n\n /**\n * Verify message timestamp is within acceptable range\n */\n static verifyTimestamp(\n timestamp: number,\n maxDriftSeconds: number = 300\n ): boolean {\n const now = Date.now();\n const drift = Math.abs(now - timestamp);\n return drift <= maxDriftSeconds * 1000;\n }\n\n /**\n * Check if a message is a replay attack\n */\n static checkReplay(\n messageId: string,\n seenMessages: Set<string>,\n _maxAge: number = 3600000 // 1 hour\n ): boolean {\n return seenMessages.has(messageId);\n }\n\n /**\n * Mark a message as seen to prevent replay\n */\n static markMessageSeen(\n messageId: string,\n seenMessages: Set<string>,\n _maxAge: number = 3600000\n ): void {\n seenMessages.add(messageId);\n\n // Clean up old entries\n if (seenMessages.size > 10000) {\n // Keep set size manageable\n const entries = Array.from(seenMessages);\n // In production, use a proper TTL-based cache\n // For now, clear half the entries if we get too large\n for (let i = 0; i < entries.length / 2; i++) {\n seenMessages.delete(entries[i]);\n }\n }\n }\n}\n","import type {\n LingyaoRuntime,\n LingyaoMessage,\n DiarySyncPayload,\n MemorySyncPayload,\n SyncRequest,\n SyncResponse\n} from \"./types.js\";\nimport { MessageType } from \"./types.js\";\nimport { AccountManager } from \"./accounts.js\";\nimport { CryptoManager } from \"./crypto.js\";\n\n/**\n * Agent message format - messages passed directly to Agent\n */\nexport interface AgentMessage {\n id: string;\n type: \"diary\" | \"memory\" | \"heartbeat\";\n from: string;\n deviceId: string;\n content: string;\n metadata: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Message handler callback for delivering messages to Agent\n */\nexport type MessageHandler = (message: AgentMessage) => void | Promise<void>;\n\n/**\n * Message queue entry for polling\n */\ninterface QueuedMessage {\n message: LingyaoMessage;\n deviceId: string;\n createdAt: number;\n delivered: boolean;\n}\n\n/**\n * Message Processor - Handles incoming messages and routes them to Agent\n */\nexport class MessageProcessor {\n private runtime: LingyaoRuntime;\n private accountManager: AccountManager;\n private messageQueue: Map<string, QueuedMessage[]> = new Map();\n private seenMessages: Set<string> = new Set();\n private messageHandler: MessageHandler | null = null;\n private readonly maxQueueSize: number = 100;\n\n constructor(\n runtime: LingyaoRuntime,\n accountManager: AccountManager\n ) {\n this.runtime = runtime;\n this.accountManager = accountManager;\n }\n\n /**\n * Initialize the message processor\n */\n async initialize(): Promise<void> {\n this.runtime.logger.info(\"Message Processor initialized\");\n }\n\n /**\n * Set the message handler for delivering messages to Agent\n */\n setMessageHandler(handler: MessageHandler): void {\n this.messageHandler = handler;\n }\n\n /**\n * Get the currently registered Agent message handler.\n */\n getMessageHandler(): MessageHandler | null {\n return this.messageHandler;\n }\n\n /**\n * Deliver a normalized message directly to the registered Agent handler.\n */\n async deliverToAgent(message: AgentMessage): Promise<void> {\n if (!this.messageHandler) {\n this.runtime.logger.warn(\"No message handler set, message not delivered to Agent\");\n return;\n }\n\n await this.messageHandler(message);\n }\n\n /**\n * Process sync request from app\n */\n async processSync(\n deviceId: string,\n request: SyncRequest\n ): Promise<SyncResponse> {\n const account = this.accountManager.getAccount(deviceId);\n if (!account) {\n return {\n processed: [],\n failed: request.messages.map((m) => ({\n id: m.id,\n error: \"Device not found\",\n })),\n };\n }\n\n const processed: string[] = [];\n const failed: Array<{ id: string; error: string }> = [];\n\n for (const message of request.messages) {\n try {\n // Validate message signature if present\n if (message.signature) {\n const isValid = CryptoManager.verifyMessage(\n message,\n message.signature,\n account.deviceToken.secret\n );\n\n if (!isValid) {\n failed.push({ id: message.id, error: \"Invalid signature\" });\n continue;\n }\n }\n\n // Check for duplicates\n if (this.isMessageSeen(message.id)) {\n this.runtime.logger.debug(`Duplicate message ignored: ${message.id}`);\n processed.push(message.id);\n continue;\n }\n\n // Verify timestamp\n if (!CryptoManager.verifyTimestamp(message.timestamp)) {\n failed.push({ id: message.id, error: \"Invalid timestamp\" });\n continue;\n }\n\n // Process message based on type\n const result = await this.processMessage(deviceId, message);\n\n if (result.success) {\n processed.push(message.id);\n this.markMessageSeen(message.id);\n } else {\n failed.push({ id: message.id, error: result.error ?? \"Processing failed\" });\n }\n } catch (error) {\n this.runtime.logger.error(`Error processing message ${message.id}`, error);\n failed.push({ id: message.id, error: \"Internal error\" });\n }\n }\n\n return { processed, failed };\n }\n\n /**\n * Process a single message\n */\n private async processMessage(\n deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n this.runtime.logger.debug(\n `Processing message ${message.type} from ${deviceId}`\n );\n\n switch (message.type) {\n case MessageType.SYNC_DIARY:\n return await this.processDiarySync(deviceId, message);\n\n case MessageType.SYNC_MEMORY:\n return await this.processMemorySync(deviceId, message);\n\n case MessageType.SYNC_ACK:\n return await this.processSyncAck(deviceId, message);\n\n case MessageType.HEARTBEAT:\n return await this.processHeartbeat(deviceId, message);\n\n default:\n return { success: false, error: \"Unknown message type\" };\n }\n }\n\n /**\n * Process diary sync - Pass directly to Agent\n */\n private async processDiarySync(\n deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n const payload = message.payload as DiarySyncPayload;\n\n // Create Agent message format\n const agentMessage: AgentMessage = {\n id: message.id,\n type: \"diary\",\n from: `lingyao:${deviceId}`,\n deviceId,\n content: payload.content,\n metadata: {\n diaryId: payload.diaryId,\n title: payload.title,\n emotion: payload.emotion,\n tags: payload.tags,\n mediaUrls: payload.mediaUrls,\n createdAt: payload.createdAt,\n updatedAt: payload.updatedAt,\n },\n timestamp: message.timestamp,\n };\n\n // Pass directly to Agent via message handler\n await this.deliverToAgent(agentMessage);\n\n this.runtime.logger.info(\n `Diary message passed to Agent: ${payload.diaryId} from ${deviceId}`\n );\n\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Diary sync error\", error);\n return { success: false, error: \"Failed to sync diary\" };\n }\n }\n\n /**\n * Process memory sync - Pass directly to Agent\n */\n private async processMemorySync(\n deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n const payload = message.payload as MemorySyncPayload;\n\n // Create Agent message format\n const agentMessage: AgentMessage = {\n id: message.id,\n type: \"memory\",\n from: `lingyao:${deviceId}`,\n deviceId,\n content: payload.content,\n metadata: {\n memoryId: payload.memoryId,\n memoryType: payload.type,\n importance: payload.importance,\n ...payload.metadata,\n timestamp: payload.timestamp,\n },\n timestamp: message.timestamp,\n };\n\n // Pass directly to Agent via message handler\n await this.deliverToAgent(agentMessage);\n\n this.runtime.logger.info(\n `Memory message passed to Agent: ${payload.memoryId} from ${deviceId}`\n );\n\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Memory sync error\", error);\n return { success: false, error: \"Failed to sync memory\" };\n }\n }\n\n /**\n * Process sync acknowledgment\n */\n private async processSyncAck(\n _deviceId: string,\n message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n // Handle acknowledgment of received messages\n this.runtime.logger.debug(`Sync ack received: ${message.id}`);\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Sync ack error\", error);\n return { success: false, error: \"Failed to process ack\" };\n }\n }\n\n /**\n * Process heartbeat\n */\n private async processHeartbeat(\n deviceId: string,\n _message: LingyaoMessage\n ): Promise<{ success: boolean; error?: string }> {\n try {\n await this.accountManager.updateLastSeen(deviceId);\n return { success: true };\n } catch (error) {\n this.runtime.logger.error(\"Heartbeat error\", error);\n return { success: false, error: \"Failed to process heartbeat\" };\n }\n }\n\n /**\n * Poll for new messages (long-polling)\n */\n async pollMessages(\n deviceId: string,\n timeout: number = 30000\n ): Promise<LingyaoMessage[]> {\n return new Promise((resolve) => {\n const startTime = Date.now();\n const checkInterval = 100; // Check every 100ms\n\n const checkForMessages = () => {\n const queue = this.messageQueue.get(deviceId);\n const messages = queue?.filter((m) => !m.delivered) ?? [];\n\n if (messages.length > 0) {\n // Mark messages as delivered\n for (const msg of messages) {\n msg.delivered = true;\n }\n resolve(messages.map((m) => m.message));\n return;\n }\n\n const elapsed = Date.now() - startTime;\n if (elapsed >= timeout) {\n resolve([]);\n return;\n }\n\n setTimeout(checkForMessages, checkInterval);\n };\n\n checkForMessages();\n });\n }\n\n /**\n * Queue a message for a device\n */\n queueMessage(deviceId: string, message: LingyaoMessage): boolean {\n let queue = this.messageQueue.get(deviceId);\n\n if (!queue) {\n queue = [];\n this.messageQueue.set(deviceId, queue);\n }\n\n // Check queue size limit\n if (queue.length >= this.maxQueueSize) {\n // Remove oldest undelivered message\n const oldestIndex = queue.findIndex((m) => !m.delivered);\n if (oldestIndex >= 0) {\n queue.splice(oldestIndex, 1);\n } else {\n this.runtime.logger.warn(\n `Message queue full for ${deviceId}, dropping message`\n );\n return false;\n }\n }\n\n queue.push({\n message,\n deviceId,\n createdAt: Date.now(),\n delivered: false,\n });\n\n this.runtime.logger.debug(\n `Message queued for ${deviceId}: ${message.id}`\n );\n\n return true;\n }\n\n /**\n * Acknowledge messages\n */\n async acknowledgeMessages(messageIds: string[]): Promise<void> {\n for (const deviceId of this.messageQueue.keys()) {\n const queue = this.messageQueue.get(deviceId);\n if (!queue) continue;\n\n for (const msgId of messageIds) {\n const index = queue.findIndex((m) => m.message.id === msgId);\n if (index >= 0) {\n queue.splice(index, 1);\n }\n }\n\n if (queue.length === 0) {\n this.messageQueue.delete(deviceId);\n }\n }\n\n this.runtime.logger.debug(`Acknowledged ${messageIds.length} messages`);\n }\n\n /**\n * Check if message has been seen (deduplication)\n */\n private isMessageSeen(messageId: string): boolean {\n return this.seenMessages.has(messageId);\n }\n\n /**\n * Mark message as seen\n */\n private markMessageSeen(messageId: string): void {\n this.seenMessages.add(messageId);\n\n // Clean up old entries periodically\n if (this.seenMessages.size > 10000) {\n const entries = Array.from(this.seenMessages);\n for (let i = 0; i < entries.length / 2; i++) {\n this.seenMessages.delete(entries[i]);\n }\n }\n }\n\n /**\n * Get queue size for a device\n */\n getQueueSize(deviceId: string): number {\n const queue = this.messageQueue.get(deviceId);\n return queue?.filter((m) => !m.delivered).length ?? 0;\n }\n\n /**\n * Get total queue size\n */\n getTotalQueueSize(): number {\n let total = 0;\n for (const queue of this.messageQueue.values()) {\n total += queue.filter((m) => !m.delivered).length;\n }\n return total;\n }\n}\n","import type { LingyaoRuntime, HealthStatus } from \"./types.js\";\n\n/**\n * Probe status levels\n */\nexport enum ProbeStatus {\n HEALTHY = \"healthy\",\n DEGRADED = \"degraded\",\n UNHEALTHY = \"unhealthy\",\n}\n\n/**\n * Health check result\n */\nexport interface HealthCheckResult {\n status: ProbeStatus;\n checks: Map<string, CheckResult>;\n timestamp: number;\n}\n\n/**\n * Individual check result\n */\nexport interface CheckResult {\n passed: boolean;\n message?: string;\n duration: number;\n error?: Error;\n}\n\n/**\n * Channel status for reporting\n */\nexport interface ChannelStatus {\n configured: boolean;\n running: boolean;\n lastError?: string;\n activeAccounts: number;\n uptime: number;\n status: ProbeStatus;\n}\n\n/**\n * Probe - Channel health status and monitoring\n */\nexport class Probe {\n private runtime: LingyaoRuntime;\n private startTime: number = Date.now();\n private lastError: string | null = null;\n private lastErrorTime: number | null = null;\n private errorCounts: Map<string, number> = new Map();\n private healthChecks: Map<string, HealthCheckFn> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n\n // Register default health checks\n this.registerHealthCheck(\"uptime\", this.checkUptime);\n this.registerHealthCheck(\"errors\", this.checkErrors);\n }\n\n /**\n * Register a custom health check\n */\n registerHealthCheck(name: string, check: HealthCheckFn): void {\n this.healthChecks.set(name, check);\n }\n\n /**\n * Run all health checks\n */\n async runHealthChecks(): Promise<HealthCheckResult> {\n const checks = new Map<string, CheckResult>();\n let overallStatus = ProbeStatus.HEALTHY;\n\n for (const [name, checkFn] of this.healthChecks.entries()) {\n const start = Date.now();\n\n try {\n const result = await checkFn();\n const duration = Date.now() - start;\n\n checks.set(name, {\n passed: result.passed,\n message: result.message,\n duration,\n });\n\n if (!result.passed && overallStatus === ProbeStatus.HEALTHY) {\n overallStatus = ProbeStatus.DEGRADED;\n }\n } catch (error) {\n const duration = Date.now() - start;\n checks.set(name, {\n passed: false,\n message: \"Health check failed with exception\",\n duration,\n error: error as Error,\n });\n overallStatus = ProbeStatus.UNHEALTHY;\n }\n }\n\n return {\n status: overallStatus,\n checks,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Get channel status for reporting\n */\n getChannelStatus(\n configured: boolean,\n running: boolean,\n activeAccounts: number = 0\n ): ChannelStatus {\n return {\n configured,\n running,\n lastError: this.lastError ?? undefined,\n activeAccounts,\n uptime: Date.now() - this.startTime,\n status: running ? ProbeStatus.HEALTHY : ProbeStatus.UNHEALTHY,\n };\n }\n\n /**\n * Get health status for API endpoint\n */\n async getHealthStatus(\n activeConnections: number = 0,\n queuedMessages: number = 0\n ): Promise<HealthStatus> {\n const healthResult = await this.runHealthChecks();\n\n let status: \"healthy\" | \"degraded\" | \"unhealthy\";\n switch (healthResult.status) {\n case ProbeStatus.HEALTHY:\n status = \"healthy\";\n break;\n case ProbeStatus.DEGRADED:\n status = \"degraded\";\n break;\n case ProbeStatus.UNHEALTHY:\n status = \"unhealthy\";\n break;\n }\n\n return {\n status,\n uptime: Date.now() - this.startTime,\n activeConnections,\n queuedMessages,\n lastError: this.lastError ?? undefined,\n };\n }\n\n /**\n * Record an error\n */\n recordError(error: string, category: string = \"general\"): void {\n this.lastError = error;\n this.lastErrorTime = Date.now();\n\n const count = this.errorCounts.get(category) ?? 0;\n this.errorCounts.set(category, count + 1);\n\n this.runtime.logger.error(`[${category}] ${error}`);\n }\n\n /**\n * Get last error\n */\n getLastError(): string | null {\n // Return error if it occurred within the last 5 minutes\n if (this.lastErrorTime && Date.now() - this.lastErrorTime < 300000) {\n return this.lastError;\n }\n return null;\n }\n\n /**\n * Clear last error\n */\n clearLastError(): void {\n this.lastError = null;\n this.lastErrorTime = null;\n }\n\n /**\n * Get error counts by category\n */\n getErrorCounts(): Record<string, number> {\n return Object.fromEntries(this.errorCounts);\n }\n\n /**\n * Reset error counts\n */\n resetErrorCounts(): void {\n this.errorCounts.clear();\n }\n\n /**\n * Get uptime in milliseconds\n */\n getUptime(): number {\n return Date.now() - this.startTime;\n }\n\n /**\n * Get uptime formatted as human-readable string\n */\n getUptimeString(): string {\n const uptime = this.getUptime();\n const seconds = Math.floor(uptime / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d ${hours % 24}h ${minutes % 60}m`;\n } else if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n } else if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n } else {\n return `${seconds}s`;\n }\n }\n\n /**\n * Health check: uptime\n */\n private checkUptime = async (): Promise<CheckResult> => {\n const uptime = this.getUptime();\n // Consider healthy if uptime > 0\n return {\n passed: uptime > 0,\n message: `Uptime: ${this.getUptimeString()}`,\n duration: 0,\n };\n };\n\n /**\n * Health check: errors\n */\n private checkErrors = async (): Promise<CheckResult> => {\n const recentErrors = this.lastErrorTime && Date.now() - this.lastErrorTime < 60000;\n\n return {\n passed: !recentErrors,\n message: recentErrors\n ? `Recent error: ${this.lastError}`\n : \"No recent errors\",\n duration: 0,\n };\n };\n\n /**\n * Create status adapter for OpenClaw integration\n */\n createStatusAdapter(configured: boolean) {\n return {\n getStatus: async (\n running: boolean,\n activeAccounts: number = 0,\n activeConnections: number = 0,\n queuedMessages: number = 0\n ) => ({\n ...this.getChannelStatus(configured, running, activeAccounts),\n activeConnections,\n queuedMessages,\n }),\n };\n }\n}\n\n/**\n * Health check function signature\n */\nexport type HealthCheckFn = () => Promise<{\n passed: boolean;\n message?: string;\n}>;\n","/**\n * 监控和指标收集模块\n */\n\nimport type { LingyaoRuntime } from './types.js';\n\n/**\n * 指标类型\n */\nexport enum MetricType {\n COUNTER = 'counter',\n GAUGE = 'gauge',\n HISTOGRAM = 'histogram',\n}\n\n/**\n * 指标数据\n */\nexport interface MetricData {\n name: string;\n type: MetricType;\n value: number;\n timestamp: number;\n labels?: Record<string, string>;\n}\n\n/**\n * 指标配置\n */\nexport interface MetricConfig {\n name: string;\n type: MetricType;\n description?: string;\n labels?: string[];\n buckets?: number[];\n}\n\n/**\n * 监控指标管理器\n */\nexport class MetricsManager {\n private metrics: Map<string, MetricData> = new Map();\n private counters: Map<string, number> = new Map();\n private gauges: Map<string, number> = new Map();\n private histograms: Map<string, number[]> = new Map();\n private histogramBuckets: Map<string, number[]> = new Map();\n\n constructor(_runtime: LingyaoRuntime) {\n // 初始化默认指标\n this.initializeDefaultMetrics();\n }\n\n /**\n * 初始化默认指标\n */\n private initializeDefaultMetrics(): void {\n // 连接指标\n this.declareMetric({\n name: 'lingyao_connection_count',\n type: MetricType.GAUGE,\n description: '当前活跃连接数',\n });\n\n this.declareMetric({\n name: 'lingyao_connection_total',\n type: MetricType.COUNTER,\n description: '总连接次数',\n });\n\n this.declareMetric({\n name: 'lingyao_disconnection_total',\n type: MetricType.COUNTER,\n description: '总断开连接次数',\n });\n\n // 消息指标\n this.declareMetric({\n name: 'lingyao_message_total',\n type: MetricType.COUNTER,\n description: '总消息数',\n labels: ['direction', 'type'],\n });\n\n this.declareMetric({\n name: 'lingyao_message_failed_total',\n type: MetricType.COUNTER,\n description: '失败消息总数',\n labels: ['direction', 'reason'],\n });\n\n // 延迟指标\n this.declareMetric({\n name: 'lingyao_message_latency',\n type: MetricType.HISTOGRAM,\n description: '消息处理延迟',\n buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],\n });\n\n // 错误指标\n this.declareMetric({\n name: 'lingyao_error_total',\n type: MetricType.COUNTER,\n description: '错误总数',\n labels: ['type', 'severity'],\n });\n\n // 心跳指标\n this.declareMetric({\n name: 'lingyao_heartbeat_total',\n type: MetricType.COUNTER,\n description: '心跳总数',\n });\n\n this.declareMetric({\n name: 'lingyao_heartbeat_missed_total',\n type: MetricType.COUNTER,\n description: '心跳丢失总数',\n });\n\n // 重连指标\n this.declareMetric({\n name: 'lingyao_reconnect_total',\n type: MetricType.COUNTER,\n description: '重连次数',\n });\n\n // 队列指标\n this.declareMetric({\n name: 'lingyao_queue_size',\n type: MetricType.GAUGE,\n description: '当前队列大小',\n });\n }\n\n /**\n * 声明指标\n */\n declareMetric(config: MetricConfig): void {\n if (config.type === MetricType.HISTOGRAM && config.buckets) {\n this.histogramBuckets.set(config.name, config.buckets);\n }\n }\n\n /**\n * 计数器增加\n */\n incrementCounter(name: string, value: number = 1, labels?: Record<string, string>): void {\n const current = this.counters.get(name) || 0;\n this.counters.set(name, current + value);\n\n this.recordMetric({\n name,\n type: MetricType.COUNTER,\n value: current + value,\n timestamp: Date.now(),\n labels,\n });\n }\n\n /**\n * 设置仪表盘值\n */\n setGauge(name: string, value: number, labels?: Record<string, string>): void {\n this.gauges.set(name, value);\n\n this.recordMetric({\n name,\n type: MetricType.GAUGE,\n value,\n timestamp: Date.now(),\n labels,\n });\n }\n\n /**\n * 记录直方图值\n */\n recordHistogram(name: string, value: number, labels?: Record<string, string>): void {\n let values = this.histograms.get(name);\n if (!values) {\n values = [];\n this.histograms.set(name, values);\n }\n values.push(value);\n\n this.recordMetric({\n name,\n type: MetricType.HISTOGRAM,\n value,\n timestamp: Date.now(),\n labels,\n });\n }\n\n /**\n * 记录指标\n */\n private recordMetric(data: MetricData): void {\n this.metrics.set(`${data.name}_${Date.now()}`, data);\n\n // 限制指标历史数量\n if (this.metrics.size > 10000) {\n const entries = Array.from(this.metrics.entries());\n entries.sort((a, b) => a[1].timestamp - b[1].timestamp);\n\n // 删除最旧的 10%\n for (let i = 0; i < 1000; i++) {\n this.metrics.delete(entries[i][0]);\n }\n }\n }\n\n /**\n * 获取所有指标\n */\n getMetrics(): MetricData[] {\n return Array.from(this.metrics.values());\n }\n\n /**\n * 获取特定指标的当前值\n */\n getMetricValue(name: string): number | undefined {\n if (this.counters.has(name)) {\n return this.counters.get(name);\n }\n if (this.gauges.has(name)) {\n return this.gauges.get(name);\n }\n return undefined;\n }\n\n /**\n * 获取直方图统计数据\n */\n getHistogramStats(name: string): {\n count: number;\n min: number;\n max: number;\n avg: number;\n p50: number;\n p95: number;\n p99: number;\n } | null {\n const values = this.histograms.get(name);\n if (!values || values.length === 0) {\n return null;\n }\n\n const sorted = [...values].sort((a, b) => a - b);\n const count = sorted.length;\n const sum = sorted.reduce((a, b) => a + b, 0);\n\n return {\n count,\n min: sorted[0],\n max: sorted[count - 1],\n avg: sum / count,\n p50: sorted[Math.floor(count * 0.5)],\n p95: sorted[Math.floor(count * 0.95)],\n p99: sorted[Math.floor(count * 0.99)],\n };\n }\n\n /**\n * 重置所有指标\n */\n reset(): void {\n this.metrics.clear();\n this.counters.clear();\n this.gauges.clear();\n this.histograms.clear();\n }\n\n /**\n * 生成 Prometheus 格式的指标导出\n */\n exportPrometheus(): string {\n const lines: string[] = [];\n\n // 导出计数器和仪表盘\n for (const [name, value] of [...this.counters, ...this.gauges]) {\n lines.push(`${name} ${value}`);\n }\n\n // 导出直方图\n for (const [name] of this.histograms) {\n const stats = this.getHistogramStats(name);\n if (stats) {\n lines.push(`${name}_count ${stats.count}`);\n lines.push(`${name}_sum ${stats.avg * stats.count}`);\n lines.push(`${name}_bucket{le=\\\"+Inf\\\"} ${stats.count}`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n\n/**\n * 监控事件\n */\nexport enum MonitoringEvent {\n // 连接事件\n CONNECTION_OPEN = 'connection_open',\n CONNECTION_CLOSE = 'connection_close',\n CONNECTION_ERROR = 'connection_error',\n RECONNECT = 'reconnect',\n\n // 消息事件\n MESSAGE_RECEIVED = 'message_received',\n MESSAGE_SENT = 'message_sent',\n MESSAGE_DELIVERED = 'message_delivered',\n MESSAGE_FAILED = 'message_failed',\n\n // 心跳事件\n HEARTBEAT_SENT = 'heartbeat_sent',\n HEARTBEAT_RECEIVED = 'heartbeat_received',\n HEARTBEAT_MISSED = 'heartbeat_missed',\n\n // 错误事件\n ERROR_OCCURRED = 'error_occurred',\n}\n\n/**\n * 监控事件数据\n */\nexport interface MonitoringEventData {\n event: MonitoringEvent;\n timestamp: number;\n data: Record<string, unknown>;\n}\n\n/**\n * 监控器\n */\nexport class Monitor {\n private runtime: LingyaoRuntime;\n private metrics: MetricsManager;\n private eventHandlers: Map<MonitoringEvent, ((data: MonitoringEventData) => void)[]> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n this.metrics = new MetricsManager(runtime);\n }\n\n /**\n * 记录事件\n */\n recordEvent(event: MonitoringEvent, data: Record<string, unknown> = {}): void {\n const eventData: MonitoringEventData = {\n event,\n timestamp: Date.now(),\n data,\n };\n\n // 更新指标\n this.updateMetricsForEvent(event, data);\n\n // 触发事件处理器\n const handlers = this.eventHandlers.get(event) || [];\n handlers.forEach(handler => {\n try {\n handler(eventData);\n } catch (error) {\n this.runtime.logger.error('Error in monitoring event handler', error);\n }\n });\n\n // 记录日志\n this.runtime.logger.debug(`Monitoring event: ${event}`, data);\n }\n\n /**\n * 为事件更新指标\n */\n private updateMetricsForEvent(event: MonitoringEvent, data: Record<string, unknown>): void {\n switch (event) {\n case MonitoringEvent.CONNECTION_OPEN:\n this.metrics.incrementCounter('lingyao_connection_total');\n this.metrics.setGauge('lingyao_connection_count', (data.activeConnections as number) || 1);\n break;\n\n case MonitoringEvent.CONNECTION_CLOSE:\n this.metrics.incrementCounter('lingyao_disconnection_total');\n this.metrics.setGauge('lingyao_connection_count', (data.activeConnections as number) || 0);\n break;\n\n case MonitoringEvent.RECONNECT:\n this.metrics.incrementCounter('lingyao_reconnect_total');\n break;\n\n case MonitoringEvent.MESSAGE_RECEIVED:\n this.metrics.incrementCounter('lingyao_message_total', 1, {\n direction: 'in',\n type: (data.messageType as string) || 'unknown',\n });\n break;\n\n case MonitoringEvent.MESSAGE_SENT:\n this.metrics.incrementCounter('lingyao_message_total', 1, {\n direction: 'out',\n type: (data.messageType as string) || 'unknown',\n });\n break;\n\n case MonitoringEvent.MESSAGE_DELIVERED:\n // 记录延迟\n if (data.latency) {\n this.metrics.recordHistogram('lingyao_message_latency', data.latency as number);\n }\n break;\n\n case MonitoringEvent.MESSAGE_FAILED:\n this.metrics.incrementCounter('lingyao_message_failed_total', 1, {\n direction: (data.direction as string) || 'unknown',\n reason: (data.reason as string) || 'unknown',\n });\n break;\n\n case MonitoringEvent.HEARTBEAT_SENT:\n this.metrics.incrementCounter('lingyao_heartbeat_total');\n break;\n\n case MonitoringEvent.HEARTBEAT_MISSED:\n this.metrics.incrementCounter('lingyao_heartbeat_missed_total');\n break;\n\n case MonitoringEvent.ERROR_OCCURRED:\n this.metrics.incrementCounter('lingyao_error_total', 1, {\n type: (data.errorType as string) || 'unknown',\n severity: (data.severity as string) || 'medium',\n });\n break;\n }\n }\n\n /**\n * 注册事件处理器\n */\n on(event: MonitoringEvent, handler: (data: MonitoringEventData) => void): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, []);\n }\n this.eventHandlers.get(event)!.push(handler);\n }\n\n /**\n * 移除事件处理器\n */\n off(event: MonitoringEvent, handler: (data: MonitoringEventData) => void): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n }\n }\n\n /**\n * 获取指标管理器\n */\n getMetrics(): MetricsManager {\n return this.metrics;\n }\n\n /**\n * 获取摘要报告\n */\n getSummary(): {\n uptime: number;\n connections: number;\n messages: {\n sent: number;\n received: number;\n failed: number;\n };\n errors: number;\n heartbeats: {\n sent: number;\n missed: number;\n };\n } {\n return {\n uptime: Date.now() - (this.runtime as any).startTime,\n connections: this.metrics.getMetricValue('lingyao_connection_total') || 0,\n messages: {\n sent: this.metrics.getMetricValue('lingyao_message_total') || 0,\n received: this.metrics.getMetricValue('lingyao_message_total') || 0,\n failed: this.metrics.getMetricValue('lingyao_message_failed_total') || 0,\n },\n errors: this.metrics.getMetricValue('lingyao_error_total') || 0,\n heartbeats: {\n sent: this.metrics.getMetricValue('lingyao_heartbeat_total') || 0,\n missed: this.metrics.getMetricValue('lingyao_heartbeat_missed_total') || 0,\n },\n };\n }\n}\n","/**\n * 错误处理模块\n */\n\nimport type { LingyaoRuntime } from './types.js';\n\n/**\n * 错误严重级别\n */\nexport enum ErrorSeverity {\n LOW = 'low',\n MEDIUM = 'medium',\n HIGH = 'high',\n CRITICAL = 'critical',\n}\n\n/**\n * Lingyao 错误基类\n */\nexport class LingyaoError extends Error {\n public readonly code: string;\n public readonly severity: ErrorSeverity;\n public readonly timestamp: number;\n public readonly context?: Record<string, unknown>;\n public readonly cause?: Error;\n\n constructor(\n message: string,\n code: string,\n severity: ErrorSeverity = ErrorSeverity.MEDIUM,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.severity = severity;\n this.timestamp = Date.now();\n this.context = context;\n this.cause = cause;\n\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * 转换为 JSON 可序列化格式\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n severity: this.severity,\n timestamp: this.timestamp,\n context: this.context,\n cause: this.cause?.message,\n stack: this.stack,\n };\n }\n}\n\n/**\n * 连接错误\n */\nexport class ConnectionError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'CONNECTION_ERROR', ErrorSeverity.HIGH, context, cause);\n }\n}\n\n/**\n * 认证错误\n */\nexport class AuthenticationError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'AUTHENTICATION_ERROR', ErrorSeverity.HIGH, context, cause);\n }\n}\n\n/**\n * 消息错误\n */\nexport class MessageError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'MESSAGE_ERROR', ErrorSeverity.MEDIUM, context, cause);\n }\n}\n\n/**\n * 验证错误\n */\nexport class ValidationError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'VALIDATION_ERROR', ErrorSeverity.LOW, context, cause);\n }\n}\n\n/**\n * 配置错误\n */\nexport class ConfigurationError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'CONFIGURATION_ERROR', ErrorSeverity.HIGH, context, cause);\n }\n}\n\n/**\n * 网络错误\n */\nexport class NetworkError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'NETWORK_ERROR', ErrorSeverity.MEDIUM, context, cause);\n }\n}\n\n/**\n * 超时错误\n */\nexport class TimeoutError extends LingyaoError {\n constructor(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(message, 'TIMEOUT_ERROR', ErrorSeverity.MEDIUM, context, cause);\n }\n}\n\n/**\n * 设备离线错误\n */\nexport class DeviceOfflineError extends LingyaoError {\n public readonly deviceId: string;\n\n constructor(\n deviceId: string,\n context?: Record<string, unknown>,\n cause?: Error\n ) {\n super(\n `Device offline: ${deviceId}`,\n 'DEVICE_OFFLINE_ERROR',\n ErrorSeverity.MEDIUM,\n context,\n cause\n );\n this.deviceId = deviceId;\n }\n}\n\n/**\n * 重试错误\n */\nexport class RetryableError extends LingyaoError {\n public readonly retryable: boolean;\n public readonly retryAfter?: number;\n public readonly maxRetries?: number;\n\n constructor(\n message: string,\n context?: Record<string, unknown> & {\n retryAfter?: number;\n maxRetries?: number;\n },\n cause?: Error\n ) {\n super(message, 'RETRYABLE_ERROR', ErrorSeverity.LOW, context, cause);\n this.retryable = true;\n this.retryAfter = context?.retryAfter;\n this.maxRetries = context?.maxRetries;\n }\n}\n\n/**\n * 错误处理器\n */\nexport class ErrorHandler {\n private runtime: LingyaoRuntime;\n private errorCounts: Map<string, number> = new Map();\n private lastErrors: Map<string, { error: LingyaoError; timestamp: number }> = new Map();\n private errorThresholds: Map<string, { count: number; window: number }> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n\n // 设置默认错误阈值\n this.setErrorThreshold('CONNECTION_ERROR', { count: 5, window: 60000 });\n this.setErrorThreshold('AUTHENTICATION_ERROR', { count: 3, window: 60000 });\n this.setErrorThreshold('NETWORK_ERROR', { count: 10, window: 60000 });\n }\n\n /**\n * 处理错误\n */\n handleError(error: Error | LingyaoError): void {\n const lingyaoError = error instanceof LingyaoError\n ? error\n : new LingyaoError(error.message, 'UNKNOWN_ERROR', ErrorSeverity.MEDIUM, {}, error);\n\n // 记录错误\n this.recordError(lingyaoError);\n\n // 根据严重级别决定日志级别\n switch (lingyaoError.severity) {\n case ErrorSeverity.LOW:\n this.runtime.logger.debug(lingyaoError.message, lingyaoError.toJSON());\n break;\n case ErrorSeverity.MEDIUM:\n this.runtime.logger.warn(lingyaoError.message, lingyaoError.toJSON());\n break;\n case ErrorSeverity.HIGH:\n case ErrorSeverity.CRITICAL:\n this.runtime.logger.error(lingyaoError.message, lingyaoError.toJSON());\n break;\n }\n\n // 检查是否超过阈值\n this.checkThresholds(lingyaoError);\n }\n\n /**\n * 记录错误\n */\n private recordError(error: LingyaoError): void {\n const key = error.code;\n const count = (this.errorCounts.get(key) || 0) + 1;\n this.errorCounts.set(key, count);\n\n this.lastErrors.set(key, {\n error,\n timestamp: Date.now(),\n });\n\n // 清理旧的错误记录(1小时后)\n setTimeout(() => {\n const lastError = this.lastErrors.get(key);\n if (lastError && lastError.timestamp === error.timestamp) {\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) - 1);\n }\n }, 3600000);\n }\n\n /**\n * 检查错误阈值\n */\n private checkThresholds(error: LingyaoError): void {\n const threshold = this.errorThresholds.get(error.code);\n if (!threshold) {\n return;\n }\n\n const count = this.errorCounts.get(error.code) || 0;\n if (count >= threshold.count) {\n this.runtime.logger.error(\n `Error threshold exceeded for ${error.code}`,\n {\n code: error.code,\n count,\n threshold: threshold.count,\n window: threshold.window,\n }\n );\n\n // 触发警报\n this.triggerAlert(error, count);\n }\n }\n\n /**\n * 触发警报\n */\n private triggerAlert(error: LingyaoError, count: number): void {\n // 这里可以集成告警系统\n this.runtime.logger.error('ALERT', {\n type: 'error_threshold_exceeded',\n error: error.toJSON(),\n count,\n });\n }\n\n /**\n * 设置错误阈值\n */\n setErrorThreshold(code: string, threshold: { count: number; window: number }): void {\n this.errorThresholds.set(code, threshold);\n }\n\n /**\n * 获取错误统计\n */\n getErrorStats(): {\n byCode: Record<string, number>;\n total: number;\n recent: Array<{ code: string; error: LingyaoError; timestamp: number }>;\n } {\n const byCode: Record<string, number> = {};\n let total = 0;\n\n for (const [code, count] of this.errorCounts) {\n byCode[code] = count;\n total += count;\n }\n\n const recent = Array.from(this.lastErrors.entries())\n .map(([code, { error, timestamp }]) => ({ code, error, timestamp }))\n .sort((a, b) => b.timestamp - a.timestamp)\n .slice(0, 10);\n\n return { byCode, total, recent };\n }\n\n /**\n * 重置错误计数\n */\n resetErrorCounts(code?: string): void {\n if (code) {\n this.errorCounts.delete(code);\n this.lastErrors.delete(code);\n } else {\n this.errorCounts.clear();\n this.lastErrors.clear();\n }\n }\n\n /**\n * 包装异步函数以自动处理错误\n */\n async wrapAsync<T>(\n fn: () => Promise<T>,\n context?: {\n operation?: string;\n fallback?: T;\n retryable?: boolean;\n }\n ): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n const operation = context?.operation || 'unknown';\n\n if (error instanceof LingyaoError) {\n this.handleError(error);\n } else if (context?.retryable) {\n const retryableError = new RetryableError(\n `Operation \"${operation}\" failed`,\n { operation },\n error as Error\n );\n this.handleError(retryableError);\n } else {\n this.handleError(new LingyaoError(\n `Operation \"${operation}\" failed: ${(error as Error).message}`,\n 'OPERATION_FAILED',\n ErrorSeverity.MEDIUM,\n { operation },\n error as Error\n ));\n }\n\n if (context?.fallback !== undefined) {\n return context.fallback;\n }\n\n throw error;\n }\n }\n\n /**\n * 创建带有错误处理的重试逻辑\n */\n async retry<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n retryDelay?: number;\n backoff?: boolean;\n onRetry?: (error: Error, attempt: number) => void;\n } = {}\n ): Promise<T> {\n const {\n maxRetries = 3,\n retryDelay = 1000,\n backoff = true,\n onRetry,\n } = options;\n\n let lastError: Error | null = null;\n let delay = retryDelay;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt === maxRetries) {\n break;\n }\n\n if (onRetry) {\n onRetry(lastError, attempt + 1);\n }\n\n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, delay));\n\n if (backoff) {\n delay *= 2;\n }\n }\n }\n\n throw new RetryableError(\n `Operation failed after ${maxRetries + 1} attempts`,\n { maxRetries },\n lastError ?? new Error(\"Unknown retry failure\")\n );\n }\n\n /**\n * 判断错误是否可重试\n */\n isRetryable(error: Error): boolean {\n if (error instanceof RetryableError) {\n return error.retryable;\n }\n\n if (error instanceof LingyaoError) {\n switch (error.code) {\n case 'NETWORK_ERROR':\n case 'TIMEOUT_ERROR':\n case 'CONNECTION_ERROR':\n return true;\n default:\n return false;\n }\n }\n\n return false;\n }\n\n /**\n * 判断错误是否需要降级处理\n */\n shouldDegrade(error: Error): boolean {\n if (error instanceof LingyaoError) {\n return error.severity === ErrorSeverity.HIGH ||\n error.severity === ErrorSeverity.CRITICAL;\n }\n\n return false;\n }\n\n /**\n * 创建降级响应\n */\n createDegradedResponse<T>(fallback: T, error?: Error): {\n success: false;\n degraded: true;\n fallback: T;\n error?: Error;\n } {\n return {\n success: false,\n degraded: true,\n fallback,\n error,\n };\n }\n}\n\n/**\n * 错误恢复策略\n */\nexport enum RecoveryStrategy {\n RETRY = 'retry',\n FALLBACK = 'fallback',\n IGNORE = 'ignore',\n ESCALATE = 'escalate',\n}\n\n/**\n * 错误恢复配置\n */\nexport interface ErrorRecoveryConfig {\n strategy: RecoveryStrategy;\n maxRetries?: number;\n fallbackValue?: any;\n ignoreThreshold?: number;\n}\n\n/**\n * 错误恢复管理器\n */\nexport class ErrorRecoveryManager {\n private recoveryConfigs: Map<string, ErrorRecoveryConfig> = new Map();\n\n /**\n * 设置恢复配置\n */\n setRecoveryConfig(errorCode: string, config: ErrorRecoveryConfig): void {\n this.recoveryConfigs.set(errorCode, config);\n }\n\n /**\n * 获取恢复策略\n */\n getRecoveryStrategy(error: Error): ErrorRecoveryConfig | null {\n if (error instanceof LingyaoError) {\n return this.recoveryConfigs.get(error.code) || null;\n }\n\n return null;\n }\n\n /**\n * 应用恢复策略\n */\n async applyRecovery(\n error: Error,\n originalFn: () => Promise<any>\n ): Promise<any> {\n const config = this.getRecoveryStrategy(error);\n\n if (!config) {\n throw error;\n }\n\n switch (config.strategy) {\n case RecoveryStrategy.RETRY:\n const errorHandler = new ErrorHandler({} as any);\n return await errorHandler.retry(originalFn, {\n maxRetries: config.maxRetries || 3,\n });\n\n case RecoveryStrategy.FALLBACK:\n if (config.fallbackValue !== undefined) {\n return config.fallbackValue;\n }\n throw error;\n\n case RecoveryStrategy.IGNORE:\n return null;\n\n case RecoveryStrategy.ESCALATE:\n throw new LingyaoError(\n `Error escalation: ${error.message}`,\n 'ESCALATED_ERROR',\n ErrorSeverity.CRITICAL,\n { originalError: error }\n );\n\n default:\n throw error;\n }\n }\n}\n","/**\n * 灵爻频道插件 - 服务器中转模式\n *\n * 架构:\n * 1. OpenClaw 作为 WebSocket 客户端,主动连接到 lingyao.live 服务器\n * 2. 鸿蒙 App 也作为 WebSocket 客户端,主动连接到 lingyao.live 服务器\n * 3. lingyao.live 服务器作为消息中转站\n * 4. 双方都不需要公网 IP,也不需要开放端口\n */\n\nimport { hostname } from 'node:os';\nimport {\n LINGYAO_SERVER_URL,\n type LingyaoRuntime,\n LingyaoConfig,\n HealthStatus,\n NotifyPayload,\n} from \"./types.js\";\nimport { AccountManager } from \"./accounts.js\";\nimport { TokenManager } from \"./token.js\";\nimport { MessageProcessor, AgentMessage } from \"./bot.js\";\nimport { Probe } from \"./probe.js\";\nimport { setRuntime } from \"./runtime.js\";\nimport { ServerHttpClient } from \"./server-client.js\";\nimport { LingyaoWSClient } from \"./websocket-client.js\";\nimport { Monitor, MonitoringEvent } from \"./metrics.js\";\nimport { ErrorHandler, ConnectionError } from \"./errors.js\";\n\n/**\n * 灵爻频道插件 - 服务器中转模式\n */\nexport class LingyaoChannel {\n private runtime: LingyaoRuntime;\n private config: LingyaoConfig;\n private accountManager: AccountManager;\n private tokenManager: TokenManager;\n private serverClient: ServerHttpClient | null = null;\n private wsClient: LingyaoWSClient | null = null;\n private processor: MessageProcessor | null = null;\n private probe: Probe;\n private monitor: Monitor;\n private errorHandler: ErrorHandler;\n private startTime: number = 0;\n private gatewayId: string;\n private isRunning: boolean = false;\n private messageHandler: ((message: AgentMessage) => void | Promise<void>) | null = null;\n\n constructor(runtime: LingyaoRuntime, config: LingyaoConfig) {\n this.runtime = runtime;\n this.config = config;\n this.startTime = Date.now();\n\n // 生成 Gateway ID\n this.gatewayId = this.generateGatewayId();\n\n // Set global runtime\n setRuntime(runtime);\n\n // Initialize components\n this.accountManager = new AccountManager(runtime);\n this.tokenManager = new TokenManager(runtime);\n this.probe = new Probe(runtime);\n this.monitor = new Monitor(runtime);\n this.errorHandler = new ErrorHandler(runtime);\n\n // Initialize server client\n this.serverClient = new ServerHttpClient(runtime, this.gatewayId, {\n baseURL: LINGYAO_SERVER_URL,\n apiBase: '/v1',\n });\n }\n\n /**\n * 初始化频道\n */\n async initialize(): Promise<void> {\n this.runtime.logger.info(\"Initializing Lingyao Channel (Server Relay Mode)...\");\n\n // Initialize account manager\n await this.accountManager.initialize();\n\n // Initialize message processor\n this.processor = new MessageProcessor(\n this.runtime,\n this.accountManager\n );\n await this.processor.initialize();\n\n if (this.messageHandler) {\n this.processor.setMessageHandler(this.messageHandler);\n }\n\n this.runtime.logger.info(\"Lingyao Channel initialized successfully\");\n }\n\n /**\n * 启动频道\n */\n async start(): Promise<void> {\n if (this.isRunning) {\n this.runtime.logger.warn(\"Lingyao Channel is already running\");\n return;\n }\n\n this.runtime.logger.info(\"Starting Lingyao Channel...\");\n\n try {\n // 1. 向服务器注册\n await this.registerToServer();\n\n // 2. 创建 WebSocket 客户端\n this.wsClient = new LingyaoWSClient(this.runtime, {\n url: `${LINGYAO_SERVER_URL}/v1/gateway/ws`,\n gatewayId: this.gatewayId,\n token: this.serverClient?.getGatewayToken() ?? undefined,\n reconnectInterval: 5000,\n heartbeatInterval: 30000,\n messageHandler: this.handleAppMessage.bind(this),\n eventHandler: this.handleClientEvent.bind(this),\n });\n\n // 3. 连接到服务器\n await this.wsClient.connect();\n\n this.isRunning = true;\n this.runtime.logger.info(\"Lingyao Channel started successfully\");\n } catch (error) {\n this.runtime.logger.error(\"Failed to start Lingyao Channel\", error);\n throw error;\n }\n }\n\n /**\n * 向 lingyao 服务器注册 Gateway\n */\n private async registerToServer(): Promise<void> {\n if (!this.serverClient) {\n throw new Error('Server client not available');\n }\n\n try {\n // 尝试从存储恢复会话\n const restored = await this.serverClient.restoreFromStorage();\n\n if (restored) {\n this.runtime.logger.info('Previous server registration restored');\n return;\n }\n\n this.runtime.logger.info('Registering to lingyao server...', {\n gatewayId: this.gatewayId,\n });\n\n // 向服务器注册\n const registerResponse = await this.serverClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n\n this.runtime.logger.info('Registered to lingyao server successfully', {\n expiresAt: new Date(registerResponse.expiresAt).toISOString(),\n heartbeatInterval: registerResponse.serverConfig.heartbeatInterval,\n });\n } catch (error) {\n const err = error as Error;\n this.runtime.logger.error('Failed to register to server', err);\n\n // 注册失败不影响启动,WebSocket 客户端会自动重连\n this.runtime.logger.info('Will attempt WebSocket connection anyway');\n }\n }\n\n /**\n * 处理来自鸿蒙 App 的消息\n */\n private async handleAppMessage(message: any): Promise<void> {\n try {\n const appMessage = message.payload;\n const deviceId = appMessage.deviceId;\n const msg = appMessage.message;\n\n this.runtime.logger.info('Received message from App', {\n deviceId,\n messageType: msg.type,\n messageId: msg.id,\n });\n\n // 记录接收消息事件\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_RECEIVED, {\n deviceId,\n messageType: msg.type,\n messageId: msg.id,\n });\n\n // 处理不同类型的消息\n switch (msg.type) {\n case 'sync_diary':\n case 'sync_memory':\n await this.handleSyncMessage(deviceId, msg);\n break;\n case 'heartbeat':\n // 心跳消息,不需要特殊处理\n this.monitor.recordEvent(MonitoringEvent.HEARTBEAT_RECEIVED, {\n deviceId,\n });\n break;\n default:\n this.runtime.logger.warn('Unknown message type', { type: msg.type });\n }\n } catch (error) {\n this.runtime.logger.error('Error handling App message', error);\n this.monitor.recordEvent(MonitoringEvent.ERROR_OCCURRED, {\n errorType: 'message_handling',\n severity: 'medium',\n });\n }\n }\n\n /**\n * 处理同步消息(日记、记忆等)\n */\n private async handleSyncMessage(\n deviceId: string,\n message: {\n id: string;\n type: \"sync_diary\" | \"sync_memory\";\n timestamp: number;\n content: string;\n metadata?: Record<string, unknown>;\n }\n ): Promise<void> {\n if (!this.processor) {\n this.runtime.logger.warn('Message processor not initialized');\n return;\n }\n\n // 转换为 Agent 消息格式\n const agentMessage: AgentMessage = {\n id: message.id,\n type: this.mapMessageType(message.type),\n from: deviceId,\n deviceId,\n content: message.content,\n metadata: message.metadata || {},\n timestamp: message.timestamp,\n };\n\n await this.processor.deliverToAgent(agentMessage);\n }\n\n /**\n * 映射消息类型\n */\n private mapMessageType(appType: \"sync_diary\" | \"sync_memory\"): AgentMessage[\"type\"] {\n return appType === \"sync_diary\" ? \"diary\" : \"memory\";\n }\n\n /**\n * 处理 WebSocket 客户端事件\n */\n private handleClientEvent(event: any): void {\n this.runtime.logger.debug('WebSocket client event', { type: event.type });\n\n switch (event.type) {\n case 'connected':\n this.runtime.logger.info('Connected to Lingyao server', {\n connectionId: event.connectionId,\n });\n this.monitor.recordEvent(MonitoringEvent.CONNECTION_OPEN, {\n connectionId: event.connectionId,\n });\n break;\n case 'disconnected':\n this.runtime.logger.warn('Disconnected from Lingyao server', {\n code: event.code,\n reason: event.reason,\n });\n this.monitor.recordEvent(MonitoringEvent.CONNECTION_CLOSE, {\n code: event.code,\n reason: event.reason,\n });\n break;\n case 'error':\n this.runtime.logger.error('WebSocket client error', event.error);\n this.probe.recordError(event.error.message, \"websocket\");\n this.monitor.recordEvent(MonitoringEvent.CONNECTION_ERROR, {\n error: event.error,\n });\n this.errorHandler.handleError(\n new ConnectionError(\n `WebSocket error: ${event.error.message}`,\n { event: event.type },\n event.error\n )\n );\n break;\n }\n }\n\n /**\n * 停止频道\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n this.runtime.logger.info(\"Stopping Lingyao Channel...\");\n\n this.isRunning = false;\n\n // 断开 WebSocket 连接\n if (this.wsClient) {\n this.wsClient.disconnect();\n this.wsClient = null;\n }\n\n // 停止服务器心跳\n if (this.serverClient) {\n this.serverClient.stopHeartbeat();\n }\n\n this.runtime.logger.info(\"Lingyao Channel stopped\");\n }\n\n /**\n * 发送通知到设备\n */\n async sendNotification(\n deviceId: string,\n notification: NotifyPayload\n ): Promise<{ success: boolean; error?: string; queued?: boolean }> {\n if (!this.wsClient || !this.wsClient.isConnected()) {\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_FAILED, {\n deviceId,\n reason: 'not_connected',\n direction: 'out',\n });\n return {\n success: false,\n error: \"Not connected to Lingyao server\",\n };\n }\n\n try {\n this.wsClient.sendNotification(deviceId, notification);\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_SENT, {\n deviceId,\n messageType: 'notification',\n });\n return { success: true };\n } catch (error) {\n const err = error as Error;\n this.monitor.recordEvent(MonitoringEvent.MESSAGE_FAILED, {\n deviceId,\n reason: err.message,\n direction: 'out',\n });\n return {\n success: false,\n error: err.message,\n };\n }\n }\n\n /**\n * 发送文本到设备\n */\n async sendText(\n deviceId: string,\n text: string\n ): Promise<{ success: boolean; error?: string; queued?: boolean }> {\n return await this.sendNotification(deviceId, {\n title: 'OpenClaw',\n body: text,\n });\n }\n\n /**\n * 获取健康状态\n */\n async getHealthStatus(): Promise<HealthStatus> {\n const activeConnections = this.wsClient?.isConnected() ? 1 : 0;\n const queuedMessages = this.processor?.getTotalQueueSize() ?? 0;\n const lastError = this.probe.getLastError() ?? undefined;\n\n let status: \"healthy\" | \"degraded\" | \"unhealthy\" = \"healthy\";\n\n if (lastError) {\n status = \"degraded\";\n }\n\n if (!this.config.enabled) {\n status = \"unhealthy\";\n }\n\n if (!this.wsClient?.isConnected()) {\n status = \"degraded\";\n }\n\n const uptime = Date.now() - this.startTime;\n\n return {\n status,\n uptime,\n activeConnections,\n queuedMessages,\n lastError,\n };\n }\n\n /**\n * 获取配置\n */\n getConfig(): LingyaoConfig {\n return { ...this.config };\n }\n\n /**\n * 更新配置\n */\n async updateConfig(updates: Partial<LingyaoConfig>): Promise<void> {\n this.config = { ...this.config, ...updates };\n this.runtime.logger.info(\"Configuration updated\", updates);\n }\n\n /**\n * 获取账号管理器\n */\n getAccountManager(): AccountManager {\n return this.accountManager;\n }\n\n /**\n * 获取 Token 管理器\n */\n getTokenManager(): TokenManager {\n return this.tokenManager;\n }\n\n /**\n * 获取服务器客户端\n */\n getServerClient(): ServerHttpClient | null {\n return this.serverClient;\n }\n\n /**\n /**\n * 获取 WebSocket 客户端\n */\n getWSClient(): LingyaoWSClient | null {\n return this.wsClient;\n }\n\n /**\n * 获取消息处理器\n */\n getMessageProcessor(): MessageProcessor | null {\n return this.processor;\n }\n\n /**\n * 设置消息处理器\n */\n setMessageHandler(handler: (message: AgentMessage) => void | Promise<void>): void {\n this.messageHandler = handler;\n if (this.processor) {\n this.processor.setMessageHandler(handler);\n }\n this.runtime.logger.info(\"Message handler registered for Agent integration\");\n }\n\n /**\n * 获取监控器\n */\n getMonitor(): Monitor {\n return this.monitor;\n }\n\n /**\n * 获取错误处理器\n */\n getErrorHandler(): ErrorHandler {\n return this.errorHandler;\n }\n\n /**\n * 获取监控摘要\n */\n getMonitoringSummary() {\n return this.monitor.getSummary();\n }\n\n /**\n * 获取错误统计\n */\n getErrorStats() {\n return this.errorHandler.getErrorStats();\n }\n\n /**\n * 生成 Gateway ID\n */\n private generateGatewayId(): string {\n const hostname = this.getRuntimeHostname();\n const randomSuffix = Math.random().toString(36).substring(2, 8);\n return `gw_openclaw_${hostname}_${randomSuffix}`;\n }\n\n /**\n * 获取运行时主机名\n */\n private getRuntimeHostname(): string {\n try {\n return hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();\n } catch {\n return 'unknown';\n }\n }\n}\n","import { randomBytes, createHash, timingSafeEqual } from \"crypto\";\nimport type { DeviceToken, DeviceInfo, LingyaoRuntime } from \"./types.js\";\n\n/**\n * Token management utilities\n */\nexport class TokenManager {\n constructor(_runtime: LingyaoRuntime) {\n void _runtime;\n }\n\n /**\n * Generate a new device token\n */\n generateDeviceToken(\n pairingId: string,\n deviceInfo: DeviceInfo,\n expiryDays: number = 30\n ): DeviceToken {\n const deviceId = this.generateDeviceId();\n const secret = this.generateSecret();\n const token = this.generateTokenString(deviceId, secret);\n\n const expiresAt = Date.now() + expiryDays * 24 * 60 * 60 * 1000;\n\n return {\n deviceId,\n pairingId,\n token,\n secret,\n expiresAt,\n deviceInfo,\n };\n }\n\n /**\n * Validate a device token\n */\n validateToken(token: string, storedSecret: string): boolean {\n try {\n // In production, use proper JWT validation\n // For now, simple token validation\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return false;\n }\n\n const [headerB64, payloadB64, signatureB64] = parts;\n\n // Verify signature\n const expectedSignature = this.sign(`${headerB64}.${payloadB64}`, storedSecret);\n const providedSignature = Buffer.from(signatureB64, \"base64url\").toString(\"utf-8\");\n\n // Use timing-safe comparison (signature segments are UTF-8 of base64 digest)\n return timingSafeEqual(\n Buffer.from(expectedSignature, \"utf-8\"),\n Buffer.from(providedSignature, \"utf-8\")\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Check if token is expired\n */\n isTokenExpired(token: DeviceToken): boolean {\n return token.expiresAt < Date.now();\n }\n\n /**\n * Refresh an existing token\n */\n refreshToken(\n oldToken: DeviceToken,\n expiryDays: number = 30\n ): DeviceToken {\n const newSecret = this.generateSecret();\n const newTokenString = this.generateTokenString(\n oldToken.deviceId,\n newSecret\n );\n\n const expiresAt = Date.now() + expiryDays * 24 * 60 * 60 * 1000;\n\n return {\n ...oldToken,\n token: newTokenString,\n secret: newSecret,\n expiresAt,\n };\n }\n\n /**\n * Extract device ID from token string\n */\n extractDeviceId(token: string): string | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n\n return payload.did || null;\n } catch {\n return null;\n }\n }\n\n /**\n * Generate a unique device ID\n */\n private generateDeviceId(): string {\n return `lingyao_${randomBytes(16).toString(\"hex\")}`;\n }\n\n /**\n * Generate a random secret key\n */\n private generateSecret(): string {\n return randomBytes(32).toString(\"hex\");\n }\n\n /**\n * Generate a JWT-like token string\n */\n private generateTokenString(deviceId: string, secret: string): string {\n const header = {\n alg: \"HS256\",\n typ: \"LingyaoToken\",\n };\n\n const payload = {\n did: deviceId,\n iat: Date.now(),\n };\n\n const headerB64 = this.base64UrlEncode(JSON.stringify(header));\n const payloadB64 = this.base64UrlEncode(JSON.stringify(payload));\n const signature = this.sign(`${headerB64}.${payloadB64}`, secret);\n const signatureB64 = this.base64UrlEncode(signature);\n\n return `${headerB64}.${payloadB64}.${signatureB64}`;\n }\n\n /**\n * Sign data with secret\n */\n private sign(data: string, secret: string): string {\n return createHash(\"sha256\")\n .update(data + secret)\n .digest(\"base64\");\n }\n\n /**\n * Base64URL encode without padding\n */\n private base64UrlEncode(data: string): string {\n return Buffer.from(data)\n .toString(\"base64url\")\n .replace(/=/g, \"\");\n }\n}\n\n/**\n * Generate a pairing code (6-digit numeric)\n */\nexport function generatePairingCode(): string {\n // Generate a 6-digit numeric code\n const min = 100000;\n const max = 999999;\n const code = Math.floor(Math.random() * (max - min + 1)) + min;\n return code.toString();\n}\n\n/**\n * Generate a nonce for pairing\n */\nexport function generateNonce(): string {\n return randomBytes(16).toString(\"hex\");\n}\n\n/**\n * Validate pairing code format\n */\nexport function isValidPairingCode(code: string): boolean {\n return /^\\d{6}$/.test(code);\n}\n","import { z } from \"zod\";\nimport type { LingyaoConfig } from \"./types.js\";\n\n/**\n * Zod schema for Lingyao plugin configuration\n */\nexport const lingyaoConfigSchema = z.object({\n enabled: z.boolean().default(true),\n maxOfflineMessages: z.number().int().min(1).max(1000).optional().default(100),\n tokenExpiryDays: z.number().int().min(1).max(365).optional().default(30),\n});\n\nexport type LingyaoConfigSchema = z.infer<typeof lingyaoConfigSchema>;\n\n/**\n * Validate configuration object\n */\nexport function validateConfig(config: unknown): LingyaoConfig {\n return lingyaoConfigSchema.parse(config);\n}\n\n/**\n * Safely parse configuration, returning null if invalid\n */\nexport function safeParseConfig(config: unknown): LingyaoConfig | null {\n const result = lingyaoConfigSchema.safeParse(config);\n return result.success ? result.data : null;\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): LingyaoConfig {\n return {\n enabled: true,\n maxOfflineMessages: 100,\n tokenExpiryDays: 30,\n };\n}\n"],"mappings":"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","names":["getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","MessageType","capabilities","hostname","randomBytes","createHash","timingSafeEqual","hostname"]}
|