chore: checkpoint admin restore state
This commit is contained in:
@@ -1,18 +1,31 @@
|
||||
import type {
|
||||
AdminDashboardSummary,
|
||||
AdminServiceRestartAction,
|
||||
AdminServiceRestartResult,
|
||||
AdminSubscription,
|
||||
AdminUserRow,
|
||||
AuthStatus,
|
||||
BlockedWord,
|
||||
CapabilityDefinition,
|
||||
CapabilityMap,
|
||||
InsufficientBalanceDetails,
|
||||
LedgerEntry,
|
||||
LlmConnectionTestResult,
|
||||
LlmExecutorBinding,
|
||||
LlmExecutorId,
|
||||
LlmExecutorLaunchPlan,
|
||||
LlmExecutorLaunchState,
|
||||
LlmExecutorRuntime,
|
||||
LlmGlobalSettings,
|
||||
LlmVisionSettings,
|
||||
LlmProviderDefinition,
|
||||
LlmProviderKeyRow,
|
||||
PlanDefinition,
|
||||
PlanSyncResult,
|
||||
PolicyDefinition,
|
||||
PolicyMap,
|
||||
PortalUser,
|
||||
MindSpaceAdminConfig,
|
||||
SkillDefinition,
|
||||
SkillMap,
|
||||
UsageRecord,
|
||||
@@ -21,6 +34,7 @@ import type {
|
||||
WechatDeliveryLog,
|
||||
WechatDigestSubscription,
|
||||
WechatMessage,
|
||||
WechatWebNotification,
|
||||
} from '../types';
|
||||
|
||||
export class ApiError extends Error {
|
||||
@@ -179,6 +193,14 @@ export async function getAdminDashboardSummary(): Promise<AdminDashboardSummary>
|
||||
return result.summary;
|
||||
}
|
||||
|
||||
export async function restartAdminService(
|
||||
action: AdminServiceRestartAction,
|
||||
): Promise<AdminServiceRestartResult> {
|
||||
return portalFetch<AdminServiceRestartResult>(`/admin-api/service-restart/${action}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
export async function listAdminUsage(params?: {
|
||||
userId?: string;
|
||||
page?: number;
|
||||
@@ -241,6 +263,21 @@ export async function getWechatAdminSummary(): Promise<WechatAdminSummary> {
|
||||
};
|
||||
}
|
||||
|
||||
export async function getMindSpaceAdminConfig(): Promise<MindSpaceAdminConfig> {
|
||||
const result = await portalFetch<{ config: MindSpaceAdminConfig }>('/admin-api/mindspace/config');
|
||||
return result.config;
|
||||
}
|
||||
|
||||
export async function updateMindSpaceAdminConfig(
|
||||
payload: Partial<MindSpaceAdminConfig>,
|
||||
): Promise<MindSpaceAdminConfig> {
|
||||
const result = await portalFetch<{ config: MindSpaceAdminConfig }>('/admin-api/mindspace/config', {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
return result.config;
|
||||
}
|
||||
|
||||
export async function listWechatBindings(params?: {
|
||||
search?: string;
|
||||
limit?: number;
|
||||
@@ -293,6 +330,42 @@ export async function listWechatDeliveries(params?: {
|
||||
return result.deliveries ?? [];
|
||||
}
|
||||
|
||||
export async function listWechatWebNotifications(params?: {
|
||||
status?: string;
|
||||
limit?: number;
|
||||
}): Promise<WechatWebNotification[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.status) q.set('status', params.status);
|
||||
if (params?.limit) q.set('limit', String(params.limit));
|
||||
const result = await portalFetch<{ notifications: WechatWebNotification[] }>(
|
||||
`/admin-api/wechat/web-notifications${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.notifications ?? [];
|
||||
}
|
||||
|
||||
export async function createWechatWebNotification(payload: {
|
||||
userId?: string;
|
||||
userIds?: string[];
|
||||
audience?: 'all';
|
||||
allUsers?: boolean;
|
||||
title: string;
|
||||
body: string;
|
||||
notificationType?: string;
|
||||
channel?: 'web' | 'wechat';
|
||||
channels?: Array<'web' | 'wechat'>;
|
||||
}): Promise<{
|
||||
ok: boolean;
|
||||
created: number;
|
||||
wechatSent: number;
|
||||
wechatFailures: Array<{ userId: string; message: string }>;
|
||||
targets: number;
|
||||
}> {
|
||||
return portalFetch('/admin-api/wechat/web-notifications', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function clearWechatRoute(userId: string): Promise<{ ok: boolean; deleted: number }> {
|
||||
return portalFetch(`/admin-api/wechat/users/${userId}/route/clear`, { method: 'POST' });
|
||||
}
|
||||
@@ -328,6 +401,11 @@ export async function listAdminUsers(params?: {
|
||||
return { items: result.users ?? [], total, page: result.page ?? 1, pageSize, totalPages: Math.ceil(total / pageSize) };
|
||||
}
|
||||
|
||||
export async function getAdminUser(userId: string): Promise<PortalUser> {
|
||||
const result = await portalFetch<{ user: PortalUser }>(`/admin-api/users/${userId}`);
|
||||
return result.user;
|
||||
}
|
||||
|
||||
export async function createAdminUser(payload: {
|
||||
username: string;
|
||||
password: string;
|
||||
@@ -351,6 +429,7 @@ export async function updateAdminUser(
|
||||
status: 'active' | 'suspended' | 'disabled';
|
||||
workspaceRoot: string;
|
||||
balanceCents: number;
|
||||
spaceQuotaBytes: number;
|
||||
role: 'user' | 'admin';
|
||||
}>,
|
||||
): Promise<PortalUser> {
|
||||
@@ -593,6 +672,109 @@ export async function getLlmGlobalSettings(): Promise<LlmGlobalSettings> {
|
||||
return result.global;
|
||||
}
|
||||
|
||||
export async function getLlmVisionSettings(): Promise<LlmVisionSettings> {
|
||||
const result = await portalFetch<{ vision: LlmVisionSettings }>('/admin-api/llm-providers/vision');
|
||||
return result.vision;
|
||||
}
|
||||
|
||||
export async function setLlmVisionKey(keyId: string, model: string): Promise<LlmVisionSettings> {
|
||||
const result = await portalFetch<{ vision: LlmVisionSettings }>('/admin-api/llm-providers/vision', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ keyId, model }),
|
||||
});
|
||||
return result.vision;
|
||||
}
|
||||
|
||||
export async function clearLlmVisionKey(): Promise<void> {
|
||||
await portalFetch('/admin-api/llm-providers/vision', { method: 'DELETE' });
|
||||
}
|
||||
|
||||
export async function listLlmExecutorBindings(): Promise<LlmExecutorBinding[]> {
|
||||
const result = await portalFetch<{ bindings: LlmExecutorBinding[] }>(
|
||||
'/admin-api/llm-providers/executor-bindings',
|
||||
);
|
||||
return result.bindings ?? [];
|
||||
}
|
||||
|
||||
export async function setLlmExecutorBinding(
|
||||
executor: LlmExecutorId,
|
||||
payload: { keyId: string | null; model: string; enabled: boolean; purpose?: string },
|
||||
): Promise<LlmExecutorBinding> {
|
||||
const result = await portalFetch<{ binding: LlmExecutorBinding }>(
|
||||
`/admin-api/llm-providers/executor-bindings/${executor}`,
|
||||
{ method: 'PUT', body: JSON.stringify(payload) },
|
||||
);
|
||||
return result.binding;
|
||||
}
|
||||
|
||||
export async function listLlmExecutorRuntime(): Promise<LlmExecutorRuntime[]> {
|
||||
const result = await portalFetch<{ runtimes: LlmExecutorRuntime[] }>(
|
||||
'/admin-api/llm-providers/executor-runtime',
|
||||
);
|
||||
return result.runtimes ?? [];
|
||||
}
|
||||
|
||||
export async function listLlmExecutorLaunchPlans(params: {
|
||||
mode?: 'headless' | 'serve';
|
||||
cwd?: string;
|
||||
instruction?: string;
|
||||
purpose?: string;
|
||||
} = {}): Promise<LlmExecutorLaunchPlan[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.mode) q.set('mode', params.mode);
|
||||
if (params.cwd) q.set('cwd', params.cwd);
|
||||
if (params.instruction) q.set('instruction', params.instruction);
|
||||
if (params.purpose) q.set('purpose', params.purpose);
|
||||
const result = await portalFetch<{ plans: LlmExecutorLaunchPlan[] }>(
|
||||
`/admin-api/llm-providers/executor-launch-plan${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.plans ?? [];
|
||||
}
|
||||
|
||||
export async function listLlmExecutorLaunchStatus(params: {
|
||||
purpose?: string;
|
||||
} = {}): Promise<Array<LlmExecutorLaunchState | null>> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.purpose) q.set('purpose', params.purpose);
|
||||
const result = await portalFetch<{ launches: Array<LlmExecutorLaunchState | null> }>(
|
||||
`/admin-api/llm-providers/executor-launch-status${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.launches ?? [];
|
||||
}
|
||||
|
||||
export async function launchLlmExecutor(
|
||||
executor: LlmExecutorId,
|
||||
payload: { mode?: 'headless' | 'serve'; cwd?: string; instruction?: string; purpose?: string } = {},
|
||||
): Promise<LlmExecutorLaunchState> {
|
||||
const result = await portalFetch<{ launch: LlmExecutorLaunchState }>(
|
||||
`/admin-api/llm-providers/executor-launch/${executor}`,
|
||||
{ method: 'POST', body: JSON.stringify(payload) },
|
||||
);
|
||||
return result.launch;
|
||||
}
|
||||
|
||||
export async function stopLlmExecutor(
|
||||
executor: LlmExecutorId,
|
||||
payload: { purpose?: string; force?: boolean } = {},
|
||||
): Promise<LlmExecutorLaunchState | null> {
|
||||
const result = await portalFetch<{ launch: LlmExecutorLaunchState | null }>(
|
||||
`/admin-api/llm-providers/executor-stop/${executor}`,
|
||||
{ method: 'POST', body: JSON.stringify(payload) },
|
||||
);
|
||||
return result.launch;
|
||||
}
|
||||
|
||||
export async function restartLlmExecutor(
|
||||
executor: LlmExecutorId,
|
||||
payload: { mode?: 'headless' | 'serve'; cwd?: string; instruction?: string; purpose?: string } = {},
|
||||
): Promise<LlmExecutorLaunchState> {
|
||||
const result = await portalFetch<{ launch: LlmExecutorLaunchState }>(
|
||||
`/admin-api/llm-providers/executor-restart/${executor}`,
|
||||
{ method: 'POST', body: JSON.stringify(payload) },
|
||||
);
|
||||
return result.launch;
|
||||
}
|
||||
|
||||
export async function setLlmGlobalModel(model: string): Promise<{ global: LlmGlobalSettings }> {
|
||||
return portalFetch('/admin-api/llm-providers/global', {
|
||||
method: 'PUT',
|
||||
@@ -627,3 +809,127 @@ export async function testLlmProviderKey(
|
||||
body: JSON.stringify(model ? { model } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
// ── Blocked words ─────────────────────────────────────
|
||||
|
||||
export async function listBlockedWords(): Promise<BlockedWord[]> {
|
||||
const result = await portalFetch<{ words: BlockedWord[] }>('/admin-api/blocked-words');
|
||||
return result.words ?? [];
|
||||
}
|
||||
|
||||
export async function createBlockedWord(payload: {
|
||||
word: string;
|
||||
replacement?: string;
|
||||
note?: string;
|
||||
}): Promise<BlockedWord> {
|
||||
const result = await portalFetch<{ blockedWord: BlockedWord }>('/admin-api/blocked-words', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
return result.blockedWord;
|
||||
}
|
||||
|
||||
export async function updateBlockedWord(
|
||||
id: string,
|
||||
payload: Partial<{ word: string; replacement: string; note: string; status: 'active' | 'disabled' }>,
|
||||
): Promise<BlockedWord> {
|
||||
const result = await portalFetch<{ blockedWord: BlockedWord }>(`/admin-api/blocked-words/${id}`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
return result.blockedWord;
|
||||
}
|
||||
|
||||
export async function deleteBlockedWord(id: string): Promise<void> {
|
||||
await portalFetch(`/admin-api/blocked-words/${id}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// ── Subscriptions ──────────────────────────────────────
|
||||
|
||||
export async function listSubscriptionPlans(): Promise<PlanDefinition[]> {
|
||||
const result = await portalFetch<{ plans: PlanDefinition[] }>('/admin-api/subscriptions/plans');
|
||||
return result.plans;
|
||||
}
|
||||
|
||||
export async function createSubscriptionPlan(
|
||||
planType: string,
|
||||
data: Partial<PlanDefinition>,
|
||||
): Promise<{ plan: PlanDefinition; sync?: PlanSyncResult }> {
|
||||
const result = await portalFetch<{ plan: PlanDefinition; sync?: PlanSyncResult }>('/admin-api/subscriptions/plans', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ planType, ...data }),
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function updateSubscriptionPlan(
|
||||
planType: string,
|
||||
data: Partial<PlanDefinition>,
|
||||
): Promise<{ plan: PlanDefinition; sync?: PlanSyncResult }> {
|
||||
const result = await portalFetch<{ plan: PlanDefinition; sync?: PlanSyncResult }>(`/admin-api/subscriptions/plans/${planType}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function deleteSubscriptionPlan(planType: string): Promise<{ ok: boolean; sync?: PlanSyncResult }> {
|
||||
return portalFetch(`/admin-api/subscriptions/plans/${planType}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
export async function syncSubscriptionPlansToProduction(): Promise<PlanSyncResult> {
|
||||
const result = await portalFetch<{ sync: PlanSyncResult }>('/admin-api/subscriptions/plans/sync-production', {
|
||||
method: 'POST',
|
||||
});
|
||||
return result.sync;
|
||||
}
|
||||
|
||||
export async function listAdminSubscriptions(opts?: {
|
||||
userId?: string;
|
||||
status?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}): Promise<{ items: AdminSubscription[]; total: number; page: number; totalPages: number; pageSize: number }> {
|
||||
const q = new URLSearchParams();
|
||||
if (opts?.userId) q.set('userId', opts.userId);
|
||||
if (opts?.status) q.set('status', opts.status);
|
||||
if (opts?.page) q.set('page', String(opts.page));
|
||||
if (opts?.pageSize) q.set('pageSize', String(opts.pageSize));
|
||||
const result = await portalFetch<{
|
||||
items: AdminSubscription[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}>(`/admin-api/subscriptions${q.toString() ? `?${q}` : ''}`);
|
||||
return {
|
||||
items: result.items,
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
totalPages: Math.ceil(result.total / result.pageSize) || 1,
|
||||
pageSize: result.pageSize,
|
||||
};
|
||||
}
|
||||
|
||||
export async function grantUserSubscription(
|
||||
userId: string,
|
||||
planType: string,
|
||||
durationDays?: number,
|
||||
note?: string,
|
||||
): Promise<AdminSubscription> {
|
||||
const result = await portalFetch<{ subscription: AdminSubscription }>(`/admin-api/users/${userId}/subscription`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ planType, durationDays, note }),
|
||||
});
|
||||
return result.subscription;
|
||||
}
|
||||
|
||||
export async function cancelUserSubscription(userId: string): Promise<void> {
|
||||
await portalFetch(`/admin-api/users/${userId}/subscription`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
export async function getUserSubscription(userId: string): Promise<AdminSubscription | null> {
|
||||
const result = await portalFetch<{ subscription: AdminSubscription | null }>(
|
||||
`/admin-api/users/${userId}/subscription`,
|
||||
);
|
||||
return result.subscription;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user