import type { JobResponse, RunEndpointResponse, ServerInstanceResponse, ServerMetricsResponse, UserContactProfile, UserStatus, UserThemePreferenceResponse } from "../api/types"; export type WorkspaceRole = "platformAdmin" | "serverOwner" | "serverAdmin"; export type WorkspaceCapability = | "profile.settings.manage" | "platform.overview.read" | "servers.read" | "servers.manage" | "plugins.market.read" | "users.manage" | "aiProviders.manage" | "system.maintenance"; export interface CurrentUserView { id: string; displayName: string; email?: string; status: UserStatus; roles: WorkspaceRole[]; capabilities: WorkspaceCapability[]; profile: UserContactProfile; themePreference?: UserThemePreferenceResponse; source: "api" | "local"; } const roleCapabilities: Record = { platformAdmin: [ "profile.settings.manage", "platform.overview.read", "servers.read", "servers.manage", "plugins.market.read", "users.manage", "aiProviders.manage", "system.maintenance" ], serverOwner: ["profile.settings.manage", "servers.read", "servers.manage"], serverAdmin: ["profile.settings.manage", "servers.read", "servers.manage"] }; export function capabilitiesForRoles(roles: WorkspaceRole[]): WorkspaceCapability[] { const set = new Set(); for (const role of roles) { for (const capability of roleCapabilities[role] ?? []) { set.add(capability); } } return [...set]; } export function isPlatformAdmin(user: CurrentUserView): boolean { return user.roles.includes("platformAdmin"); } export function rolesFromBackendRoles(roles: string[]): WorkspaceRole[] { const mapped = new Set(); for (const role of roles) { const normalized = role.toLowerCase(); if (normalized === "admin" || normalized === "platform-admin" || normalized === "platformadmin") { mapped.add("platformAdmin"); } if (normalized === "server-owner" || normalized === "owner") { mapped.add("serverOwner"); } if (normalized === "server-admin" || normalized === "operator") { mapped.add("serverAdmin"); } } return mapped.size > 0 ? [...mapped] : ["serverAdmin"]; } export type OperationStatus = "pending" | "succeeded" | "failed"; export interface OperationRecord { id: string; intent: string; targetKind: "server" | "plugin" | "config" | "llm" | "platform"; targetId: string; requester: string; status: OperationStatus; jobId?: string; jobState?: JobResponse["state"]; message?: string; errorReason?: string; diagnosticId?: string; createdAt: string; updatedAt: string; } export interface ServerCardView { instance: ServerInstanceResponse; endpoint?: RunEndpointResponse; metrics?: ServerMetricsResponse; pendingJobs: number; activeJobs?: number; failedJobs?: number; latestJob?: JobResponse; } export type ServerStatusFilter = "all" | "online" | "offline" | "attention"; export function serverIsOnline(state: ServerInstanceResponse["state"]): boolean { return state === "running"; } export function serverNeedsAttention(state: ServerInstanceResponse["state"]): boolean { return state === "failed" || state === "installing"; } export function filterServerCards(cards: ServerCardView[], keyword: string, status: ServerStatusFilter): ServerCardView[] { const query = keyword.trim().toLowerCase(); return cards.filter((card) => { if (query && !`${card.instance.name} ${card.instance.id} ${card.instance.pluginId}`.toLowerCase().includes(query)) { return false; } if (status === "online") { return serverIsOnline(card.instance.state); } if (status === "offline") { return !serverIsOnline(card.instance.state); } if (status === "attention") { return serverNeedsAttention(card.instance.state); } return true; }); } export interface GameTypeDistributionEntry { serverType: string; label: string; count: number; } export interface PlatformOverviewSignal { id: string; kind: "log" | "fault" | "plugin" | "aiProvider" | "job"; summary: string; detail: string; targetPage: "servers" | "plugins" | "aiProviders" | "maintenance"; targetId?: string; tone: "info" | "warning" | "error"; at: string; } export type ServerDetailSection = "manage" | "files" | "llm" | `plugin:${string}`; export const serverDetailSections: Array<{ id: ServerDetailSection; label: string }> = [ { id: "manage", label: "管理" }, { id: "files", label: "文件" }, { id: "llm", label: "AI 助手" } ]; export interface DiffLine { kind: "same" | "added" | "removed"; text: string; } export interface ConfigDiffView { serverInstanceId: string; configVersion?: number; checksum?: string; key?: string; source?: string; summary: string; lines: DiffLine[]; nextContent: string; proposedContentInputRef?: string; } export interface LlmSuggestionView { serverInstanceId: string; source: "api"; recommendation: string; diffSummary?: string; executionStatus?: string; job?: JobResponse; }