Add smart ACK provider for WeChat MP replies

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>
This commit is contained in:
john
2026-06-26 15:19:03 +08:00
parent 9ed4fd48d7
commit 9b4a25799f
162 changed files with 17276 additions and 2054 deletions
+49 -67
View File
@@ -42,16 +42,6 @@ export type AdminSummary = {
};
};
export type LlmKey = {
id: string;
name: string;
provider: string;
model?: string;
models?: string[];
isSelected: boolean;
createdAt?: string;
};
export type LedgerEntry = {
id: string;
userId: string;
@@ -160,6 +150,33 @@ export type WechatDeliveryLog = {
digestType: string | null;
};
export type WechatWebNotification = {
id: string;
userId: string;
username: string;
displayName: string;
channel: string;
notificationType: string;
title: string;
body: string;
status: string;
readAt: number | null;
createdAt: number;
updatedAt: number;
};
export type CreateWechatNotificationPayload = {
userId?: string;
userIds?: string[];
audience?: 'all';
allUsers?: boolean;
title: string;
body: string;
notificationType?: string;
channel?: 'web' | 'wechat';
channels?: Array<'web' | 'wechat'>;
};
// ─── Summary ──────────────────────────────────────────────────────────────────
export async function fetchAdminSummary() {
@@ -269,6 +286,28 @@ export async function fetchWechatDeliveries(params: { status?: string; limit?: n
return adminFetch<{ deliveries: WechatDeliveryLog[] }>(`/admin-api/wechat/deliveries?${q}`);
}
export async function fetchWechatWebNotifications(params: { status?: string; limit?: number } = {}) {
const q = new URLSearchParams();
if (params.status) q.set('status', params.status);
if (params.limit) q.set('limit', String(params.limit));
return adminFetch<{ notifications: WechatWebNotification[] }>(
`/admin-api/wechat/web-notifications?${q}`,
);
}
export async function createWechatWebNotification(body: CreateWechatNotificationPayload) {
return adminFetch<{
ok: boolean;
created: number;
wechatSent: number;
wechatFailures: Array<{ userId: string; message: string }>;
targets: number;
}>('/admin-api/wechat/web-notifications', {
method: 'POST',
body: JSON.stringify(body),
});
}
export async function clearWechatRoute(userId: string) {
return adminFetch<{ ok: boolean; deleted: number; openidMasked: string }>(
`/admin-api/wechat/users/${userId}/route/clear`,
@@ -285,60 +324,3 @@ export async function resumeWechatDigest(id: string) {
method: 'POST',
});
}
// ─── LLM Providers ───────────────────────────────────────────────────────────
export async function fetchLlmKeys() {
return adminFetch<{ keys: LlmKey[] }>('/admin-api/llm-providers/keys');
}
export async function createLlmKey(body: {
name: string;
provider: string;
apiKey: string;
model?: string;
models?: string;
baseUrl?: string;
}) {
return adminFetch<{ key: LlmKey }>('/admin-api/llm-providers/keys', {
method: 'POST',
body: JSON.stringify(body),
});
}
export async function patchLlmKey(keyId: string, patch: { name?: string; apiKey?: string; model?: string }) {
return adminFetch<{ key: LlmKey }>(`/admin-api/llm-providers/keys/${keyId}`, {
method: 'PATCH',
body: JSON.stringify(patch),
});
}
export async function selectLlmKey(keyId: string) {
return adminFetch(`/admin-api/llm-providers/keys/${keyId}/select`, { method: 'POST' });
}
export async function deleteLlmKey(keyId: string) {
return adminFetch(`/admin-api/llm-providers/keys/${keyId}`, { method: 'DELETE' });
}
export async function testLlmKey(keyId: string) {
return adminFetch<{ ok: boolean; model?: string; error?: string }>(
`/admin-api/llm-providers/keys/${keyId}/test`,
{ method: 'POST' },
);
}
export async function fetchLlmGlobal() {
return adminFetch<{ settings: { model: string | null } }>('/admin-api/llm-providers/global');
}
export async function putLlmGlobal(model: string) {
return adminFetch('/admin-api/llm-providers/global', {
method: 'PUT',
body: JSON.stringify({ model }),
});
}
export async function syncLlmProviders() {
return adminFetch<{ synced: number }>('/admin-api/llm-providers/sync', { method: 'POST' });
}