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:
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user