Files
browser/platform_web/contracts/pluginBridge.ts
T

150 lines
4.0 KiB
TypeScript

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.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"
| "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.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",
"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[];
featureKeys?: string[];
}
export interface PluginBridgeManifestContract {
id: string;
declaredPermissions: PluginPermission[];
bridgeActions: PluginBridgeAction[];
pages: PluginPageContract[];
aiPurposes?: string[];
}
export function pluginBridgeManifestContractFromResponse(
plugin: Pick<GamePluginResponse, "id" | "declaredPermissions" | "bridgeActions" | "pages" | "aiPurposes">
): 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),
featureKeys: page.featureKeys ? [...page.featureKeys] : []
})),
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<string, string>;
}
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<string, string>;
error?: PluginBridgeSafeError;
}