const CONFIG_TABLE = 'h5_wechat_cursor_executor_config'; const CONFIG_SCOPE = 'global'; const POLICY_SOURCE_DEFAULT = 'default'; const POLICY_SOURCE_ADMIN_DB = 'admin-db'; const DEFAULT_INTENT_ALLOWLIST = Object.freeze(['page.generate']); const DEFAULT_CHANNEL_ALLOWLIST = Object.freeze(['h5', 'wechat_mp']); export const CURSOR_EXECUTOR_CHANNEL = Object.freeze({ H5: 'h5', WECHAT_MP: 'wechat_mp', }); function defaultConfigShape() { return { enabled: false, userAllowlist: [], channelAllowlist: [...DEFAULT_CHANNEL_ALLOWLIST], intentAllowlist: [...DEFAULT_INTENT_ALLOWLIST], fallbackToDeepseek: true, meta: { notes: '', }, }; } function normalizeBoolean(value, fallback = false) { if (value == null || value === '') return fallback; if (typeof value === 'boolean') return value; const normalized = String(value).trim().toLowerCase(); if (['1', 'true', 'yes', 'on'].includes(normalized)) return true; if (['0', 'false', 'no', 'off'].includes(normalized)) return false; return fallback; } function normalizeStringList(value) { if (!Array.isArray(value)) { return String(value ?? '') .split(/[\n,]+/) .map((item) => item.trim()) .filter(Boolean); } return value.map((item) => String(item ?? '').trim()).filter(Boolean); } function cloneConfig(config = null) { return structuredClone?.(config ?? defaultConfigShape()) ?? JSON.parse(JSON.stringify(config ?? defaultConfigShape())); } function parseJsonLike(value, fallback) { if (value == null || value === '') return fallback; if (typeof value === 'string') { try { return JSON.parse(value); } catch { return fallback; } } if (typeof value === 'object') return value; return fallback; } function mergePatch(currentConfig, patch = {}) { const next = cloneConfig(currentConfig); if ('enabled' in patch) next.enabled = normalizeBoolean(patch.enabled, false); if ('userAllowlist' in patch) next.userAllowlist = normalizeStringList(patch.userAllowlist); if ('channelAllowlist' in patch) { const channels = normalizeStringList(patch.channelAllowlist); next.channelAllowlist = channels.length ? channels : [...DEFAULT_CHANNEL_ALLOWLIST]; } if ('intentAllowlist' in patch) { const intents = normalizeStringList(patch.intentAllowlist); next.intentAllowlist = intents.length ? intents : [...DEFAULT_INTENT_ALLOWLIST]; } if ('fallbackToDeepseek' in patch) { next.fallbackToDeepseek = normalizeBoolean(patch.fallbackToDeepseek, true); } if (patch?.meta && typeof patch.meta.notes === 'string') { next.meta.notes = patch.meta.notes; } return next; } function flattenPolicy(config, source) { const intentAllowlist = normalizeStringList(config.intentAllowlist); const channelAllowlist = normalizeStringList(config.channelAllowlist); return { source, enabled: Boolean(config.enabled), userAllowlist: normalizeStringList(config.userAllowlist), channelAllowlist: channelAllowlist.length ? channelAllowlist : [...DEFAULT_CHANNEL_ALLOWLIST], intentAllowlist: intentAllowlist.length ? intentAllowlist : [...DEFAULT_INTENT_ALLOWLIST], fallbackToDeepseek: config.fallbackToDeepseek !== false, }; } export function isChannelAllowedByCursorPolicy(channel, policy) { const allowlist = normalizeStringList(policy?.channelAllowlist ?? DEFAULT_CHANNEL_ALLOWLIST) .map((item) => item.toLowerCase()); if (allowlist.length === 0) return false; const normalized = String(channel ?? '').trim().toLowerCase(); if (!normalized) return false; return allowlist.includes(normalized); } export function isUserAllowedByWechatCursorPolicy(user, policy) { if (!policy?.enabled) return false; const allowlist = normalizeStringList(policy.userAllowlist).map((item) => item.toLowerCase()); if (allowlist.length === 0) return false; if (allowlist.includes('*')) return true; const identities = [ user?.userId, user?.id, user?.username, user?.slug, user?.displayName, user?.nickname, ] .map((value) => String(value ?? '').trim().toLowerCase()) .filter(Boolean); return identities.some((identity) => allowlist.includes(identity)); } export function isIntentAllowedByWechatCursorPolicy(intentKind, policy) { const allowlist = (policy?.intentAllowlist ?? DEFAULT_INTENT_ALLOWLIST) .map((item) => String(item ?? '').trim()) .filter(Boolean); const normalized = String(intentKind ?? '').trim(); if (!normalized) return false; return allowlist.includes(normalized); } async function ensureConfigTable(pool) { await pool.query(` CREATE TABLE IF NOT EXISTS ${CONFIG_TABLE} ( config_scope VARCHAR(32) PRIMARY KEY, config_json JSON NOT NULL, updated_by CHAR(36) NULL, updated_at BIGINT NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `); } async function loadStoredState(pool) { await ensureConfigTable(pool); const [rows] = await pool.query( `SELECT config_json, updated_by, updated_at FROM ${CONFIG_TABLE} WHERE config_scope = ? LIMIT 1`, [CONFIG_SCOPE], ); const row = rows[0]; if (!row) return null; const parsed = parseJsonLike(row.config_json, {}); return { config: mergePatch(defaultConfigShape(), parsed), updatedAt: Number(row.updated_at ?? 0) || null, updatedBy: row.updated_by ?? null, }; } export function createWechatCursorExecutorAdminConfigService(pool) { async function loadEffectiveConfig() { const stored = await loadStoredState(pool); if (stored) { return { config: cloneConfig(stored.config), updatedAt: stored.updatedAt, updatedBy: stored.updatedBy, source: POLICY_SOURCE_ADMIN_DB, }; } return { config: defaultConfigShape(), updatedAt: null, updatedBy: null, source: POLICY_SOURCE_DEFAULT, }; } return { async getAdminConfig() { const state = await loadEffectiveConfig(); return { config: state.config, updatedAt: state.updatedAt, updatedBy: state.updatedBy, source: state.source, }; }, async updateAdminConfig(patch = {}, { updatedBy = null } = {}) { const stored = await loadStoredState(pool); const base = stored?.config ?? defaultConfigShape(); const nextConfig = mergePatch(base, patch.config ?? patch); await ensureConfigTable(pool); const now = Date.now(); await pool.query( `INSERT INTO ${CONFIG_TABLE} (config_scope, config_json, updated_by, updated_at) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE config_json = VALUES(config_json), updated_by = VALUES(updated_by), updated_at = VALUES(updated_at)`, [CONFIG_SCOPE, JSON.stringify(nextConfig), updatedBy, now], ); return this.getAdminConfig(); }, async getRuntimeState() { const state = await loadEffectiveConfig(); const policy = flattenPolicy(state.config, state.source); return { source: state.source, updatedAt: state.updatedAt, updatedBy: state.updatedBy, config: state.config, policy, }; }, async getEffectivePolicy(userId, user = null) { const state = await loadEffectiveConfig(); const policy = flattenPolicy(state.config, state.source); const subject = user ?? { userId }; return { ...policy, userAllowed: isUserAllowedByWechatCursorPolicy(subject, policy), }; }, }; } export const wechatCursorExecutorAdminConfigInternals = { CONFIG_TABLE, defaultConfigShape, mergePatch, flattenPolicy, };