import type { GamePluginResponse } from "../api/types"; export type PluginPermission = | "server.create" | "server.read" | "server.lifecycle" | "server.files.read" | "server.files.write" | "server.logs.read" | "server.artifacts.read" | "server.artifacts.write" | "server.remote.access" | "server.run.distribution" | "server.dependencies.manage" | "server.client-manager.manage" | "server.game-client.read" | "server.game-client.command" | "server.game-client.maintenance" | "ai.invoke"; export type PluginBridgeAction = | "server.instances.read" | "jobs.dispatch" | "logs.query" | "artifacts.open" | "files.request" | "remote.access.request" | "run.distribution.request" | "dependencies.request" | "logs.backfill.request" | "client-manager.request" | "plugin-lifecycle.request" | "ai.invoke"; const pluginPermissions: readonly PluginPermission[] = [ "server.create", "server.read", "server.lifecycle", "server.files.read", "server.files.write", "server.logs.read", "server.artifacts.read", "server.artifacts.write", "server.remote.access", "server.run.distribution", "server.dependencies.manage", "server.client-manager.manage", "server.game-client.read", "server.game-client.command", "server.game-client.maintenance", "ai.invoke" ]; const pluginBridgeActions: readonly PluginBridgeAction[] = [ "server.instances.read", "jobs.dispatch", "logs.query", "artifacts.open", "files.request", "remote.access.request", "run.distribution.request", "dependencies.request", "logs.backfill.request", "client-manager.request", "plugin-lifecycle.request", "ai.invoke" ]; export function isPluginPermission(value: string): value is PluginPermission { return pluginPermissions.includes(value as PluginPermission); } export function isPluginBridgeAction(value: string): value is PluginBridgeAction { return pluginBridgeActions.includes(value as PluginBridgeAction); } export interface PluginPageContract { key: string; title: string; path: string; bundleKey?: string; bundleVersion?: string; bundleIntegritySha256?: string; permissions?: PluginPermission[]; bridgeActions?: PluginBridgeAction[]; } export interface PluginBridgeManifestContract { id: string; declaredPermissions: PluginPermission[]; bridgeActions: PluginBridgeAction[]; pages: PluginPageContract[]; aiPurposes?: string[]; } export function pluginBridgeManifestContractFromResponse( plugin: Pick ): PluginBridgeManifestContract { return { id: plugin.id, declaredPermissions: plugin.declaredPermissions.filter(isPluginPermission), bridgeActions: plugin.bridgeActions.filter(isPluginBridgeAction), pages: plugin.pages.map((page) => ({ key: page.key, title: page.title, path: page.path, bundleKey: page.bundleKey, bundleVersion: page.bundleVersion, bundleIntegritySha256: page.bundleIntegritySha256, permissions: page.permissions.filter(isPluginPermission), bridgeActions: page.bridgeActions?.filter(isPluginBridgeAction) })), aiPurposes: [...plugin.aiPurposes] }; } export interface PluginBridgeThemeTokens { colorScheme: "light" | "dark"; accentColor: string; } export interface PluginBridgeHostContext { pluginId: string; routeKey: string; serverInstanceId?: string; themeTokens: PluginBridgeThemeTokens; permissions: PluginPermission[]; bridgeActions: PluginBridgeAction[]; aiPurposes: string[]; } export interface PluginBridgeExecuteEnvelope { requestId: string; action: PluginBridgeAction; aiPurpose?: string; payload?: Record; } export interface PluginBridgeSafeError { code: string; message: string; details?: string[]; } export interface PluginBridgeExecutionResult { requestId: string; action: PluginBridgeAction; status: "ok" | "queued" | "denied" | "unsupported" | "cancelled" | "error" | string; result?: Record; error?: PluginBridgeSafeError; }