功能修改
This commit is contained in:
+169
-1
@@ -8,6 +8,11 @@ import type {
|
||||
AiProviderUpdateRequest,
|
||||
AIInvocationRequest,
|
||||
AIInvocationResponse,
|
||||
AIConfigDiffApprovalResponse,
|
||||
AIConfigDiffListResponse,
|
||||
AlertListResponse,
|
||||
AlertResponse,
|
||||
AlertRetryResponse,
|
||||
ApiErrorResponse,
|
||||
ArtifactContentChunk,
|
||||
ArtifactDownloadReferenceResponse,
|
||||
@@ -16,8 +21,16 @@ import type {
|
||||
AuthSessionResponse,
|
||||
AuditEventListResponse,
|
||||
ClientManagerBuildRequest,
|
||||
ClientManagerControlRequest,
|
||||
ClientManagerDeployRequest,
|
||||
ClientManagerDistributionResponse,
|
||||
ClientManagerDownloadRequest,
|
||||
ClientManagerInstallationListResponse,
|
||||
ClientManagerInstallationResponse,
|
||||
ClientManagerRetryRequest,
|
||||
ClientManagerRevokeSessionRequest,
|
||||
ClientManagerUninstallRequest,
|
||||
ClientManagerUpdateRequest,
|
||||
ComponentKeyResponse,
|
||||
ComponentKeyResetRequest,
|
||||
CurrentUserResponse,
|
||||
@@ -25,6 +38,15 @@ import type {
|
||||
DependencyJobRequest,
|
||||
FileOperationDispatchRequest,
|
||||
FileOperationDispatchResponse,
|
||||
GameClientBridgeCancelRequest,
|
||||
GameClientBridgeCancelResponse,
|
||||
GameClientBridgeCommandFilterRequest,
|
||||
GameClientBridgeCommandListResponse,
|
||||
GameClientBridgeCommandResponse,
|
||||
GameClientBridgeQueueRequest,
|
||||
GameClientBridgeSnapshotListResponse,
|
||||
GameClientBridgeSnapshotQuery,
|
||||
GameClientBridgeStatusResponse,
|
||||
GamePluginListResponse,
|
||||
HealthResponse,
|
||||
JobCreateRequest,
|
||||
@@ -42,6 +64,11 @@ import type {
|
||||
MarketplacePluginResponse,
|
||||
MarketplacePluginStateRequest,
|
||||
PlatformResourceUsageResponse,
|
||||
ProductionCapacitySummaryResponse,
|
||||
CapacityAdmissionDecisionResponse,
|
||||
PluginLifecycleActionRequest,
|
||||
PluginLifecycleActionResponse,
|
||||
PluginLifecycleListResponse,
|
||||
PluginBridgeAuthorizeRequest,
|
||||
PluginBridgeAuthorizeResponse,
|
||||
PluginBridgeExecuteRequest,
|
||||
@@ -86,6 +113,15 @@ import type {
|
||||
} from "./types";
|
||||
import { readWebRuntimeEnv } from "../schemas/env";
|
||||
import { parseSafeDependencyCatalog, parseSafeRunUpdate, parseSafeRunUpdateList } from "../schemas/runtimeUpdates";
|
||||
import { parseSafeClientManagerLifecycle, parseSafeClientManagerLifecycleList } from "../schemas/clientManagerLifecycle";
|
||||
import {
|
||||
parseSafeGameClientBridgeCancellation,
|
||||
parseSafeGameClientBridgeCommand,
|
||||
parseSafeGameClientBridgeCommandList,
|
||||
parseSafeGameClientBridgeSnapshotList,
|
||||
parseSafeGameClientBridgeStatus
|
||||
} from "../schemas/gameClientBridge";
|
||||
import { safeDiagnosticText } from "../utils/safeDiagnosticText";
|
||||
|
||||
let platformApiSessionToken: string | null = null;
|
||||
let platformApiAuthFailureHandler: ((error: PlatformApiError) => void) | null = null;
|
||||
@@ -298,6 +334,74 @@ export class PlatformApiClient {
|
||||
});
|
||||
}
|
||||
|
||||
async listClientManagerLifecycles(id: string): Promise<ClientManagerInstallationListResponse> {
|
||||
return parseSafeClientManagerLifecycleList(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers`));
|
||||
}
|
||||
|
||||
async getClientManagerLifecycle(id: string, profileKey: string): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/${encodeURIComponent(profileKey)}`));
|
||||
}
|
||||
|
||||
async deployClientManager(id: string, request: ClientManagerDeployRequest): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/deploy`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async controlClientManager(id: string, request: ClientManagerControlRequest): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/control`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async updateClientManager(id: string, request: ClientManagerUpdateRequest): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/update`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async retryClientManagerLifecycle(id: string, request: ClientManagerRetryRequest): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/retry`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async revokeClientManagerSession(id: string, request: ClientManagerRevokeSessionRequest): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/revoke-session`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async uninstallClientManager(id: string, request: ClientManagerUninstallRequest): Promise<ClientManagerInstallationResponse> {
|
||||
return parseSafeClientManagerLifecycle(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/client-managers/uninstall`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async getGameClientBridgeStatus(id: string): Promise<GameClientBridgeStatusResponse> {
|
||||
return parseSafeGameClientBridgeStatus(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/game-client-bridge`));
|
||||
}
|
||||
|
||||
async listGameClientBridgeCommands(id: string, filter: GameClientBridgeCommandFilterRequest = {}): Promise<GameClientBridgeCommandListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
if (filter.profileKey) params.set("profileKey", filter.profileKey);
|
||||
if (filter.state) params.set("state", filter.state);
|
||||
if (filter.commandType) params.set("commandType", filter.commandType);
|
||||
const query = params.toString();
|
||||
return parseSafeGameClientBridgeCommandList(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/game-client-bridge/commands${query ? `?${query}` : ""}`));
|
||||
}
|
||||
|
||||
async queueGameClientBridgeCommand(id: string, request: GameClientBridgeQueueRequest): Promise<GameClientBridgeCommandResponse> {
|
||||
return parseSafeGameClientBridgeCommand(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/game-client-bridge/commands`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async getGameClientBridgeCommand(id: string, commandId: string): Promise<GameClientBridgeCommandResponse> {
|
||||
return parseSafeGameClientBridgeCommand(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/game-client-bridge/commands/${encodeURIComponent(commandId)}`));
|
||||
}
|
||||
|
||||
async cancelGameClientBridgeCommand(id: string, commandId: string, request: GameClientBridgeCancelRequest = {}): Promise<GameClientBridgeCancelResponse> {
|
||||
return parseSafeGameClientBridgeCancellation(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/game-client-bridge/commands/${encodeURIComponent(commandId)}/cancel`, { method: "POST", body: request }));
|
||||
}
|
||||
|
||||
async listGameClientBridgeSnapshots(id: string, query: GameClientBridgeSnapshotQuery = {}): Promise<GameClientBridgeSnapshotListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
if (query.profileKey) params.set("profileKey", query.profileKey);
|
||||
if (query.type) params.set("type", query.type);
|
||||
if (query.streamKey) params.set("streamKey", query.streamKey);
|
||||
if (query.observedAfter) params.set("observedAfter", query.observedAfter);
|
||||
if (query.limit !== undefined) params.set("limit", String(query.limit));
|
||||
const search = params.toString();
|
||||
return parseSafeGameClientBridgeSnapshotList(await this.request<unknown>(`/server-instances/${encodeURIComponent(id)}/game-client-bridge/snapshots${search ? `?${search}` : ""}`));
|
||||
}
|
||||
|
||||
async checkDependencies(id: string, request: DependencyJobRequest): Promise<JobResponse> {
|
||||
return this.request<JobResponse>(`/server-instances/${encodeURIComponent(id)}/dependencies/check`, {
|
||||
method: "POST",
|
||||
@@ -386,6 +490,55 @@ export class PlatformApiClient {
|
||||
return this.request<PlatformResourceUsageResponse>("/metrics/platform");
|
||||
}
|
||||
|
||||
async getProductionCapacity(): Promise<ProductionCapacitySummaryResponse> {
|
||||
return this.request<ProductionCapacitySummaryResponse>("/production/capacity");
|
||||
}
|
||||
|
||||
async checkCapacityAdmission(request: { serverInstanceId?: string; runEndpointId?: string; capability: string; targetKey?: string; idempotencyKey?: string }): Promise<CapacityAdmissionDecisionResponse> {
|
||||
return this.request<CapacityAdmissionDecisionResponse>("/production/capacity/admission", { method: "POST", body: request });
|
||||
}
|
||||
|
||||
async listAlerts(filter: { state?: string; sourceKind?: string; sourceId?: string; severity?: string } = {}): Promise<AlertListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
Object.entries(filter).forEach(([key, value]) => { if (value) params.set(key, value); });
|
||||
const query = params.toString();
|
||||
return this.request<AlertListResponse>(`/alerts${query ? `?${query}` : ""}`);
|
||||
}
|
||||
|
||||
async acknowledgeAlert(id: string, note = ""): Promise<AlertResponse> {
|
||||
return this.request<AlertResponse>(`/alerts/${encodeURIComponent(id)}/acknowledge`, { method: "POST", body: { note } });
|
||||
}
|
||||
|
||||
async resolveAlert(id: string, note = ""): Promise<AlertResponse> {
|
||||
return this.request<AlertResponse>(`/alerts/${encodeURIComponent(id)}/resolve`, { method: "POST", body: { note } });
|
||||
}
|
||||
|
||||
async retryAlert(id: string, idempotencyKey: string): Promise<AlertRetryResponse> {
|
||||
return this.request<AlertRetryResponse>(`/alerts/${encodeURIComponent(id)}/retry`, { method: "POST", body: { idempotencyKey } });
|
||||
}
|
||||
|
||||
async listPluginLifecycles(filter: { pluginId?: string; serverInstanceId?: string; currentState?: string } = {}): Promise<PluginLifecycleListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
Object.entries(filter).forEach(([key, value]) => { if (value) params.set(key, value); });
|
||||
const query = params.toString();
|
||||
return this.request<PluginLifecycleListResponse>(`/plugin-lifecycles${query ? `?${query}` : ""}`);
|
||||
}
|
||||
|
||||
async runPluginLifecycle(pluginId: string, request: PluginLifecycleActionRequest): Promise<PluginLifecycleActionResponse> {
|
||||
return this.request<PluginLifecycleActionResponse>(`/plugin-lifecycles/${encodeURIComponent(pluginId)}/actions`, { method: "POST", body: request });
|
||||
}
|
||||
|
||||
async listAIConfigDiffs(filter: { serverInstanceId?: string; pluginId?: string; state?: string } = {}): Promise<AIConfigDiffListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
Object.entries(filter).forEach(([key, value]) => { if (value) params.set(key, value); });
|
||||
const query = params.toString();
|
||||
return this.request<AIConfigDiffListResponse>(`/ai/config-diffs${query ? `?${query}` : ""}`);
|
||||
}
|
||||
|
||||
async approveAIConfigDiff(id: string, idempotencyKey: string): Promise<AIConfigDiffApprovalResponse> {
|
||||
return this.request<AIConfigDiffApprovalResponse>(`/ai/config-diffs/${encodeURIComponent(id)}/approve`, { method: "POST", body: { idempotencyKey } });
|
||||
}
|
||||
|
||||
async listServerMetrics(): Promise<ServerMetricsListResponse> {
|
||||
return this.request<ServerMetricsListResponse>("/metrics/server-instances");
|
||||
}
|
||||
@@ -556,7 +709,7 @@ async function responseError(response: Response): Promise<PlatformApiError> {
|
||||
const message = response.status === 401
|
||||
? "会话已失效,请重新登录。"
|
||||
: response.status === 403
|
||||
? "没有权限访问该资源。"
|
||||
? safeForbiddenMessage(apiError?.message)
|
||||
: apiError?.message ?? `request failed: ${response.status}`;
|
||||
const error = new PlatformApiError(response.status, apiError?.code ?? "request_failed", message);
|
||||
if (response.status === 401) {
|
||||
@@ -566,6 +719,21 @@ async function responseError(response: Response): Promise<PlatformApiError> {
|
||||
return error;
|
||||
}
|
||||
|
||||
function safeForbiddenMessage(apiMessage?: string): string {
|
||||
const sanitized = safeDiagnosticText(apiMessage, "")?.trim();
|
||||
if (!sanitized || sanitized === "account is not allowed to access this resource") {
|
||||
return "没有权限访问该资源。";
|
||||
}
|
||||
const missingPermission = sanitized.match(/^plugin does not declare required permission:\s*([a-z0-9._-]+)$/i);
|
||||
if (missingPermission) {
|
||||
return `插件未声明所需权限:${missingPermission[1]}`;
|
||||
}
|
||||
if (sanitized === "plugin is not installed") {
|
||||
return "插件未安装,不能执行该操作。";
|
||||
}
|
||||
return "没有权限访问该资源。";
|
||||
}
|
||||
|
||||
function marketplaceQuery(filter: MarketplacePluginFilterRequest): string {
|
||||
const params = new URLSearchParams();
|
||||
if (filter.status && filter.status !== "all") {
|
||||
|
||||
Reference in New Issue
Block a user