diff --git a/server/app.mjs b/server/app.mjs index 9868798..0dcc25c 100644 --- a/server/app.mjs +++ b/server/app.mjs @@ -97,6 +97,7 @@ export function createAdminApp(services) { loadMindSpaceConfig, updateMindSpaceConfig, memoryV2ConfigService, + wechatScheduleLlmConfigService, adminSystemTestService, systemTestAccountService, wordFilterService, @@ -285,7 +286,27 @@ export function createAdminApp(services) { adminApi.get('/wechat/summary', requireAdmin, async (_req, res) => { if (!wechatAdmin) return res.status(503).json({ message: '服务号管理未启用' }); - res.json(await wechatAdmin.getSummary()); + const summary = await wechatAdmin.getSummary(); + const scheduleLlmConfig = wechatScheduleLlmConfigService + ? await wechatScheduleLlmConfigService.getConfig() + : { scheduleLlmEnabled: false }; + res.json({ + ...summary, + config: { + ...summary.config, + scheduleLlmEnabled: scheduleLlmConfig.scheduleLlmEnabled, + }, + }); + }); + + adminApi.patch('/wechat/schedule-llm-config', requireAdmin, async (req, res) => { + if (!wechatScheduleLlmConfigService) { + return res.status(503).json({ message: '服务号提醒 LLM 配置未启用' }); + } + const result = await wechatScheduleLlmConfigService.updateConfig(req.body ?? {}, { + updatedBy: req.currentUser.id, + }); + res.json(result); }); adminApi.get('/mindspace/config', requireAdmin, async (_req, res) => { diff --git a/server/bootstrap.mjs b/server/bootstrap.mjs index e7cd318..b4f7c30 100644 --- a/server/bootstrap.mjs +++ b/server/bootstrap.mjs @@ -29,6 +29,7 @@ export async function bootstrapAdminServices() { updateMindSpaceConfig, } = await importMemind('mindspace-config.mjs'); const { createMemoryV2AdminConfigService } = await importMemind('memory-v2-admin-config.mjs'); + const { createWechatScheduleLlmConfigService } = await importMemind('wechat-schedule-llm-config.mjs'); const { createAdminSystemTestService } = await importMemind('admin-system-tests.mjs'); const { createOpsApi } = await importMemind('admin-routes.mjs'); const { createWordFilterService, ensureWordFilterSchema } = await importMemind('word-filter.mjs'); @@ -88,6 +89,9 @@ export async function bootstrapAdminServices() { const memoryV2ConfigService = createMemoryV2AdminConfigService(pool, { env: process.env, }); + const wechatScheduleLlmConfigService = createWechatScheduleLlmConfigService(pool, { + env: process.env, + }); const adminSystemTestService = createAdminSystemTestService({ pool, userAuth, @@ -136,6 +140,7 @@ export async function bootstrapAdminServices() { loadMindSpaceConfig, updateMindSpaceConfig, memoryV2ConfigService, + wechatScheduleLlmConfigService, adminSystemTestService, systemTestAccountService, wordFilterService, diff --git a/server/index.mjs b/server/index.mjs index e045abd..5f3d003 100644 --- a/server/index.mjs +++ b/server/index.mjs @@ -104,6 +104,7 @@ ready loadMindSpaceConfig, updateMindSpaceConfig, memoryV2ConfigService, + wechatScheduleLlmConfigService, adminSystemTestService, systemTestAccountService, wordFilterService, @@ -125,6 +126,7 @@ ready loadMindSpaceConfig, updateMindSpaceConfig, memoryV2ConfigService, + wechatScheduleLlmConfigService, adminSystemTestService, systemTestAccountService, wordFilterService, diff --git a/src/admin/pages/WechatPage.tsx b/src/admin/pages/WechatPage.tsx index c63e266..23a3625 100644 --- a/src/admin/pages/WechatPage.tsx +++ b/src/admin/pages/WechatPage.tsx @@ -11,6 +11,7 @@ import { listWechatMessages, listWechatWebNotifications, resumeWechatDigest, + updateWechatScheduleLlmConfig, } from '../../api/client'; import type { AdminUserRow, @@ -38,6 +39,7 @@ function safeSummary(summary: WechatAdminSummary | null) { bindPath: null, tokenEndpointConfigured: false, customerServiceEndpointConfigured: false, + scheduleLlmEnabled: false, }, counts: summary?.counts ?? { boundUsers: 0, @@ -88,6 +90,7 @@ export function WechatPage() { const [notifyBody, setNotifyBody] = useState(''); const [notifyType, setNotifyType] = useState('manual'); const [notifyChannels, setNotifyChannels] = useState>(['web']); + const [scheduleLlmEnabled, setScheduleLlmEnabled] = useState(false); const [loading, setLoading] = useState(true); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); @@ -117,6 +120,7 @@ export function WechatPage() { listAdminUsers({ page: 1, pageSize: 200, status: 'active' }), ]); setSummary(nextSummary); + setScheduleLlmEnabled(nextSummary.config.scheduleLlmEnabled ?? false); setBindings(nextBindings); setMessages(nextMessages); setDigests(nextDigests); @@ -224,6 +228,13 @@ export function WechatPage() { } }; + const handleSaveScheduleLlm = async () => { + await runAction(async () => { + await updateWechatScheduleLlmConfig({ scheduleLlmEnabled }); + setNotice(`提醒待办 LLM 已${scheduleLlmEnabled ? '开启' : '关闭'}。`); + }); + }; + return (
@@ -280,7 +291,28 @@ export function WechatPage() {
推送 worker
{summary.config.reminderWorkerEnabled ? '已启用' : '未启用'}
+
+
提醒待办 LLM
+
{summary.config.scheduleLlmEnabled ? '已开启' : '已关闭'}
+
+
+ + +
+

+ 默认关闭。开启后仅在规则未识别出提醒意图时,才调用后台已选中的 LLM 做补充解析;复杂定时提醒仍走原有会话链路。 +

)} diff --git a/src/api/client.ts b/src/api/client.ts index efbcf9d..abfd32c 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -38,6 +38,7 @@ import type { WechatBinding, WechatDeliveryLog, WechatDigestSubscription, + WechatScheduleLlmConfig, WechatMessage, WechatWebNotification, } from '../types'; @@ -254,6 +255,7 @@ export async function getWechatAdminSummary(): Promise { bindPath: summary.config?.bindPath ?? null, tokenEndpointConfigured: summary.config?.tokenEndpointConfigured ?? false, customerServiceEndpointConfigured: summary.config?.customerServiceEndpointConfigured ?? false, + scheduleLlmEnabled: summary.config?.scheduleLlmEnabled ?? false, }, counts: { boundUsers: summary.counts?.boundUsers ?? 0, @@ -268,6 +270,15 @@ export async function getWechatAdminSummary(): Promise { }; } +export async function updateWechatScheduleLlmConfig( + payload: Pick, +): Promise { + return portalFetch('/admin-api/wechat/schedule-llm-config', { + method: 'PATCH', + body: JSON.stringify(payload), + }); +} + export async function getMindSpaceAdminConfig(): Promise { const result = await portalFetch<{ config: MindSpaceAdminConfig }>('/admin-api/mindspace/config'); return result.config; diff --git a/src/types.ts b/src/types.ts index 26f8976..1d35e18 100644 --- a/src/types.ts +++ b/src/types.ts @@ -241,6 +241,7 @@ export type WechatAdminSummary = { bindPath: string | null; tokenEndpointConfigured: boolean; customerServiceEndpointConfigured: boolean; + scheduleLlmEnabled: boolean; }; counts: { boundUsers: number; @@ -251,6 +252,12 @@ export type WechatAdminSummary = { }; }; +export type WechatScheduleLlmConfig = { + scheduleLlmEnabled: boolean; + updatedAt: number | null; + updatedBy: string | null; +}; + export type MindSpaceAdminConfig = { publicPageLimit: number; };