9b4a25799f
Replace fixed ackText with a rule-based AckProvider that picks response templates by message type and intent (translate, summary, rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync, zero I/O, auto-falls back to config.ackText on any error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
97 lines
3.0 KiB
JavaScript
97 lines
3.0 KiB
JavaScript
const PUBLIC_PAGE_LIMIT_KEY = 'public_page_limit';
|
|
|
|
function asPositiveInteger(value, fallback) {
|
|
const parsed = Number(value);
|
|
if (!Number.isFinite(parsed) || parsed < 1) return fallback;
|
|
return Math.floor(parsed);
|
|
}
|
|
|
|
async function ensureConfigTable(pool) {
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS mindspace_config (
|
|
\`key\` VARCHAR(64) PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
description VARCHAR(255) NULL,
|
|
updated_at BIGINT NOT NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
`);
|
|
}
|
|
|
|
export function defaultMindSpaceConfig(env = process.env) {
|
|
return {
|
|
publicPageLimit: asPositiveInteger(env.MINDSPACE_FREE_PUBLIC_PAGE_LIMIT ?? 5, 5),
|
|
};
|
|
}
|
|
|
|
async function readConfigRows(pool) {
|
|
const [rows] = await pool.query(
|
|
'SELECT `key`, value FROM mindspace_config',
|
|
);
|
|
return rows;
|
|
}
|
|
|
|
export async function ensureMindSpaceConfig(pool, { env = process.env, seedDefault = true } = {}) {
|
|
await ensureConfigTable(pool);
|
|
if (!seedDefault) return;
|
|
const [rows] = await pool.query('SELECT COUNT(*) AS count FROM mindspace_config');
|
|
if (Number(rows[0]?.count ?? 0) > 0) return;
|
|
|
|
const now = Date.now();
|
|
const defaults = defaultMindSpaceConfig(env);
|
|
await pool.query(
|
|
`INSERT INTO mindspace_config (\`key\`, value, description, updated_at)
|
|
VALUES (?, ?, ?, ?)`,
|
|
[PUBLIC_PAGE_LIMIT_KEY, String(defaults.publicPageLimit), '公开页面数量上限', now],
|
|
);
|
|
}
|
|
|
|
export async function loadMindSpaceConfig(pool, { env = process.env } = {}) {
|
|
const config = defaultMindSpaceConfig(env);
|
|
try {
|
|
const rows = await readConfigRows(pool);
|
|
for (const row of rows) {
|
|
if (row.key === PUBLIC_PAGE_LIMIT_KEY) {
|
|
config.publicPageLimit = asPositiveInteger(row.value, config.publicPageLimit);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error?.code === 'ER_NO_SUCH_TABLE') return config;
|
|
throw error;
|
|
}
|
|
return config;
|
|
}
|
|
|
|
export async function updateMindSpaceConfig(pool, patch, { env = process.env } = {}) {
|
|
await ensureConfigTable(pool);
|
|
const updates = [];
|
|
if (patch?.publicPageLimit !== undefined) {
|
|
const publicPageLimit = asPositiveInteger(patch.publicPageLimit, null);
|
|
if (!publicPageLimit) {
|
|
throw Object.assign(new Error('公开页面数量上限必须是大于 0 的整数'), {
|
|
code: 'invalid_mindspace_config',
|
|
});
|
|
}
|
|
updates.push([PUBLIC_PAGE_LIMIT_KEY, String(publicPageLimit), '公开页面数量上限']);
|
|
}
|
|
|
|
if (updates.length === 0) return loadMindSpaceConfig(pool, { env });
|
|
|
|
const now = Date.now();
|
|
for (const [key, value, description] of updates) {
|
|
await pool.query(
|
|
`INSERT INTO mindspace_config (\`key\`, value, description, updated_at)
|
|
VALUES (?, ?, ?, ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
value = VALUES(value),
|
|
description = VALUES(description),
|
|
updated_at = VALUES(updated_at)`,
|
|
[key, value, description, now],
|
|
);
|
|
}
|
|
return loadMindSpaceConfig(pool, { env });
|
|
}
|
|
|
|
export const mindspaceConfigInternals = {
|
|
PUBLIC_PAGE_LIMIT_KEY,
|
|
};
|