refactor(scum): remove legacy projection workflows

This commit is contained in:
npc0-hue
2026-08-11 15:18:03 +08:00
parent df48d8b283
commit 13746150cb
26 changed files with 47 additions and 3844 deletions
+1 -13
View File
@@ -244,12 +244,6 @@ describe("PlatformApiClient AI providers", () => {
count: 1
});
}
if (url.endsWith("/api/v1/server-instances/server-1/scum/players")) return jsonResponse({ items: [{ id: "scum-player-1", gamePlayerId: "steam-1", displayName: "Prisoner One", online: true }], count: 1 });
if (url.endsWith("/api/v1/server-instances/server-1/scum/squads")) return jsonResponse({ items: [{ id: "squad-1", squadId: "squad-1", name: "Alpha" }], count: 1 });
if (url.endsWith("/api/v1/server-instances/server-1/scum/squad-members")) return jsonResponse({ items: [{ id: "member-1", squadId: "squad-1", gamePlayerId: "steam-1" }], count: 1 });
if (url.endsWith("/api/v1/server-instances/server-1/scum/vehicles")) return jsonResponse({ items: [{ id: "vehicle-1", vehicleId: "vehicle-1", label: "SUV" }], count: 1 });
if (url.endsWith("/api/v1/server-instances/server-1/scum/flags")) return jsonResponse({ items: [{ id: "flag-1", flagId: "flag-1", ownerSquadId: "squad-1" }], count: 1 });
if (url.endsWith("/api/v1/server-instances/server-1/scum/positions")) return jsonResponse({ items: [{ id: "position-1", subjectType: "player", subjectId: "steam-1", x: 1, y: 2, z: 3 }], count: 1 });
if (url.endsWith("/api/v1/file-operations/dispatch") && init?.method === "POST") {
expect(JSON.parse(String(init.body))).toEqual({
serverInstanceId: server.id,
@@ -548,12 +542,6 @@ describe("PlatformApiClient AI providers", () => {
await expect(client.deleteServerInstance(server.id, { password: "secret-password", force: true, confirmation: "FORCE DELETE" })).resolves.toBeUndefined();
await expect(client.getPlatformResourceUsage()).resolves.toMatchObject({ source: "platform-derived", cpuPercent: 28 });
await expect(client.listServerMetrics()).resolves.toMatchObject({ count: 1, items: [{ serverInstanceId: server.id, online: true }] });
await expect(client.listSCUMPlayers(server.id)).resolves.toMatchObject({ count: 1, items: [{ gamePlayerId: "steam-1" }] });
await expect(client.listSCUMSquads(server.id)).resolves.toMatchObject({ count: 1 });
await expect(client.listSCUMSquadMembers(server.id)).resolves.toMatchObject({ count: 1 });
await expect(client.listSCUMVehicles(server.id)).resolves.toMatchObject({ count: 1 });
await expect(client.listSCUMFlags(server.id)).resolves.toMatchObject({ count: 1 });
await expect(client.listSCUMPositions(server.id)).resolves.toMatchObject({ count: 1 });
await expect(client.dispatchFileOperation({ serverInstanceId: server.id, operation: "read", key: "logs/latest.log", idempotencyKey: "idem-file" })).resolves.toMatchObject({
status: "queued",
job: { capability: "files.read", targetKey: "logs/latest.log" }
@@ -612,7 +600,7 @@ describe("PlatformApiClient AI providers", () => {
client.invokeAI({ requestId: "ai-1", serverInstanceId: server.id, purpose: "config.suggest", prompt: "Tune PVP safely", currentConfig: "server.name=Example Survival #1\n" })
).resolves.toMatchObject({ status: "ok", usage: { mocked: true }, configRecommendation: { diffSummary: "review required" } });
expect(fetchMock).toHaveBeenCalledTimes(42);
expect(fetchMock).toHaveBeenCalledTimes(36);
});
it("calls plugin marketplace endpoints with filter and state contracts", async () => {
-25
View File
@@ -101,7 +101,6 @@ import type {
RemoteAdapterDeclarationListResponse,
RemoteAdapterRequest,
RemoteAdapterResponse,
SCUMListResponse,
ServerRuntimeActionsResponse,
UserCreateRequest,
UserListResponse,
@@ -576,30 +575,6 @@ export class PlatformApiClient {
return this.request<RemoteAdapterResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/remote-adapters`, { method: "POST", body: request });
}
async listSCUMPlayers(serverInstanceId: string): Promise<SCUMListResponse> {
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/players`);
}
async listSCUMSquads(serverInstanceId: string): Promise<SCUMListResponse> {
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/squads`);
}
async listSCUMSquadMembers(serverInstanceId: string): Promise<SCUMListResponse> {
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/squad-members`);
}
async listSCUMVehicles(serverInstanceId: string): Promise<SCUMListResponse> {
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/vehicles`);
}
async listSCUMFlags(serverInstanceId: string): Promise<SCUMListResponse> {
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/flags`);
}
async listSCUMPositions(serverInstanceId: string): Promise<SCUMListResponse> {
return this.request<SCUMListResponse>(`/server-instances/${encodeURIComponent(serverInstanceId)}/scum/positions`);
}
async dispatchFileOperation(request: FileOperationDispatchRequest): Promise<FileOperationDispatchResponse> {
return this.request<FileOperationDispatchResponse>("/file-operations/dispatch", {
method: "POST",
-3
View File
@@ -1373,9 +1373,6 @@ export interface RemoteAdapterResponse {
completedAt?: string;
}
export type SCUMJsonRecord = Record<string, unknown>;
export interface SCUMListResponse<T = SCUMJsonRecord> { items: T[]; count: number; }
export interface ServerConfigResponse {
serverInstanceId: string;
configVersion: number;
+1 -8
View File
@@ -1,8 +1 @@
export interface PluginPageWorkspaceActions {
listSCUMPlayers?: () => Promise<unknown>;
listSCUMSquads?: () => Promise<unknown>;
listSCUMSquadMembers?: () => Promise<unknown>;
listSCUMVehicles?: () => Promise<unknown>;
listSCUMFlags?: () => Promise<unknown>;
listSCUMPositions?: () => Promise<unknown>;
}
export interface PluginPageWorkspaceActions {}
@@ -96,11 +96,11 @@ describe("PluginPageHostPage", () => {
expect(hostSource).not.toMatch(/ScumFileConfigWorkbench|GamePlayerIntelligencePanel|GameGiftCatalogPanel|ScumMapTrajectoryPanel|game\.scum/);
});
it("keeps SCUM workspace callbacks read-only across parent operational refreshes", () => {
it("removes SCUM legacy workspace callbacks from the parent host", () => {
expect(hostSource).toContain("readyPluginRef.current = readyPlugin");
expect(hostSource).toContain("hostContextRef.current = hostContext");
expect(hostSource).toContain("listSCUMPlayers: () => platformApiClient.listSCUMPlayers(serverId)");
expect(hostSource).toContain("listSCUMPositions: () => platformApiClient.listSCUMPositions(serverId)");
expect(hostSource).not.toContain("listSCUMPlayers");
expect(hostSource).not.toContain("listSCUMPositions");
expect(hostSource).not.toContain("createSCUMWorkflow");
expect(hostSource).not.toContain("createSCUMOperation");
expect(hostSource).not.toContain("listSCUMWorkflowSteps");
@@ -108,7 +108,6 @@ describe("PluginPageHostPage", () => {
expect(hostSource).not.toContain("requestFile");
expect(hostSource).not.toContain("writeFile");
expect(hostSource).not.toContain("getDeclaredFileReadSnapshot");
expect(hostSource).toContain("}, [pluginId, serverId]);");
expect(hostSource).not.toContain("}, [hostContext, readyPlugin, serverId]);");
expect(hostSource).toContain("const workspaceActions = undefined");
});
});
+1 -11
View File
@@ -66,17 +66,7 @@ export function PluginPageHostPage({ params, onNavigate, initialPlugin, embedded
}) : undefined, [manifestContract, routeKey, serverId]);
readyPluginRef.current = readyPlugin;
hostContextRef.current = hostContext;
const workspaceActions = useMemo<PluginPageWorkspaceActions | undefined>(() => {
if (!pluginId) return undefined;
return {
listSCUMPlayers: () => platformApiClient.listSCUMPlayers(serverId),
listSCUMSquads: () => platformApiClient.listSCUMSquads(serverId),
listSCUMSquadMembers: () => platformApiClient.listSCUMSquadMembers(serverId),
listSCUMVehicles: () => platformApiClient.listSCUMVehicles(serverId),
listSCUMFlags: () => platformApiClient.listSCUMFlags(serverId),
listSCUMPositions: () => platformApiClient.listSCUMPositions(serverId)
};
}, [pluginId, serverId]);
const workspaceActions = undefined as PluginPageWorkspaceActions | undefined;
const bundleLoadKey = declaredBundlePage ? [declaredBundlePage.bundleKey, declaredBundlePage.bundleVersion, declaredBundlePage.bundleIntegritySha256, declaredBundlePage.path].join(":") : "";
const loadableBundlePage = useMemo(() => declaredBundlePage, [bundleLoadKey]);
useEffect(() => {