Improve WeChat MP replies and ship MindSpace/H5 production updates.

Add WeChat service account routing with sync acks, connectivity tests, and context isolation; document deploy runbooks; and bundle related MindSpace, voice, Plaza, and server gateway changes for production rollout.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-06-19 23:06:43 +08:00
parent b0f5d6a51c
commit 229805a070
241 changed files with 13190 additions and 902 deletions
+137
View File
@@ -74,6 +74,92 @@ export type UsageRecord = {
createdAt: string;
};
export type WechatAdminSummary = {
config: {
mpEnabled: boolean;
scheduleEnabled: boolean;
reminderWorkerEnabled: boolean;
appId: string | null;
publicBaseUrl: string | null;
bindPath: string | null;
tokenEndpointConfigured: boolean;
customerServiceEndpointConfigured: boolean;
};
counts: {
boundUsers: number;
routes: { total: number; active: number };
recentMessages: Record<string, number>;
digests: Record<string, number>;
recentDeliveries: Record<string, number>;
};
};
export type WechatBinding = {
userId: string;
username: string;
displayName: string;
status: string;
appId: string | null;
openidMasked: string;
nickname: string | null;
avatarUrl: string | null;
lastLoginAt: number;
boundAt: number;
routeId: string | null;
routeStatus: string | null;
agentSessionId: string | null;
routeUpdatedAt: number | null;
};
export type WechatMessage = {
appId: string | null;
openidMasked: string;
msgId: string;
status: string;
agentSessionId: string | null;
createdAt: number;
updatedAt: number;
userId: string | null;
username: string | null;
displayName: string | null;
};
export type WechatDigestSubscription = {
id: string;
userId: string;
username: string;
displayName: string;
digestType: string;
hour: number;
minute: number;
timezone: string;
channel: string;
status: string;
nextRunAt: number;
lastRunAt: number | null;
attempts: number;
lastError: string | null;
sourceText: string | null;
createdAt: number;
updatedAt: number;
};
export type WechatDeliveryLog = {
id: string;
reminderId: string | null;
subscriptionId: string | null;
userId: string;
username: string;
displayName: string;
channel: string;
status: string;
providerMessageId: string | null;
errorCode: string | null;
errorMessage: string | null;
createdAt: number;
digestType: string | null;
};
// ─── Summary ──────────────────────────────────────────────────────────────────
export async function fetchAdminSummary() {
@@ -149,6 +235,57 @@ export async function fetchAdminUsage(params: { page?: number; pageSize?: number
);
}
// ─── WeChat MP ────────────────────────────────────────────────────────────────
export async function fetchWechatSummary() {
return adminFetch<WechatAdminSummary>('/admin-api/wechat/summary');
}
export async function fetchWechatBindings(params: { search?: string; limit?: number } = {}) {
const q = new URLSearchParams();
if (params.search) q.set('search', params.search);
if (params.limit) q.set('limit', String(params.limit));
return adminFetch<{ bindings: WechatBinding[] }>(`/admin-api/wechat/bindings?${q}`);
}
export async function fetchWechatMessages(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<{ messages: WechatMessage[] }>(`/admin-api/wechat/messages?${q}`);
}
export async function fetchWechatDigests(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<{ digests: WechatDigestSubscription[] }>(`/admin-api/wechat/digests?${q}`);
}
export async function fetchWechatDeliveries(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<{ deliveries: WechatDeliveryLog[] }>(`/admin-api/wechat/deliveries?${q}`);
}
export async function clearWechatRoute(userId: string) {
return adminFetch<{ ok: boolean; deleted: number; openidMasked: string }>(
`/admin-api/wechat/users/${userId}/route/clear`,
{ method: 'POST' },
);
}
export async function cancelWechatDigest(id: string) {
return adminFetch<{ ok: boolean }>(`/admin-api/wechat/digests/${id}/cancel`, { method: 'POST' });
}
export async function resumeWechatDigest(id: string) {
return adminFetch<{ ok: boolean; nextRunAt: number }>(`/admin-api/wechat/digests/${id}/resume`, {
method: 'POST',
});
}
// ─── LLM Providers ───────────────────────────────────────────────────────────
export async function fetchLlmKeys() {