@lingyao037/openclaw-lingyao-cli 1.3.4 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +2 -17
- package/dist/index.js +3 -15
- package/dist/index.js.map +1 -1
- package/dist/setup-entry.js +3 -15
- package/dist/setup-entry.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api.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/ws-heartbeat-interval.ts","../src/server-client.ts","../src/websocket-client.ts","../src/accounts.ts","../src/probe.ts","../src/metrics.ts","../src/errors.ts","../src/config-schema.ts","../src/runtime-api.ts"],"sourcesContent":["import { defineChannelPluginEntry } from 'openclaw/plugin-sdk/channel-core';\nimport { lingyaoPlugin } from './api.js';\nimport { setLingyaoRuntime } from './runtime-api.js';\nimport { lingyaoChannelConfigSchema } from './config-schema.js';\n\nexport * from './api.js';\n\nconst plugin = defineChannelPluginEntry({\n id: 'lingyao',\n name: 'Lingyao',\n description: 'Lingyao Channel Plugin - bidirectional sync via lingyao.live server relay',\n plugin: lingyaoPlugin,\n configSchema: lingyaoChannelConfigSchema,\n setRuntime(runtime) {\n setLingyaoRuntime(runtime as Parameters<typeof setLingyaoRuntime>[0]);\n },\n});\n\nexport default plugin;\n","import type { PluginRuntime, ChannelPlugin } from 'openclaw/plugin-sdk';\nimport { createChatChannelPlugin } from 'openclaw/plugin-sdk/channel-core';\n\nimport { setRuntime, 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 type { LingyaoProbeResult } 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 { lingyaoChannelConfigSchema } from './config-schema.js';\n\nexport * from './types.js';\nexport type { AgentMessage } from './bot.js';\nexport { validateConfig, getDefaultConfig } from './config-schema.js';\n\nlet orchestrator: MultiAccountOrchestrator | null = null;\n\nfunction getOrchestrator(): MultiAccountOrchestrator | null {\n return orchestrator;\n}\n\nconst configAdapter = createConfigAdapter();\nconst setupAdapter = createSetupAdapter();\nconst messagingAdapter = createMessagingAdapter();\nconst gatewayAdapter = createGatewayAdapter(getOrchestrator);\nconst directoryAdapter = createDirectoryAdapter(getOrchestrator);\nconst outboundAdapter = createOutboundAdapter(getOrchestrator);\n\nconst securityOptions = {\n dm: {\n channelKey: 'lingyao',\n resolvePolicy: (account: ResolvedAccount) => account.dmPolicy,\n resolveAllowFrom: (account: ResolvedAccount) => account.allowFrom,\n defaultPolicy: 'pairing' 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\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\nexport const lingyaoPlugin: ChannelPlugin<ResolvedAccount, LingyaoProbeResult> = {\n ...createChatChannelPlugin<ResolvedAccount, LingyaoProbeResult>({\n base: {\n id: 'lingyao',\n meta,\n capabilities,\n configSchema: lingyaoChannelConfigSchema,\n config: configAdapter,\n setup: setupAdapter,\n status: createStatusAdapter(getOrchestrator),\n },\n security: securityOptions,\n pairing: pairingOptions,\n outbound: outboundAdapter,\n }),\n gateway: gatewayAdapter,\n directory: directoryAdapter,\n messaging: messagingAdapter,\n};\n\nexport function initializeLingyaoRuntime(runtime: PluginRuntime): void {\n const adapted = adaptPluginRuntime(runtime as Parameters<typeof adaptPluginRuntime>[0]);\n setRuntime(adapted);\n orchestrator = new MultiAccountOrchestrator(adapted);\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 rawLogger = pr.logging?.getChildLogger?.() ?? {\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n };\n const childLogger = {\n info: rawLogger.info,\n warn: rawLogger.warn,\n error: rawLogger.error,\n debug: rawLogger.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\ntype LingyaoDmPolicy = 'pairing' | 'allowlist' | 'open';\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: LingyaoDmPolicy;\n readonly allowFrom: string[];\n readonly gatewayId?: string;\n readonly rawConfig: LingyaoAccountConfig;\n}\n\n/**\n * Normalize legacy Lingyao DM policy values to current OpenClaw semantics.\n *\n * `paired` was the old plugin-local name for the standard `pairing` mode.\n * `deny` had no SDK equivalent; map it to an empty `allowlist` so behavior\n * stays strict instead of silently opening access.\n */\nfunction normalizeDmPolicy(raw: unknown): LingyaoDmPolicy {\n switch (raw) {\n case 'pairing':\n case 'allowlist':\n case 'open':\n return raw;\n case 'paired':\n return 'pairing';\n case 'deny':\n return 'allowlist';\n default:\n return 'pairing';\n }\n}\n\nfunction extractChannelConfig(cfg: OpenClawConfig): Record<string, unknown> {\n const channels = (cfg as Record<string, unknown>)?.channels as Record<string, unknown> | undefined;\n return (channels?.lingyao as Record<string, unknown> | undefined) ?? {};\n}\n\n/**\n * Extract the Lingyao accounts from OpenClaw config.\n *\n * Lingyao supports top-level single-account fields and nested multi-account\n * fields. Nested accounts inherit unspecified values from the top-level\n * section so the UI and runtime agree on the effective account config.\n */\nfunction extractAccounts(cfg: OpenClawConfig): Record<string, LingyaoAccountConfig> {\n const lingyao = extractChannelConfig(cfg);\n const accounts = lingyao?.accounts as Record<string, LingyaoAccountConfig> | undefined;\n const baseConfig: LingyaoAccountConfig = {\n enabled: lingyao.enabled as boolean | undefined,\n dmPolicy: normalizeDmPolicy(lingyao.dmPolicy),\n allowFrom: Array.isArray(lingyao.allowFrom) ? (lingyao.allowFrom as string[]) : [],\n gatewayId: lingyao.gatewayId as string | undefined,\n websocketHeartbeatIntervalMs: lingyao.websocketHeartbeatIntervalMs as number | undefined,\n };\n\n if (!accounts || Object.keys(accounts).length === 0) {\n return { default: baseConfig };\n }\n\n return Object.fromEntries(\n Object.entries(accounts).map(([accountId, accountConfig]) => {\n const mergedAllowFrom =\n Array.isArray(accountConfig?.allowFrom) && accountConfig.allowFrom.length > 0\n ? accountConfig.allowFrom\n : baseConfig.allowFrom;\n\n const normalized: LingyaoAccountConfig = {\n ...baseConfig,\n ...accountConfig,\n dmPolicy: normalizeDmPolicy(accountConfig?.dmPolicy ?? baseConfig.dmPolicy),\n allowFrom: mergedAllowFrom,\n };\n\n return [accountId, normalized];\n })\n );\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 const ids = Object.keys(accounts);\n return ids.length > 0 ? ids : ['default'];\n },\n\n resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedAccount {\n const accounts = extractAccounts(cfg);\n const ids = Object.keys(accounts);\n const channelConfig = extractChannelConfig(cfg);\n const configuredDefaultAccount = channelConfig.defaultAccount as string | undefined;\n const resolvedId =\n accountId ?? configuredDefaultAccount ?? (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: normalizeDmPolicy((accountConfig as Record<string, unknown>)?.dmPolicy),\n allowFrom: ((accountConfig as Record<string, unknown>)?.allowFrom as string[]) ?? [],\n gatewayId: (accountConfig as Record<string, unknown>)?.gatewayId as string | undefined,\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, PluginRuntime, OpenClawConfig } 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 channelRuntime: ctx.channelRuntime as PluginRuntime['channel'] | undefined,\n cfg: ctx.cfg as OpenClawConfig,\n });\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","import {\n buildBaseChannelStatusSummary,\n createDefaultChannelRuntimeState,\n} from 'openclaw/plugin-sdk/channel-status';\nimport { createComputedAccountStatusAdapter } from 'openclaw/plugin-sdk/status-helpers';\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): ReturnType<typeof createComputedAccountStatusAdapter<ResolvedAccount, LingyaoProbeResult>> {\n return createComputedAccountStatusAdapter<ResolvedAccount, LingyaoProbeResult>({\n defaultRuntime: createDefaultChannelRuntimeState('default'),\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 buildChannelSummary({ snapshot }: { snapshot: any }): Record<string, unknown> {\n return buildBaseChannelStatusSummary(snapshot, {\n connected: snapshot.connected ?? false,\n healthState: snapshot.healthState ?? 'unhealthy',\n dmPolicy: snapshot.dmPolicy ?? 'pairing',\n });\n },\n\n resolveAccountSnapshot({ account, probe }: { account: ResolvedAccount; probe?: LingyaoProbeResult }) {\n const orchestrator = getOrchestrator();\n const state = orchestrator?.getAccountState(account.id);\n const connected = state?.wsClient?.isConnected() ?? false;\n const normalizedProbe = probe ?? {\n ok: false,\n status: 'unhealthy' as const,\n wsConnected: false,\n error: 'Probe not available',\n };\n\n return {\n accountId: account.id,\n enabled: account.enabled,\n configured: true,\n extra: {\n connected,\n healthState: normalizedProbe.status,\n dmPolicy: account.dmPolicy,\n allowFrom: account.allowFrom,\n gatewayId: account.gatewayId ?? state?.gatewayId ?? null,\n },\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 * - resolveSessionConversation: map rawId to conversation structure\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: 'direct' | 'group' | 'channel';\n id: string;\n threadId?: string | null;\n }): string | undefined {\n return `${PREFIX}${params.id}`;\n },\n\n resolveSessionConversation(params: {\n kind: 'group' | 'channel';\n rawId: string;\n }): {\n id: string;\n threadId?: string | null;\n baseConversationId?: string | null;\n parentConversationCandidates?: string[];\n } | null {\n // Lingyao has no group/channel encoding in rawId — treat as passthrough\n return {\n id: params.rawId,\n baseConversationId: params.rawId,\n };\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 \"pairing\".\n */\n\nimport { createPatchedAccountSetupAdapter } from 'openclaw/plugin-sdk/setup-runtime';\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 (\"pairing\") 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, Probe, and Monitor instances.\n *\n * Data flow:\n * Gateway Adapter → orchestrator.start(account, { channelRuntime, cfg }) → WS connect\n * Inbound (App) → WS message → orchestrator → dispatchInboundDirectDmWithRuntime → Agent\n * Outbound (Agent)→ deliver callback → orchestrator.sendNotification() → WS → App\n */\n\nimport { hostname, networkInterfaces } from 'node:os';\nimport { createHash } from 'node:crypto';\nimport { LINGYAO_SERVER_URL, getLingyaoGatewayWsUrl } from './types.js';\nimport { resolveLingyaoWsHeartbeatIntervalMs } from './ws-heartbeat-interval.js';\nimport type { LingyaoRuntime } from './types.js';\nimport type { ResolvedAccount } from './adapters/config.js';\nimport type { PluginRuntime, OpenClawConfig } from 'openclaw/plugin-sdk';\nimport { dispatchInboundDirectDmWithRuntime } from 'openclaw/plugin-sdk/channel-inbound';\nimport { ServerHttpClient } from './server-client.js';\nimport { LingyaoWSClient } from './websocket-client.js';\nimport { AccountManager } from './accounts.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 probe: Probe;\n monitor: Monitor;\n errorHandler: ErrorHandler;\n status: 'stopped' | 'starting' | 'running' | 'stopping' | 'error';\n startTime: number;\n gatewayId: string;\n channelRuntime?: PluginRuntime['channel'];\n cfg?: OpenClawConfig;\n /** One automatic clear+re-register after WS HTTP 404 (avoid infinite loops). */\n wsHandshake404RecoveryAttempted?: boolean;\n}\n\n/**\n * 获取机器的稳定标识符 (基于 MAC 地址)\n */\nfunction getMachineId(): string {\n try {\n const interfaces = networkInterfaces();\n const macSet = new Set<string>();\n\n // 收集所有非内部回环的 MAC 地址,去重后排序保证跨重启稳定\n for (const iface of Object.values(interfaces)) {\n if (!iface) continue;\n for (const alias of iface) {\n if (!alias.internal && alias.mac && alias.mac !== '00:00:00:00:00:00') {\n macSet.add(alias.mac);\n }\n }\n }\n const macs = [...macSet].sort();\n\n if (macs.length > 0) {\n // 排序后的 MAC 地址拼接,取 MD5 前 8 位作为机器稳定标识\n return createHash('md5').update(macs.join('')).digest('hex').substring(0, 8);\n }\n } catch (e) {\n // 忽略获取网卡失败的错误\n }\n\n // 回退:使用随机后缀(由于在内存中缓存,单次运行期间稳定)\n return Math.random().toString(36).substring(2, 10);\n}\n\n// 缓存 machineId,避免频繁计算\nconst MACHINE_ID = getMachineId();\n\n/**\n * Generate a gateway ID for an account\n * 使用主机名 + 机器稳定标识(MAC哈希) + 账户ID,确保跨重启稳定\n */\nfunction generateGatewayId(accountId: string): string {\n const host = hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();\n return `gw_openclaw_${host}_${MACHINE_ID}_${accountId}`;\n}\n\nexport class MultiAccountOrchestrator {\n private runtime: LingyaoRuntime;\n private accounts: Map<string, AccountState> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n }\n\n /**\n * Start an account: create components, register to server, connect WS.\n */\n async start(\n account: ResolvedAccount,\n context?: {\n channelRuntime?: PluginRuntime['channel'];\n cfg?: OpenClawConfig;\n }\n ): 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 = account.gatewayId ?? generateGatewayId(accountId);\n const storagePrefix = `lingyao:${accountId}`;\n\n const accountManager = new AccountManager(this.runtime);\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 probe,\n monitor,\n errorHandler,\n status: 'starting',\n startTime: Date.now(),\n gatewayId,\n channelRuntime: context?.channelRuntime,\n cfg: context?.cfg,\n };\n\n this.accounts.set(accountId, state);\n\n try {\n await accountManager.initialize();\n\n // Register to server (restore from storage or fresh register)\n await this.registerToServer(state);\n\n const wsHeartbeatMs = resolveLingyaoWsHeartbeatIntervalMs(account, httpClient);\n this.runtime.logger.info(`Lingyao WebSocket heartbeat interval: ${wsHeartbeatMs}ms (relay serverConfig / config)`);\n\n // Create and connect WebSocket client\n const wsClient = new LingyaoWSClient(this.runtime, {\n url: getLingyaoGatewayWsUrl(),\n gatewayId,\n token: httpClient.getGatewayToken() ?? undefined,\n reconnectInterval: 5000,\n heartbeatInterval: wsHeartbeatMs,\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 this.runtime.logger.warn(`[${accountId}] Cannot send notification: WS not connected`, { deviceId });\n return false;\n }\n\n this.runtime.logger.info(`[${accountId}] Sending notification to device`, {\n deviceId,\n notificationType: notification.type,\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) via SDK dispatch pipeline.\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.channelRuntime || !state.cfg) {\n this.runtime.logger.warn(`[${state.accountId}] channelRuntime/cfg not available, cannot dispatch to Agent`, {\n messageId: message.id,\n messageType: message.type,\n deviceId,\n });\n return;\n }\n\n this.runtime.logger.info(`[${state.accountId}] Dispatching sync message to Agent via SDK pipeline`, {\n messageId: message.id,\n messageType: message.type,\n deviceId,\n contentLength: message.content?.length ?? 0,\n });\n\n const dmRuntime = {\n channel: {\n routing: {\n resolveAgentRoute: state.channelRuntime.routing.resolveAgentRoute,\n },\n session: {\n resolveStorePath: state.channelRuntime.session.resolveStorePath,\n readSessionUpdatedAt: state.channelRuntime.session.readSessionUpdatedAt,\n recordInboundSession: state.channelRuntime.session.recordInboundSession,\n },\n reply: {\n resolveEnvelopeFormatOptions: state.channelRuntime.reply.resolveEnvelopeFormatOptions,\n formatAgentEnvelope: state.channelRuntime.reply.formatAgentEnvelope,\n finalizeInboundContext: state.channelRuntime.reply.finalizeInboundContext,\n dispatchReplyWithBufferedBlockDispatcher:\n state.channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher,\n },\n },\n };\n\n try {\n await dispatchInboundDirectDmWithRuntime({\n cfg: state.cfg,\n runtime: dmRuntime,\n channel: 'lingyao',\n channelLabel: '灵爻',\n accountId: state.accountId,\n peer: { kind: 'direct', id: deviceId },\n senderId: deviceId,\n senderAddress: deviceId,\n recipientAddress: state.gatewayId,\n conversationLabel: `灵爻 DM with ${deviceId}`,\n rawBody: message.content,\n messageId: message.id,\n timestamp: message.timestamp,\n bodyForAgent: message.content,\n provider: 'lingyao',\n surface: 'lingyao',\n extraContext: {\n messageType: message.type === 'sync_diary' ? 'diary' : 'memory',\n metadata: message.metadata || {},\n },\n deliver: async (payload) => {\n const sent = this.sendNotification(state.accountId, deviceId, {\n type: 'agent_reply',\n text: payload.text,\n mediaUrl: payload.mediaUrl,\n mediaUrls: payload.mediaUrls,\n });\n if (!sent) {\n this.runtime.logger.warn(\n `[${state.accountId}] Failed to deliver Agent reply to ${deviceId}: WS not connected`\n );\n }\n },\n onRecordError: (err: unknown) => {\n this.runtime.logger.error(`[${state.accountId}] Failed to record inbound session`, err);\n },\n onDispatchError: (err: unknown, info: { kind: string }) => {\n this.runtime.logger.error(`[${state.accountId}] Dispatch error`, { err, kind: info.kind });\n },\n });\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] dispatchInboundDirectDmWithRuntime failed`, error);\n throw error;\n }\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\n // 如果是因为 Token 无效导致的断开,触发重新注册和重连\n if (event.code === 1008) {\n this.runtime.logger.warn(`[${state.accountId}] Token invalid (1008). Forcing re-registration...`);\n this.handleInvalidToken(state).catch(err => {\n this.runtime.logger.error(`[${state.accountId}] Failed to re-register after 1008`, err);\n });\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 case 'fatal_handshake':\n if (event.reason === 'http_404') {\n void this.handleWsHandshake404(state);\n }\n break;\n case 'pairing_completed':\n this.handlePairingCompleted(state, event);\n break;\n }\n };\n }\n\n /**\n * Handle pairing completed event from WS — auto-bind device.\n */\n private async handlePairingCompleted(state: AccountState, event: any): Promise<void> {\n const { deviceId, deviceInfo } = event;\n this.runtime.logger.info(`[${state.accountId}] Pairing completed, auto-binding device`, { deviceId, deviceInfo });\n\n try {\n await state.accountManager.addDevice(deviceId, {\n name: deviceInfo?.name ?? deviceId,\n platform: deviceInfo?.platform ?? 'harmonyos',\n version: deviceInfo?.version ?? '',\n });\n this.runtime.logger.info(`[${state.accountId}] Device auto-bound: ${deviceId}`);\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] Failed to auto-bind device: ${deviceId}`, error);\n }\n }\n\n /**\n * After HTTP 404 on WebSocket upgrade: clear local tokens, re-register once, reconnect.\n * Does not fix wrong server URL or permanently deleted gateway rows (user must fix config).\n */\n private async handleWsHandshake404(state: AccountState): Promise<void> {\n if (state.wsHandshake404RecoveryAttempted) {\n this.runtime.logger.error(\n `[${state.accountId}] Lingyao WebSocket still failing after one recovery attempt. ` +\n `Check that wss://…/lyoc/gateway/ws is deployed; if the gateway was removed, delete ` +\n `\\`channels.lingyao.accounts.${state.accountId}.gatewayId\\` or use a new account id, then restart.`\n );\n return;\n }\n state.wsHandshake404RecoveryAttempted = true;\n\n const { httpClient, wsClient, accountId } = state;\n if (!httpClient || !wsClient) {\n return;\n }\n\n this.runtime.logger.info(`[${accountId}] WS HTTP 404 — clearing local session and re-registering...`);\n\n try {\n await httpClient.clearLocalSession();\n const response = await httpClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n wsClient.updateToken(response.gatewayToken);\n await wsClient.connect();\n this.runtime.logger.info(`[${accountId}] Re-register OK; WebSocket reconnect issued.`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes('already registered')) {\n this.runtime.logger.error(\n `[${accountId}] Re-register failed: gateway still registered on server but local session was cleared. ` +\n `Remove or change \\`gatewayId\\` under this account, or reset the gateway on lingyao.live, then restart OpenClaw.`,\n error\n );\n } else {\n this.runtime.logger.error(`[${accountId}] WS 404 recovery (clear + register) failed`, error);\n }\n }\n }\n\n /**\n * Handle invalid token by re-registering the gateway and reconnecting WS\n */\n private async handleInvalidToken(state: AccountState): Promise<void> {\n if (!state.httpClient || !state.wsClient) {\n return;\n }\n\n try {\n this.runtime.logger.info(`[${state.accountId}] Requesting new gateway token...`);\n // 强制重新注册以获取新 token\n const response = await state.httpClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n\n this.runtime.logger.info(`[${state.accountId}] Obtained new token. Reconnecting WS...`);\n // 更新 WS 客户端的 token 并重新连接\n state.wsClient.updateToken(response.gatewayToken);\n await state.wsClient.connect();\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] Failed to handle invalid token`, error);\n // 可以在此处接入 errorHandler 以实现更高级的退避重试\n state.errorHandler.handleError(error as Error);\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 * WebSocket URL for the OpenClaw gateway client (must use wss:// for TLS).\n * The `ws` package accepts https URLs in some builds, but wss:// avoids ambiguity.\n */\n/** Production api.lingyao.live exposes Gateway WS under `/lyoc` (not `/v1`). */\nexport function getLingyaoGatewayWsUrl(): string {\n return LINGYAO_SERVER_URL.replace(/^https:/i, 'wss:') + '/lyoc/gateway/ws';\n}\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?: \"pairing\" | \"allowlist\" | \"open\";\n allowFrom?: string[];\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n gatewayId?: string;\n /**\n * WebSocket `gateway_heartbeat` 间隔(毫秒)。默认使用注册接口返回的 `heartbeatInterval`。\n * 建议 5000–55000,须小于中继 `heartbeatTimeout`(常见 60s)。\n */\n websocketHeartbeatIntervalMs?: number;\n}\n\n/**\n * Channel configuration\n */\nexport interface LingyaoConfig {\n enabled: boolean;\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n dmPolicy?: \"pairing\" | \"allowlist\" | \"open\";\n allowFrom?: string[];\n /** 顶层默认,可被 `accounts.<id>` 覆盖 */\n websocketHeartbeatIntervalMs?: number;\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","import type { ResolvedAccount } from './adapters/config.js';\nimport type { ServerHttpClient } from './server-client.js';\n\n/** 中继通常 60s 内无心跳即判离线;WS 心跳间隔需明显小于该值 */\nconst MIN_MS = 5_000;\nconst MAX_MS = 55_000;\nconst FALLBACK_MS = 30_000;\n\n/**\n * 灵爻 Gateway WebSocket 心跳间隔:优先用户配置,其次 HTTP 注册返回的 `serverConfig.heartbeatInterval`,并钳制在安全范围。\n */\nexport function resolveLingyaoWsHeartbeatIntervalMs(\n account: ResolvedAccount,\n httpClient: ServerHttpClient\n): number {\n const fromServer = httpClient.getHeartbeatIntervalMs();\n const fromCfg = account.rawConfig?.websocketHeartbeatIntervalMs;\n let ms =\n typeof fromCfg === 'number' && Number.isFinite(fromCfg) && fromCfg > 0 ? fromCfg : fromServer;\n if (!Number.isFinite(ms) || ms <= 0) {\n ms = FALLBACK_MS;\n }\n return Math.max(MIN_MS, Math.min(ms, MAX_MS));\n}\n\n/**\n * 非 OpenClaw 多账户路径(如旧版 `LingyaoChannel`)仅根据 HTTP 客户端解析间隔。\n */\nexport function resolveLingyaoWsHeartbeatIntervalMsFromHttp(httpClient: ServerHttpClient): number {\n const ms = httpClient.getHeartbeatIntervalMs();\n const base = Number.isFinite(ms) && ms > 0 ? ms : FALLBACK_MS;\n return Math.max(MIN_MS, Math.min(base, MAX_MS));\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 // Public API (api.lingyao.live) serves gateway HTTP under /lyoc; local relay also accepts /lyoc (see server getApiPathSuffix).\n apiBase: serverConfig.apiBase || '/lyoc',\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 } else if (status === 404) {\n throw new Error(\n 'Lingyao gateway register returned 404. Check server URL and /lyoc/gateway/register; ' +\n 'the gatewayId may be invalid or the API may not be deployed on this host.'\n );\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 * HTTP 注册/恢复后由 `serverConfig.heartbeatInterval` 写入(毫秒),用于与 WebSocket `gateway_heartbeat` 对齐。\n */\n getHeartbeatIntervalMs(): number {\n return this.heartbeatInterval > 0 ? this.heartbeatInterval : 30000;\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 * Clear local gateway token/session (storage + in-memory). Used when WS handshake\n * fails with 404 or when forcing re-registration with the same gatewayId.\n */\n async clearLocalSession(): Promise<void> {\n this.stopHeartbeat();\n this.gatewayToken = null;\n this.webhookSecret = null;\n this.tokenExpiresAt = 0;\n this.isRegistered = false;\n\n const keys = ['gatewayToken', 'webhookSecret', 'tokenExpiresAt', 'serverConfig'] as const;\n for (const k of keys) {\n try {\n await this.runtime.storage.delete(this.storageKey(k));\n } catch (e) {\n this.runtime.logger.warn(`Failed to delete storage key ${k}`, e);\n }\n }\n\n this.runtime.logger.info('Cleared local Lingyao gateway session');\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 消息类型(与 `lingyao/server/src/server.ts` 中 Gateway 协议一致)\n */\nexport enum WSMessageType {\n // Gateway → 服务器\n GATEWAY_REGISTER = \"gateway_register\",\n GATEWAY_HEARTBEAT = \"gateway_heartbeat\",\n GATEWAY_SEND_MESSAGE = \"gateway_send_message\",\n\n // 服务器 → Gateway\n GATEWAY_REGISTERED = \"gateway_registered\",\n GATEWAY_HEARTBEAT_ACK = \"gateway_heartbeat_ack\",\n MESSAGE_DELIVERED = \"message_delivered\",\n MESSAGE_FAILED = \"message_failed\",\n APP_MESSAGE = \"app_message\",\n DEVICE_ONLINE = \"device_online\",\n PAIRING_COMPLETED = \"pairing_completed\",\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.GATEWAY_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.GATEWAY_HEARTBEAT;\n payload: {\n timestamp: number;\n status: \"online\";\n };\n}\n\n/**\n * 发送消息\n */\nexport interface SendMessage extends WSMessage {\n type: WSMessageType.GATEWAY_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: \"fatal_handshake\"; reason: \"http_404\" }\n | { type: \"message\"; message: WSMessage }\n | { type: \"appMessage\"; deviceId: string; message: AppMessage[\"payload\"][\"message\"] }\n | { type: \"pairing_completed\"; deviceId: string; deviceInfo: { name: string; platform: string; version: string }; sessionId: string };\n\n/** True when the `ws` library reports HTTP 404 on the WebSocket upgrade (invalid path or gateway rejected at edge). */\nexport function isWebsocketUpgradeNotFoundError(message: string): boolean {\n return /Unexpected server response:\\s*404/i.test(message) || /\\b404\\b/.test(message);\n}\n\n/**\n * 将服务端类型映射到本客户端 handler 使用的 key(与 {@link WSMessageType} 一致)。\n * 仍接受旧版短名 `registered` / `heartbeat_ack`,便于与历史部署混连。\n */\nexport function normalizeIncomingGatewayMessageType(type: string): string {\n switch (type) {\n case \"registered\":\n return WSMessageType.GATEWAY_REGISTERED;\n case \"heartbeat_ack\":\n return WSMessageType.GATEWAY_HEARTBEAT_ACK;\n case \"gateway_registered\":\n return WSMessageType.GATEWAY_REGISTERED;\n case \"gateway_heartbeat_ack\":\n return WSMessageType.GATEWAY_HEARTBEAT_ACK;\n default:\n return type;\n }\n}\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 /** When set, close handler will not schedule reconnect (e.g. HTTP 404 on upgrade). */\n private suppressReconnect = false;\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.GATEWAY_REGISTERED, this.handleRegistered.bind(this));\n this.registerMessageHandler(WSMessageType.GATEWAY_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.DEVICE_ONLINE, this.handleDeviceOnline.bind(this));\n this.registerMessageHandler(WSMessageType.PAIRING_COMPLETED, this.handlePairingCompleted.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.suppressReconnect = false;\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 const rawType = String(message.type);\n const handlerKey = normalizeIncomingGatewayMessageType(rawType);\n this.logger.debug(\"Received message from server\", { type: rawType, handlerKey });\n\n const handler = this.messageHandlers.get(handlerKey);\n if (handler) {\n handler(message);\n } else {\n this.logger.warn(\"No handler for message type\", { type: rawType });\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 const msg = error?.message ?? String(error);\n if (isWebsocketUpgradeNotFoundError(msg)) {\n this.suppressReconnect = true;\n this.logger.error(\n \"WebSocket handshake failed with HTTP 404 — stopping reconnect loop. \" +\n \"If the gateway was removed server-side, remove `gatewayId` from channels.lingyao.accounts.* \" +\n \"or use a new account id; if the path is wrong, verify wss://…/lyoc/gateway/ws is deployed on api.lingyao.live.\",\n { gatewayId: this.config.gatewayId, message: msg }\n );\n } else {\n this.logger.error(\"WebSocket error\", error);\n }\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 // 1008 表示 Token 无效,不应继续使用原 Token 重连,交给外部重新注册\n if (code === 1008) {\n this.logger.error(\"WebSocket closed with 1008 (Invalid Token). Stopping reconnect loop.\");\n return;\n }\n\n if (this.suppressReconnect) {\n this.suppressReconnect = false;\n this.emitEvent({ type: \"fatal_handshake\", reason: \"http_404\" });\n return;\n }\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.GATEWAY_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.GATEWAY_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.GATEWAY_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 handleDeviceOnline(message: WSMessage): void {\n this.logger.debug(\"Device online (server push)\", {\n payload: message.payload,\n });\n }\n\n /**\n * 处理配对完成通知(来自 lingyao.live 服务器)\n */\n private handlePairingCompleted(message: WSMessage): void {\n const payload = message.payload;\n this.logger.info(\"Pairing completed\", {\n deviceId: payload?.deviceId,\n sessionId: payload?.sessionId,\n });\n\n if (this.config.eventHandler) {\n this.config.eventHandler({\n type: \"pairing_completed\",\n deviceId: payload?.deviceId,\n deviceInfo: payload?.deviceInfo,\n sessionId: payload?.sessionId,\n });\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 * 更新 WebSocket 连接使用的 token\n */\n updateToken(token: string): void {\n this.config.token = token;\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 * Manually add a device by deviceId (user-initiated pairing).\n * No pairing code or deviceToken required — the user explicitly\n * trusts this device from the OpenClaw CLI.\n */\n async addDevice(deviceId: string, deviceInfo: DeviceInfo): Promise<LingyaoAccount> {\n const existing = this.accounts.get(deviceId);\n if (existing) {\n // Already tracked — reactivate if revoked\n existing.status = 'active';\n existing.deviceInfo = deviceInfo;\n existing.lastSeenAt = Date.now();\n await this.saveAccounts();\n this.runtime.logger.info(`Device re-activated: ${deviceId} (${deviceInfo.name})`);\n return existing;\n }\n\n const now = Date.now();\n const account: LingyaoAccount = {\n deviceId,\n deviceInfo,\n deviceToken: {\n deviceId,\n pairingId: `manual_${now}`,\n token: '',\n secret: '',\n expiresAt: 0,\n deviceInfo,\n },\n pairedAt: now,\n lastSeenAt: now,\n status: 'active',\n };\n\n this.accounts.set(deviceId, account);\n await this.saveAccounts();\n\n this.runtime.logger.info(`Device added: ${deviceId} (${deviceInfo.name})`);\n return account;\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 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 const key = `${data.name}_${Date.now()}_${Math.random().toString(36).substring(7)}`;\n this.metrics.set(key, data);\n\n // 限制历史记录数量,避免内存泄漏\n if (this.metrics.size > 10000) {\n // 优化:Map 保持插入顺序,最旧的数据在最前面,直接通过迭代器删除前 10%\n let count = 0;\n const deleteCount = Math.floor(this.metrics.size * 0.1);\n for (const k of this.metrics.keys()) {\n this.metrics.delete(k);\n if (++count >= deleteCount) break;\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 private cleanupTimer: NodeJS.Timeout | null = null;\n private errorTimestamps: Map<string, number[]> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n\n // 每 5 分钟执行一次统一的错误清理,替代为每个错误单独创建 setTimeout\n this.cleanupTimer = setInterval(() => this.cleanupOldErrors(), 5 * 60 * 1000);\n if (this.cleanupTimer.unref) {\n this.cleanupTimer.unref(); // 允许进程正常退出\n }\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 public destroy(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n\n private cleanupOldErrors(): void {\n const now = Date.now();\n for (const [code, timestamps] of this.errorTimestamps.entries()) {\n const thresholdConfig = this.errorThresholds.get(code);\n const windowMs = thresholdConfig?.window || 3600000; // 默认 1 小时\n \n // 保留在窗口期内的时间戳\n const validTimestamps = timestamps.filter(ts => now - ts <= windowMs);\n \n if (validTimestamps.length === 0) {\n this.errorTimestamps.delete(code);\n this.errorCounts.delete(code);\n // 如果需要,也可以选择保留 lastErrors 供追溯,或者一起删除\n } else {\n this.errorTimestamps.set(code, validTimestamps);\n this.errorCounts.set(code, validTimestamps.length);\n }\n }\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 timestamp = Date.now();\n\n // 先清理该类型的过期错误,确保计数准确\n const thresholdConfig = this.errorThresholds.get(key);\n const windowMs = thresholdConfig?.window || 3600000;\n \n let timestamps = this.errorTimestamps.get(key) || [];\n timestamps = timestamps.filter(ts => timestamp - ts <= windowMs);\n \n // 记录新的时间戳\n timestamps.push(timestamp);\n this.errorTimestamps.set(key, timestamps);\n\n // 更新当前时间窗口内的错误计数\n this.errorCounts.set(key, timestamps.length);\n\n this.lastErrors.set(key, {\n error,\n timestamp,\n });\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","import { z } from \"zod\";\nimport type { LingyaoConfig } from \"./types.js\";\n\n/**\n * OpenClaw-standard DM policy values.\n */\nexport const lingyaoDmPolicySchema = z.enum([\"pairing\", \"allowlist\", \"open\"]);\n\nconst allowFromSchema = z.array(z.string()).optional();\n\nexport const lingyaoAccountConfigSchema = z.object({\n enabled: z.boolean().optional(),\n dmPolicy: lingyaoDmPolicySchema.optional(),\n allowFrom: allowFromSchema,\n websocketHeartbeatIntervalMs: z.number().int().min(5000).max(120000).optional(),\n});\n\n/**\n * Zod schema for Lingyao channel configuration.\n *\n * Lingyao supports both top-level single-account config and\n * `channels.lingyao.accounts.<id>` multi-account config. Account entries inherit\n * unspecified values from the top-level section.\n */\nexport const lingyaoConfigSchema = z.object({\n enabled: z.boolean().default(true),\n dmPolicy: lingyaoDmPolicySchema.optional().default(\"pairing\"),\n allowFrom: allowFromSchema.default([]),\n websocketHeartbeatIntervalMs: z.number().int().min(5000).max(120000).optional(),\n defaultAccount: z.string().min(1).optional(),\n accounts: z.record(lingyaoAccountConfigSchema).optional(),\n});\n\nexport type LingyaoConfigSchema = z.infer<typeof lingyaoConfigSchema>;\nexport const lingyaoChannelConfigSchema = {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n enabled: {\n type: \"boolean\",\n default: true,\n },\n dmPolicy: {\n type: \"string\",\n enum: [\"pairing\", \"allowlist\", \"open\"],\n default: \"pairing\",\n },\n allowFrom: {\n type: \"array\",\n items: { type: \"string\" },\n default: [],\n },\n defaultAccount: {\n type: \"string\",\n },\n websocketHeartbeatIntervalMs: {\n type: \"integer\",\n minimum: 5000,\n maximum: 120000,\n description:\n \"WebSocket gateway_heartbeat interval in ms (default: server register response). Use 5000–55000 for typical relay timeout.\",\n },\n accounts: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n enabled: {\n type: \"boolean\",\n default: true,\n },\n dmPolicy: {\n type: \"string\",\n enum: [\"pairing\", \"allowlist\", \"open\"],\n },\n allowFrom: {\n type: \"array\",\n items: { type: \"string\" },\n },\n websocketHeartbeatIntervalMs: {\n type: \"integer\",\n minimum: 5000,\n maximum: 120000,\n },\n },\n default: {},\n },\n },\n },\n} as const;\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 dmPolicy: \"pairing\",\n allowFrom: [],\n };\n}\n","import type { PluginRuntime } from 'openclaw/plugin-sdk';\n\nimport { initializeLingyaoRuntime } from './api.js';\n\nexport function setLingyaoRuntime(runtime: PluginRuntime): void {\n initializeLingyaoRuntime(runtime);\n}\n"],"mappings":"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","names":["getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","MessageType","capabilities"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api.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/ws-heartbeat-interval.ts","../src/server-client.ts","../src/websocket-client.ts","../src/accounts.ts","../src/probe.ts","../src/metrics.ts","../src/errors.ts","../src/config-schema.ts","../src/runtime-api.ts"],"sourcesContent":["import { defineChannelPluginEntry } from 'openclaw/plugin-sdk/channel-core';\nimport { lingyaoPlugin } from './api.js';\nimport { setLingyaoRuntime } from './runtime-api.js';\nimport { lingyaoChannelConfigSchema } from './config-schema.js';\n\nexport * from './api.js';\n\nconst plugin = defineChannelPluginEntry({\n id: 'lingyao',\n name: 'Lingyao',\n description: 'Lingyao Channel Plugin - bidirectional sync via lingyao.live server relay',\n plugin: lingyaoPlugin,\n configSchema: lingyaoChannelConfigSchema,\n setRuntime(runtime) {\n setLingyaoRuntime(runtime as Parameters<typeof setLingyaoRuntime>[0]);\n },\n});\n\nexport default plugin;\n","import type { PluginRuntime, ChannelPlugin } from 'openclaw/plugin-sdk';\nimport { createChatChannelPlugin } from 'openclaw/plugin-sdk/channel-core';\n\nimport { setRuntime, 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 type { LingyaoProbeResult } 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 { lingyaoChannelConfigSchema } from './config-schema.js';\n\nexport * from './types.js';\nexport type { AgentMessage } from './bot.js';\nexport { validateConfig, getDefaultConfig } from './config-schema.js';\n\nlet orchestrator: MultiAccountOrchestrator | null = null;\n\nfunction getOrchestrator(): MultiAccountOrchestrator | null {\n return orchestrator;\n}\n\nconst configAdapter = createConfigAdapter();\nconst setupAdapter = createSetupAdapter();\nconst messagingAdapter = createMessagingAdapter();\nconst gatewayAdapter = createGatewayAdapter(getOrchestrator);\nconst directoryAdapter = createDirectoryAdapter(getOrchestrator);\nconst outboundAdapter = createOutboundAdapter(getOrchestrator);\n\nconst securityOptions = {\n dm: {\n channelKey: 'lingyao',\n resolvePolicy: (account: ResolvedAccount) => account.dmPolicy,\n resolveAllowFrom: (account: ResolvedAccount) => account.allowFrom,\n defaultPolicy: 'pairing' 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\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\nexport const lingyaoPlugin: ChannelPlugin<ResolvedAccount, LingyaoProbeResult> = {\n ...createChatChannelPlugin<ResolvedAccount, LingyaoProbeResult>({\n base: {\n id: 'lingyao',\n meta,\n capabilities,\n configSchema: lingyaoChannelConfigSchema,\n config: configAdapter,\n setup: setupAdapter,\n status: createStatusAdapter(getOrchestrator),\n },\n security: securityOptions,\n pairing: pairingOptions,\n outbound: outboundAdapter,\n }),\n gateway: gatewayAdapter,\n directory: directoryAdapter,\n messaging: messagingAdapter,\n};\n\nexport function initializeLingyaoRuntime(runtime: PluginRuntime): void {\n const adapted = adaptPluginRuntime(runtime as Parameters<typeof adaptPluginRuntime>[0]);\n setRuntime(adapted);\n orchestrator = new MultiAccountOrchestrator(adapted);\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 rawLogger = pr.logging?.getChildLogger?.() ?? {\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n };\n const childLogger = {\n info: rawLogger.info,\n warn: rawLogger.warn,\n error: rawLogger.error,\n debug: rawLogger.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\ntype LingyaoDmPolicy = 'pairing' | 'allowlist' | 'open';\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: LingyaoDmPolicy;\n readonly allowFrom: string[];\n readonly gatewayId?: string;\n readonly rawConfig: LingyaoAccountConfig;\n}\n\n/**\n * Normalize legacy Lingyao DM policy values to current OpenClaw semantics.\n *\n * `paired` was the old plugin-local name for the standard `pairing` mode.\n * `deny` had no SDK equivalent; map it to an empty `allowlist` so behavior\n * stays strict instead of silently opening access.\n */\nfunction normalizeDmPolicy(raw: unknown): LingyaoDmPolicy {\n switch (raw) {\n case 'pairing':\n case 'allowlist':\n case 'open':\n return raw;\n case 'paired':\n return 'pairing';\n case 'deny':\n return 'allowlist';\n default:\n return 'pairing';\n }\n}\n\nfunction extractChannelConfig(cfg: OpenClawConfig): Record<string, unknown> {\n const channels = (cfg as Record<string, unknown>)?.channels as Record<string, unknown> | undefined;\n return (channels?.lingyao as Record<string, unknown> | undefined) ?? {};\n}\n\n/**\n * Extract the Lingyao accounts from OpenClaw config.\n *\n * Lingyao supports top-level single-account fields and nested multi-account\n * fields. Nested accounts inherit unspecified values from the top-level\n * section so the UI and runtime agree on the effective account config.\n */\nfunction extractAccounts(cfg: OpenClawConfig): Record<string, LingyaoAccountConfig> {\n const lingyao = extractChannelConfig(cfg);\n const accounts = lingyao?.accounts as Record<string, LingyaoAccountConfig> | undefined;\n const baseConfig: LingyaoAccountConfig = {\n enabled: lingyao.enabled as boolean | undefined,\n dmPolicy: normalizeDmPolicy(lingyao.dmPolicy),\n allowFrom: Array.isArray(lingyao.allowFrom) ? (lingyao.allowFrom as string[]) : [],\n gatewayId: lingyao.gatewayId as string | undefined,\n websocketHeartbeatIntervalMs: lingyao.websocketHeartbeatIntervalMs as number | undefined,\n };\n\n if (!accounts || Object.keys(accounts).length === 0) {\n return { default: baseConfig };\n }\n\n return Object.fromEntries(\n Object.entries(accounts).map(([accountId, accountConfig]) => {\n const mergedAllowFrom =\n Array.isArray(accountConfig?.allowFrom) && accountConfig.allowFrom.length > 0\n ? accountConfig.allowFrom\n : baseConfig.allowFrom;\n\n const normalized: LingyaoAccountConfig = {\n ...baseConfig,\n ...accountConfig,\n dmPolicy: normalizeDmPolicy(accountConfig?.dmPolicy ?? baseConfig.dmPolicy),\n allowFrom: mergedAllowFrom,\n };\n\n return [accountId, normalized];\n })\n );\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 const ids = Object.keys(accounts);\n return ids.length > 0 ? ids : ['default'];\n },\n\n resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedAccount {\n const accounts = extractAccounts(cfg);\n const ids = Object.keys(accounts);\n const channelConfig = extractChannelConfig(cfg);\n const configuredDefaultAccount = channelConfig.defaultAccount as string | undefined;\n const resolvedId =\n accountId ?? configuredDefaultAccount ?? (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: normalizeDmPolicy((accountConfig as Record<string, unknown>)?.dmPolicy),\n allowFrom: ((accountConfig as Record<string, unknown>)?.allowFrom as string[]) ?? [],\n gatewayId: (accountConfig as Record<string, unknown>)?.gatewayId as string | undefined,\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, PluginRuntime, OpenClawConfig } 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 channelRuntime: ctx.channelRuntime as PluginRuntime['channel'] | undefined,\n cfg: ctx.cfg as OpenClawConfig,\n });\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","import {\n buildBaseChannelStatusSummary,\n createDefaultChannelRuntimeState,\n} from 'openclaw/plugin-sdk/channel-status';\nimport { createComputedAccountStatusAdapter } from 'openclaw/plugin-sdk/status-helpers';\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): ReturnType<typeof createComputedAccountStatusAdapter<ResolvedAccount, LingyaoProbeResult>> {\n return createComputedAccountStatusAdapter<ResolvedAccount, LingyaoProbeResult>({\n defaultRuntime: createDefaultChannelRuntimeState('default'),\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 buildChannelSummary({ snapshot }: { snapshot: any }): Record<string, unknown> {\n return buildBaseChannelStatusSummary(snapshot, {\n connected: snapshot.connected ?? false,\n healthState: snapshot.healthState ?? 'unhealthy',\n dmPolicy: snapshot.dmPolicy ?? 'pairing',\n });\n },\n\n resolveAccountSnapshot({ account, probe }: { account: ResolvedAccount; probe?: LingyaoProbeResult }) {\n const orchestrator = getOrchestrator();\n const state = orchestrator?.getAccountState(account.id);\n const connected = state?.wsClient?.isConnected() ?? false;\n const normalizedProbe = probe ?? {\n ok: false,\n status: 'unhealthy' as const,\n wsConnected: false,\n error: 'Probe not available',\n };\n\n return {\n accountId: account.id,\n enabled: account.enabled,\n configured: true,\n extra: {\n connected,\n healthState: normalizedProbe.status,\n dmPolicy: account.dmPolicy,\n allowFrom: account.allowFrom,\n gatewayId: account.gatewayId ?? state?.gatewayId ?? null,\n },\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 * - resolveSessionConversation: map rawId to conversation structure\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: 'direct' | 'group' | 'channel';\n id: string;\n threadId?: string | null;\n }): string | undefined {\n return `${PREFIX}${params.id}`;\n },\n\n resolveSessionConversation(params: {\n kind: 'group' | 'channel';\n rawId: string;\n }): {\n id: string;\n threadId?: string | null;\n baseConversationId?: string | null;\n parentConversationCandidates?: string[];\n } | null {\n // Lingyao has no group/channel encoding in rawId — treat as passthrough\n return {\n id: params.rawId,\n baseConversationId: params.rawId,\n };\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 \"pairing\".\n */\n\nimport { createPatchedAccountSetupAdapter } from 'openclaw/plugin-sdk/setup-runtime';\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 (\"pairing\") 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, Probe, and Monitor instances.\n *\n * Data flow:\n * Gateway Adapter → orchestrator.start(account, { channelRuntime, cfg }) → WS connect\n * Inbound (App) → WS message → orchestrator → dispatchInboundDirectDmWithRuntime → Agent\n * Outbound (Agent)→ deliver callback → orchestrator.sendNotification() → WS → App\n */\n\nimport { hostname } from 'node:os';\nimport { createHash } from 'node:crypto';\nimport { LINGYAO_SERVER_URL, getLingyaoGatewayWsUrl } from './types.js';\nimport { resolveLingyaoWsHeartbeatIntervalMs } from './ws-heartbeat-interval.js';\nimport type { LingyaoRuntime } from './types.js';\nimport type { ResolvedAccount } from './adapters/config.js';\nimport type { PluginRuntime, OpenClawConfig } from 'openclaw/plugin-sdk';\nimport { dispatchInboundDirectDmWithRuntime } from 'openclaw/plugin-sdk/channel-inbound';\nimport { ServerHttpClient } from './server-client.js';\nimport { LingyaoWSClient } from './websocket-client.js';\nimport { AccountManager } from './accounts.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 probe: Probe;\n monitor: Monitor;\n errorHandler: ErrorHandler;\n status: 'stopped' | 'starting' | 'running' | 'stopping' | 'error';\n startTime: number;\n gatewayId: string;\n channelRuntime?: PluginRuntime['channel'];\n cfg?: OpenClawConfig;\n /** One automatic clear+re-register after WS HTTP 404 (avoid infinite loops). */\n wsHandshake404RecoveryAttempted?: boolean;\n}\n\n/**\n * 获取机器的稳定标识符 (基于 MAC 地址)\n *\n * 使用 hostname 作为主要标识(跨重启稳定),MAC 地址作为辅助。\n * 虚拟接口的 MAC 不稳定(VPN、Docker 等会动态创建),所以只用 hostname 哈希。\n */\nfunction getMachineId(): string {\n try {\n // hostname 在单台机器上跨重启稳定\n const host = hostname();\n return createHash('md5').update(host).digest('hex').substring(0, 8);\n } catch (e) {\n // 忽略错误\n }\n\n // 回退:使用随机后缀(由于在内存中缓存,单次运行期间稳定)\n return Math.random().toString(36).substring(2, 10);\n}\n\n// 缓存 machineId,避免频繁计算\nconst MACHINE_ID = getMachineId();\n\n/**\n * Generate a gateway ID for an account\n * 使用主机名 + 机器稳定标识(MAC哈希) + 账户ID,确保跨重启稳定\n */\nfunction generateGatewayId(accountId: string): string {\n const host = hostname().split('.')[0].replace(/[^a-z0-9]/gi, '').toLowerCase();\n return `gw_openclaw_${host}_${MACHINE_ID}_${accountId}`;\n}\n\nexport class MultiAccountOrchestrator {\n private runtime: LingyaoRuntime;\n private accounts: Map<string, AccountState> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n }\n\n /**\n * Start an account: create components, register to server, connect WS.\n */\n async start(\n account: ResolvedAccount,\n context?: {\n channelRuntime?: PluginRuntime['channel'];\n cfg?: OpenClawConfig;\n }\n ): 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 = account.gatewayId ?? generateGatewayId(accountId);\n const storagePrefix = `lingyao:${accountId}`;\n\n const accountManager = new AccountManager(this.runtime);\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 probe,\n monitor,\n errorHandler,\n status: 'starting',\n startTime: Date.now(),\n gatewayId,\n channelRuntime: context?.channelRuntime,\n cfg: context?.cfg,\n };\n\n this.accounts.set(accountId, state);\n\n try {\n await accountManager.initialize();\n\n // Register to server (restore from storage or fresh register)\n await this.registerToServer(state);\n\n const wsHeartbeatMs = resolveLingyaoWsHeartbeatIntervalMs(account, httpClient);\n this.runtime.logger.info(`Lingyao WebSocket heartbeat interval: ${wsHeartbeatMs}ms (relay serverConfig / config)`);\n\n // Create and connect WebSocket client\n const wsClient = new LingyaoWSClient(this.runtime, {\n url: getLingyaoGatewayWsUrl(),\n gatewayId,\n token: httpClient.getGatewayToken() ?? undefined,\n reconnectInterval: 5000,\n heartbeatInterval: wsHeartbeatMs,\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 this.runtime.logger.warn(`[${accountId}] Cannot send notification: WS not connected`, { deviceId });\n return false;\n }\n\n this.runtime.logger.info(`[${accountId}] Sending notification to device`, {\n deviceId,\n notificationType: notification.type,\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) via SDK dispatch pipeline.\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.channelRuntime || !state.cfg) {\n this.runtime.logger.warn(`[${state.accountId}] channelRuntime/cfg not available, cannot dispatch to Agent`, {\n messageId: message.id,\n messageType: message.type,\n deviceId,\n });\n return;\n }\n\n this.runtime.logger.info(`[${state.accountId}] Dispatching sync message to Agent via SDK pipeline`, {\n messageId: message.id,\n messageType: message.type,\n deviceId,\n contentLength: message.content?.length ?? 0,\n });\n\n const dmRuntime = {\n channel: {\n routing: {\n resolveAgentRoute: state.channelRuntime.routing.resolveAgentRoute,\n },\n session: {\n resolveStorePath: state.channelRuntime.session.resolveStorePath,\n readSessionUpdatedAt: state.channelRuntime.session.readSessionUpdatedAt,\n recordInboundSession: state.channelRuntime.session.recordInboundSession,\n },\n reply: {\n resolveEnvelopeFormatOptions: state.channelRuntime.reply.resolveEnvelopeFormatOptions,\n formatAgentEnvelope: state.channelRuntime.reply.formatAgentEnvelope,\n finalizeInboundContext: state.channelRuntime.reply.finalizeInboundContext,\n dispatchReplyWithBufferedBlockDispatcher:\n state.channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher,\n },\n },\n };\n\n try {\n await dispatchInboundDirectDmWithRuntime({\n cfg: state.cfg,\n runtime: dmRuntime,\n channel: 'lingyao',\n channelLabel: '灵爻',\n accountId: state.accountId,\n peer: { kind: 'direct', id: deviceId },\n senderId: deviceId,\n senderAddress: deviceId,\n recipientAddress: state.gatewayId,\n conversationLabel: `灵爻 DM with ${deviceId}`,\n rawBody: message.content,\n messageId: message.id,\n timestamp: message.timestamp,\n bodyForAgent: message.content,\n provider: 'lingyao',\n surface: 'lingyao',\n extraContext: {\n messageType: message.type === 'sync_diary' ? 'diary' : 'memory',\n metadata: message.metadata || {},\n },\n deliver: async (payload) => {\n const sent = this.sendNotification(state.accountId, deviceId, {\n type: 'agent_reply',\n text: payload.text,\n mediaUrl: payload.mediaUrl,\n mediaUrls: payload.mediaUrls,\n });\n if (!sent) {\n this.runtime.logger.warn(\n `[${state.accountId}] Failed to deliver Agent reply to ${deviceId}: WS not connected`\n );\n }\n },\n onRecordError: (err: unknown) => {\n this.runtime.logger.error(`[${state.accountId}] Failed to record inbound session`, err);\n },\n onDispatchError: (err: unknown, info: { kind: string }) => {\n this.runtime.logger.error(`[${state.accountId}] Dispatch error`, { err, kind: info.kind });\n },\n });\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] dispatchInboundDirectDmWithRuntime failed`, error);\n throw error;\n }\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\n // 如果是因为 Token 无效导致的断开,触发重新注册和重连\n if (event.code === 1008) {\n this.runtime.logger.warn(`[${state.accountId}] Token invalid (1008). Forcing re-registration...`);\n this.handleInvalidToken(state).catch(err => {\n this.runtime.logger.error(`[${state.accountId}] Failed to re-register after 1008`, err);\n });\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 case 'fatal_handshake':\n if (event.reason === 'http_404') {\n void this.handleWsHandshake404(state);\n }\n break;\n case 'pairing_completed':\n this.handlePairingCompleted(state, event);\n break;\n }\n };\n }\n\n /**\n * Handle pairing completed event from WS — auto-bind device.\n */\n private async handlePairingCompleted(state: AccountState, event: any): Promise<void> {\n const { deviceId, deviceInfo } = event;\n this.runtime.logger.info(`[${state.accountId}] Pairing completed, auto-binding device`, { deviceId, deviceInfo });\n\n try {\n await state.accountManager.addDevice(deviceId, {\n name: deviceInfo?.name ?? deviceId,\n platform: deviceInfo?.platform ?? 'harmonyos',\n version: deviceInfo?.version ?? '',\n });\n this.runtime.logger.info(`[${state.accountId}] Device auto-bound: ${deviceId}`);\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] Failed to auto-bind device: ${deviceId}`, error);\n }\n }\n\n /**\n * After HTTP 404 on WebSocket upgrade: clear local tokens, re-register once, reconnect.\n * Does not fix wrong server URL or permanently deleted gateway rows (user must fix config).\n */\n private async handleWsHandshake404(state: AccountState): Promise<void> {\n if (state.wsHandshake404RecoveryAttempted) {\n this.runtime.logger.error(\n `[${state.accountId}] Lingyao WebSocket still failing after one recovery attempt. ` +\n `Check that wss://…/lyoc/gateway/ws is deployed; if the gateway was removed, delete ` +\n `\\`channels.lingyao.accounts.${state.accountId}.gatewayId\\` or use a new account id, then restart.`\n );\n return;\n }\n state.wsHandshake404RecoveryAttempted = true;\n\n const { httpClient, wsClient, accountId } = state;\n if (!httpClient || !wsClient) {\n return;\n }\n\n this.runtime.logger.info(`[${accountId}] WS HTTP 404 — clearing local session and re-registering...`);\n\n try {\n await httpClient.clearLocalSession();\n const response = await httpClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n wsClient.updateToken(response.gatewayToken);\n await wsClient.connect();\n this.runtime.logger.info(`[${accountId}] Re-register OK; WebSocket reconnect issued.`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes('already registered')) {\n this.runtime.logger.error(\n `[${accountId}] Re-register failed: gateway still registered on server but local session was cleared. ` +\n `Remove or change \\`gatewayId\\` under this account, or reset the gateway on lingyao.live, then restart OpenClaw.`,\n error\n );\n } else {\n this.runtime.logger.error(`[${accountId}] WS 404 recovery (clear + register) failed`, error);\n }\n }\n }\n\n /**\n * Handle invalid token by re-registering the gateway and reconnecting WS\n */\n private async handleInvalidToken(state: AccountState): Promise<void> {\n if (!state.httpClient || !state.wsClient) {\n return;\n }\n\n try {\n this.runtime.logger.info(`[${state.accountId}] Requesting new gateway token...`);\n // 强制重新注册以获取新 token\n const response = await state.httpClient.register({\n websocket: true,\n compression: false,\n maxMessageSize: 1048576,\n });\n\n this.runtime.logger.info(`[${state.accountId}] Obtained new token. Reconnecting WS...`);\n // 更新 WS 客户端的 token 并重新连接\n state.wsClient.updateToken(response.gatewayToken);\n await state.wsClient.connect();\n } catch (error) {\n this.runtime.logger.error(`[${state.accountId}] Failed to handle invalid token`, error);\n // 可以在此处接入 errorHandler 以实现更高级的退避重试\n state.errorHandler.handleError(error as Error);\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 * WebSocket URL for the OpenClaw gateway client (must use wss:// for TLS).\n * The `ws` package accepts https URLs in some builds, but wss:// avoids ambiguity.\n */\n/** Production api.lingyao.live exposes Gateway WS under `/lyoc` (not `/v1`). */\nexport function getLingyaoGatewayWsUrl(): string {\n return LINGYAO_SERVER_URL.replace(/^https:/i, 'wss:') + '/lyoc/gateway/ws';\n}\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?: \"pairing\" | \"allowlist\" | \"open\";\n allowFrom?: string[];\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n gatewayId?: string;\n /**\n * WebSocket `gateway_heartbeat` 间隔(毫秒)。默认使用注册接口返回的 `heartbeatInterval`。\n * 建议 5000–55000,须小于中继 `heartbeatTimeout`(常见 60s)。\n */\n websocketHeartbeatIntervalMs?: number;\n}\n\n/**\n * Channel configuration\n */\nexport interface LingyaoConfig {\n enabled: boolean;\n maxOfflineMessages?: number;\n tokenExpiryDays?: number;\n dmPolicy?: \"pairing\" | \"allowlist\" | \"open\";\n allowFrom?: string[];\n /** 顶层默认,可被 `accounts.<id>` 覆盖 */\n websocketHeartbeatIntervalMs?: number;\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","import type { ResolvedAccount } from './adapters/config.js';\nimport type { ServerHttpClient } from './server-client.js';\n\n/** 中继通常 60s 内无心跳即判离线;WS 心跳间隔需明显小于该值 */\nconst MIN_MS = 5_000;\nconst MAX_MS = 55_000;\nconst FALLBACK_MS = 30_000;\n\n/**\n * 灵爻 Gateway WebSocket 心跳间隔:优先用户配置,其次 HTTP 注册返回的 `serverConfig.heartbeatInterval`,并钳制在安全范围。\n */\nexport function resolveLingyaoWsHeartbeatIntervalMs(\n account: ResolvedAccount,\n httpClient: ServerHttpClient\n): number {\n const fromServer = httpClient.getHeartbeatIntervalMs();\n const fromCfg = account.rawConfig?.websocketHeartbeatIntervalMs;\n let ms =\n typeof fromCfg === 'number' && Number.isFinite(fromCfg) && fromCfg > 0 ? fromCfg : fromServer;\n if (!Number.isFinite(ms) || ms <= 0) {\n ms = FALLBACK_MS;\n }\n return Math.max(MIN_MS, Math.min(ms, MAX_MS));\n}\n\n/**\n * 非 OpenClaw 多账户路径(如旧版 `LingyaoChannel`)仅根据 HTTP 客户端解析间隔。\n */\nexport function resolveLingyaoWsHeartbeatIntervalMsFromHttp(httpClient: ServerHttpClient): number {\n const ms = httpClient.getHeartbeatIntervalMs();\n const base = Number.isFinite(ms) && ms > 0 ? ms : FALLBACK_MS;\n return Math.max(MIN_MS, Math.min(base, MAX_MS));\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 // Public API (api.lingyao.live) serves gateway HTTP under /lyoc; local relay also accepts /lyoc (see server getApiPathSuffix).\n apiBase: serverConfig.apiBase || '/lyoc',\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 } else if (status === 404) {\n throw new Error(\n 'Lingyao gateway register returned 404. Check server URL and /lyoc/gateway/register; ' +\n 'the gatewayId may be invalid or the API may not be deployed on this host.'\n );\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 * HTTP 注册/恢复后由 `serverConfig.heartbeatInterval` 写入(毫秒),用于与 WebSocket `gateway_heartbeat` 对齐。\n */\n getHeartbeatIntervalMs(): number {\n return this.heartbeatInterval > 0 ? this.heartbeatInterval : 30000;\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 * Clear local gateway token/session (storage + in-memory). Used when WS handshake\n * fails with 404 or when forcing re-registration with the same gatewayId.\n */\n async clearLocalSession(): Promise<void> {\n this.stopHeartbeat();\n this.gatewayToken = null;\n this.webhookSecret = null;\n this.tokenExpiresAt = 0;\n this.isRegistered = false;\n\n const keys = ['gatewayToken', 'webhookSecret', 'tokenExpiresAt', 'serverConfig'] as const;\n for (const k of keys) {\n try {\n await this.runtime.storage.delete(this.storageKey(k));\n } catch (e) {\n this.runtime.logger.warn(`Failed to delete storage key ${k}`, e);\n }\n }\n\n this.runtime.logger.info('Cleared local Lingyao gateway session');\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 消息类型(与 `lingyao/server/src/server.ts` 中 Gateway 协议一致)\n */\nexport enum WSMessageType {\n // Gateway → 服务器\n GATEWAY_REGISTER = \"gateway_register\",\n GATEWAY_HEARTBEAT = \"gateway_heartbeat\",\n GATEWAY_SEND_MESSAGE = \"gateway_send_message\",\n\n // 服务器 → Gateway\n GATEWAY_REGISTERED = \"gateway_registered\",\n GATEWAY_HEARTBEAT_ACK = \"gateway_heartbeat_ack\",\n MESSAGE_DELIVERED = \"message_delivered\",\n MESSAGE_FAILED = \"message_failed\",\n APP_MESSAGE = \"app_message\",\n DEVICE_ONLINE = \"device_online\",\n PAIRING_COMPLETED = \"pairing_completed\",\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.GATEWAY_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.GATEWAY_HEARTBEAT;\n payload: {\n timestamp: number;\n status: \"online\";\n };\n}\n\n/**\n * 发送消息\n */\nexport interface SendMessage extends WSMessage {\n type: WSMessageType.GATEWAY_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: \"fatal_handshake\"; reason: \"http_404\" }\n | { type: \"message\"; message: WSMessage }\n | { type: \"appMessage\"; deviceId: string; message: AppMessage[\"payload\"][\"message\"] }\n | { type: \"pairing_completed\"; deviceId: string; deviceInfo: { name: string; platform: string; version: string }; sessionId: string };\n\n/** True when the `ws` library reports HTTP 404 on the WebSocket upgrade (invalid path or gateway rejected at edge). */\nexport function isWebsocketUpgradeNotFoundError(message: string): boolean {\n return /Unexpected server response:\\s*404/i.test(message) || /\\b404\\b/.test(message);\n}\n\n/**\n * 将服务端类型映射到本客户端 handler 使用的 key(与 {@link WSMessageType} 一致)。\n * 仍接受旧版短名 `registered` / `heartbeat_ack`,便于与历史部署混连。\n */\nexport function normalizeIncomingGatewayMessageType(type: string): string {\n switch (type) {\n case \"registered\":\n return WSMessageType.GATEWAY_REGISTERED;\n case \"heartbeat_ack\":\n return WSMessageType.GATEWAY_HEARTBEAT_ACK;\n case \"gateway_registered\":\n return WSMessageType.GATEWAY_REGISTERED;\n case \"gateway_heartbeat_ack\":\n return WSMessageType.GATEWAY_HEARTBEAT_ACK;\n default:\n return type;\n }\n}\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 /** When set, close handler will not schedule reconnect (e.g. HTTP 404 on upgrade). */\n private suppressReconnect = false;\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.GATEWAY_REGISTERED, this.handleRegistered.bind(this));\n this.registerMessageHandler(WSMessageType.GATEWAY_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.DEVICE_ONLINE, this.handleDeviceOnline.bind(this));\n this.registerMessageHandler(WSMessageType.PAIRING_COMPLETED, this.handlePairingCompleted.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.suppressReconnect = false;\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 const rawType = String(message.type);\n const handlerKey = normalizeIncomingGatewayMessageType(rawType);\n this.logger.debug(\"Received message from server\", { type: rawType, handlerKey });\n\n const handler = this.messageHandlers.get(handlerKey);\n if (handler) {\n handler(message);\n } else {\n this.logger.warn(\"No handler for message type\", { type: rawType });\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 const msg = error?.message ?? String(error);\n if (isWebsocketUpgradeNotFoundError(msg)) {\n this.suppressReconnect = true;\n this.logger.error(\n \"WebSocket handshake failed with HTTP 404 — stopping reconnect loop. \" +\n \"If the gateway was removed server-side, remove `gatewayId` from channels.lingyao.accounts.* \" +\n \"or use a new account id; if the path is wrong, verify wss://…/lyoc/gateway/ws is deployed on api.lingyao.live.\",\n { gatewayId: this.config.gatewayId, message: msg }\n );\n } else {\n this.logger.error(\"WebSocket error\", error);\n }\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 // 1008 表示 Token 无效,不应继续使用原 Token 重连,交给外部重新注册\n if (code === 1008) {\n this.logger.error(\"WebSocket closed with 1008 (Invalid Token). Stopping reconnect loop.\");\n return;\n }\n\n if (this.suppressReconnect) {\n this.suppressReconnect = false;\n this.emitEvent({ type: \"fatal_handshake\", reason: \"http_404\" });\n return;\n }\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.GATEWAY_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.GATEWAY_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.GATEWAY_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 handleDeviceOnline(message: WSMessage): void {\n this.logger.debug(\"Device online (server push)\", {\n payload: message.payload,\n });\n }\n\n /**\n * 处理配对完成通知(来自 lingyao.live 服务器)\n */\n private handlePairingCompleted(message: WSMessage): void {\n const payload = message.payload;\n this.logger.info(\"Pairing completed\", {\n deviceId: payload?.deviceId,\n sessionId: payload?.sessionId,\n });\n\n if (this.config.eventHandler) {\n this.config.eventHandler({\n type: \"pairing_completed\",\n deviceId: payload?.deviceId,\n deviceInfo: payload?.deviceInfo,\n sessionId: payload?.sessionId,\n });\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 * 更新 WebSocket 连接使用的 token\n */\n updateToken(token: string): void {\n this.config.token = token;\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 * Manually add a device by deviceId (user-initiated pairing).\n * No pairing code or deviceToken required — the user explicitly\n * trusts this device from the OpenClaw CLI.\n */\n async addDevice(deviceId: string, deviceInfo: DeviceInfo): Promise<LingyaoAccount> {\n const existing = this.accounts.get(deviceId);\n if (existing) {\n // Already tracked — reactivate if revoked\n existing.status = 'active';\n existing.deviceInfo = deviceInfo;\n existing.lastSeenAt = Date.now();\n await this.saveAccounts();\n this.runtime.logger.info(`Device re-activated: ${deviceId} (${deviceInfo.name})`);\n return existing;\n }\n\n const now = Date.now();\n const account: LingyaoAccount = {\n deviceId,\n deviceInfo,\n deviceToken: {\n deviceId,\n pairingId: `manual_${now}`,\n token: '',\n secret: '',\n expiresAt: 0,\n deviceInfo,\n },\n pairedAt: now,\n lastSeenAt: now,\n status: 'active',\n };\n\n this.accounts.set(deviceId, account);\n await this.saveAccounts();\n\n this.runtime.logger.info(`Device added: ${deviceId} (${deviceInfo.name})`);\n return account;\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 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 const key = `${data.name}_${Date.now()}_${Math.random().toString(36).substring(7)}`;\n this.metrics.set(key, data);\n\n // 限制历史记录数量,避免内存泄漏\n if (this.metrics.size > 10000) {\n // 优化:Map 保持插入顺序,最旧的数据在最前面,直接通过迭代器删除前 10%\n let count = 0;\n const deleteCount = Math.floor(this.metrics.size * 0.1);\n for (const k of this.metrics.keys()) {\n this.metrics.delete(k);\n if (++count >= deleteCount) break;\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 private cleanupTimer: NodeJS.Timeout | null = null;\n private errorTimestamps: Map<string, number[]> = new Map();\n\n constructor(runtime: LingyaoRuntime) {\n this.runtime = runtime;\n\n // 每 5 分钟执行一次统一的错误清理,替代为每个错误单独创建 setTimeout\n this.cleanupTimer = setInterval(() => this.cleanupOldErrors(), 5 * 60 * 1000);\n if (this.cleanupTimer.unref) {\n this.cleanupTimer.unref(); // 允许进程正常退出\n }\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 public destroy(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n\n private cleanupOldErrors(): void {\n const now = Date.now();\n for (const [code, timestamps] of this.errorTimestamps.entries()) {\n const thresholdConfig = this.errorThresholds.get(code);\n const windowMs = thresholdConfig?.window || 3600000; // 默认 1 小时\n \n // 保留在窗口期内的时间戳\n const validTimestamps = timestamps.filter(ts => now - ts <= windowMs);\n \n if (validTimestamps.length === 0) {\n this.errorTimestamps.delete(code);\n this.errorCounts.delete(code);\n // 如果需要,也可以选择保留 lastErrors 供追溯,或者一起删除\n } else {\n this.errorTimestamps.set(code, validTimestamps);\n this.errorCounts.set(code, validTimestamps.length);\n }\n }\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 timestamp = Date.now();\n\n // 先清理该类型的过期错误,确保计数准确\n const thresholdConfig = this.errorThresholds.get(key);\n const windowMs = thresholdConfig?.window || 3600000;\n \n let timestamps = this.errorTimestamps.get(key) || [];\n timestamps = timestamps.filter(ts => timestamp - ts <= windowMs);\n \n // 记录新的时间戳\n timestamps.push(timestamp);\n this.errorTimestamps.set(key, timestamps);\n\n // 更新当前时间窗口内的错误计数\n this.errorCounts.set(key, timestamps.length);\n\n this.lastErrors.set(key, {\n error,\n timestamp,\n });\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","import { z } from \"zod\";\nimport type { LingyaoConfig } from \"./types.js\";\n\n/**\n * OpenClaw-standard DM policy values.\n */\nexport const lingyaoDmPolicySchema = z.enum([\"pairing\", \"allowlist\", \"open\"]);\n\nconst allowFromSchema = z.array(z.string()).optional();\n\nexport const lingyaoAccountConfigSchema = z.object({\n enabled: z.boolean().optional(),\n dmPolicy: lingyaoDmPolicySchema.optional(),\n allowFrom: allowFromSchema,\n websocketHeartbeatIntervalMs: z.number().int().min(5000).max(120000).optional(),\n});\n\n/**\n * Zod schema for Lingyao channel configuration.\n *\n * Lingyao supports both top-level single-account config and\n * `channels.lingyao.accounts.<id>` multi-account config. Account entries inherit\n * unspecified values from the top-level section.\n */\nexport const lingyaoConfigSchema = z.object({\n enabled: z.boolean().default(true),\n dmPolicy: lingyaoDmPolicySchema.optional().default(\"pairing\"),\n allowFrom: allowFromSchema.default([]),\n websocketHeartbeatIntervalMs: z.number().int().min(5000).max(120000).optional(),\n defaultAccount: z.string().min(1).optional(),\n accounts: z.record(lingyaoAccountConfigSchema).optional(),\n});\n\nexport type LingyaoConfigSchema = z.infer<typeof lingyaoConfigSchema>;\nexport const lingyaoChannelConfigSchema = {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n enabled: {\n type: \"boolean\",\n default: true,\n },\n dmPolicy: {\n type: \"string\",\n enum: [\"pairing\", \"allowlist\", \"open\"],\n default: \"pairing\",\n },\n allowFrom: {\n type: \"array\",\n items: { type: \"string\" },\n default: [],\n },\n defaultAccount: {\n type: \"string\",\n },\n websocketHeartbeatIntervalMs: {\n type: \"integer\",\n minimum: 5000,\n maximum: 120000,\n description:\n \"WebSocket gateway_heartbeat interval in ms (default: server register response). Use 5000–55000 for typical relay timeout.\",\n },\n accounts: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n enabled: {\n type: \"boolean\",\n default: true,\n },\n dmPolicy: {\n type: \"string\",\n enum: [\"pairing\", \"allowlist\", \"open\"],\n },\n allowFrom: {\n type: \"array\",\n items: { type: \"string\" },\n },\n websocketHeartbeatIntervalMs: {\n type: \"integer\",\n minimum: 5000,\n maximum: 120000,\n },\n },\n default: {},\n },\n },\n },\n} as const;\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 dmPolicy: \"pairing\",\n allowFrom: [],\n };\n}\n","import type { PluginRuntime } from 'openclaw/plugin-sdk';\n\nimport { initializeLingyaoRuntime } from './api.js';\n\nexport function setLingyaoRuntime(runtime: PluginRuntime): void {\n initializeLingyaoRuntime(runtime);\n}\n"],"mappings":"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","names":["getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","getOrchestrator","orchestrator","MessageType","capabilities"]}
|