Complete platform management workflows

This commit is contained in:
npc0-hue
2026-07-14 16:39:37 +08:00
parent 7e05d0a4e7
commit 4f33f761a3
106 changed files with 11313 additions and 460 deletions
+293
View File
@@ -7,6 +7,10 @@ export type PluginPermission =
| "server.logs.read"
| "server.artifacts.read"
| "server.artifacts.write"
| "server.remote.access"
| "server.run.distribution"
| "server.dependencies.manage"
| "server.client-manager.manage"
| "ai.invoke";
export type RunCapability =
@@ -20,6 +24,18 @@ export type RunCapability =
| "files.write"
| "files.patch"
| "logs.read"
| "remote.ftp.read"
| "remote.ftp.write"
| "remote.rsync.read"
| "remote.rsync.write"
| "remote.run.files.read"
| "remote.run.files.write"
| "remote.run.process.start"
| "remote.run.process.stop"
| "remote.run.db.mysql.query"
| "remote.run.db.sqlite.query"
| "remote.run.logs.transfer"
| "remote.run.rcon.command"
| "artifacts.read"
| "artifacts.write"
| "ai.invoke";
@@ -32,6 +48,11 @@ export type PluginBridgeAction =
| "logs.query"
| "artifacts.open"
| "files.request"
| "remote.access.request"
| "run.distribution.request"
| "dependencies.request"
| "logs.backfill.request"
| "client-manager.request"
| "ai.invoke";
export type PluginBridgeRequestPayload = Record<string, unknown>;
@@ -105,6 +126,150 @@ export type PluginLifecycleDispatchPayload = Record<string, string> & {
idempotencyKey: string;
};
export type PluginRemoteAccessPayload = Record<string, string> & {
capability: Extract<RunCapability, `remote.${string}`>;
targetKey?: string;
inputRef?: string;
idempotencyKey: string;
};
export type PluginRunDistributionPayload = Record<string, string> & {
operation: "generate" | "download" | "reset-key" | "update";
targetOS?: RuntimePlatform;
targetArch?: RuntimeArch;
artifactId?: string;
idempotencyKey: string;
};
export type PluginDependencyActionPayload = Record<string, string> & {
operation: "check" | "install";
probeKey?: string;
planKey?: string;
idempotencyKey: string;
};
export type PluginLogBackfillPayload = Record<string, string> & {
sourceKey: string;
cursor?: string;
limit?: string;
idempotencyKey: string;
};
export type PluginClientManagerPayload = Record<string, string> & {
operation: "generate" | "download" | "reset-key";
profileKey: string;
targetOS?: RuntimePlatform;
targetArch?: RuntimeArch;
artifactId?: string;
idempotencyKey: string;
};
export type RemoteAccessMethod = "ftp" | "rsync" | "run";
export type RemoteDatabaseEngine = "mysql" | "sqlite";
export interface GamePluginRemoteAccess {
methods: RemoteAccessMethod[];
runCapabilities?: Array<Extract<RunCapability, `remote.${string}`>>;
databaseEngines?: RemoteDatabaseEngine[];
rcon?: boolean;
logTransfer?: boolean;
}
export type RuntimePlatform = "windows" | "linux" | "darwin";
export type RuntimeArch = "amd64" | "arm64";
export type RuntimeTarget = { os: RuntimePlatform; arch: RuntimeArch };
export interface RuntimeDiscoveryProbe {
key: string;
kind: "file.exists" | "command.version" | "service.status" | "port.open" | "steam.app" | "docker.container";
targetKey: string;
required?: boolean;
expected?: string;
platforms?: RuntimePlatform[];
}
export interface RuntimeLifecycleProfile {
key: string;
mode: "local-process" | "hosted-ftp-rcon" | "ftp-only" | "custom-client";
capabilities: RunCapability[];
actionRefs?: Partial<Record<PluginLifecycleAction, string>>;
transportKeys?: string[];
clientManagerRef?: string;
platforms?: RuntimePlatform[];
}
export interface RuntimeDependencyProbe {
key: string;
kind: "command.version" | "service.exists" | "port.available" | "steam.app" | "java.version" | "docker.available" | "package.installed" | "file.exists";
targetKey: string;
required?: boolean;
minimumVersion?: string;
platforms?: RuntimePlatform[];
}
export interface RuntimeInstallStep {
type: "package" | "verified-download" | "steamcmd-app" | "manual";
targetKey: string;
packageManager?: "winget" | "choco" | "scoop" | "apt" | "yum" | "dnf" | "pacman" | "zypper" | "brew" | "steamcmd" | "manual";
packageName?: string;
version?: string;
downloadRef?: string;
checksum?: `sha256:${string}`;
}
export interface RuntimeInstallPlan {
key: string;
title: string;
platforms?: RuntimePlatform[];
steps: RuntimeInstallStep[];
}
export interface RuntimeLogSource {
key: string;
kind: "process.stdout" | "process.stderr" | "file.tail" | "ftp.poll" | "sql.query" | "client-manager";
targetKey?: string;
streamKey: string;
cursorKind?: "sequence" | "offset" | "fingerprint" | "ftp-listing" | "sql-cursor";
retentionDays?: number;
}
export interface RuntimeTransportProfile {
key: string;
kind: "file" | "ftp" | "rsync" | "mysql" | "sqlite" | "rcon";
targetKey?: string;
capabilities: RunCapability[];
}
export interface RuntimeClientManagerProfile {
key: string;
displayName?: string;
repository: {
url: string;
revisionPolicy: "pinned" | "branch" | "tag";
branch?: string;
tag?: string;
revision?: string;
};
supportedTargets: RuntimeTarget[];
build: {
system: "go" | "npm" | "cargo" | "make";
workspaceRef?: string;
entryRef?: string;
};
configTemplates?: Array<{ key: string; templateRef: string; outputRef: string }>;
outputArtifacts: string[];
}
export interface GamePluginRuntimeProfiles {
discovery?: RuntimeDiscoveryProbe[];
lifecycleProfiles?: RuntimeLifecycleProfile[];
dependencyProbes?: RuntimeDependencyProbe[];
installPlans?: RuntimeInstallPlan[];
logSources?: RuntimeLogSource[];
transportProfiles?: RuntimeTransportProfile[];
clientManagers?: RuntimeClientManagerProfile[];
}
export interface PluginArtifactReference {
artifactId: string;
filename: string;
@@ -140,6 +305,11 @@ export const pluginBridgeActionPolicies: Record<PluginBridgeAction, PluginBridge
"logs.query": { permissions: ["server.logs.read"] },
"artifacts.open": { permissions: ["server.artifacts.read"] },
"files.request": { permissions: ["server.files.read"] },
"remote.access.request": { permissions: ["server.remote.access"] },
"run.distribution.request": { permissions: ["server.run.distribution"] },
"dependencies.request": { permissions: ["server.dependencies.manage"] },
"logs.backfill.request": { permissions: ["server.logs.read"] },
"client-manager.request": { permissions: ["server.client-manager.manage"] },
"ai.invoke": { permissions: ["ai.invoke"], aiPurposeRequired: true }
};
@@ -179,6 +349,8 @@ export interface GamePluginManifest {
bridge?: GamePluginBridge;
capabilities: RunCapability[];
permissions: PluginPermission[];
remoteAccess?: GamePluginRemoteAccess;
runtimeProfiles?: GamePluginRuntimeProfiles;
actions?: GamePluginActions;
pages?: GamePluginPage[];
ai?: {
@@ -280,6 +452,127 @@ export function createLifecycleDispatchRequest(input: {
});
}
export function createRemoteAccessRequest(input: {
requestId: string;
context: PluginBridgeContext;
capability: PluginRemoteAccessPayload["capability"];
targetKey?: string;
inputRef?: string;
idempotencyKey: string;
}): PluginBridgeExecutionRequest<PluginRemoteAccessPayload> {
return createBridgeExecutionRequest({
requestId: input.requestId,
context: input.context,
action: "remote.access.request",
payload: {
capability: input.capability,
targetKey: input.targetKey ?? "",
inputRef: input.inputRef ?? "",
idempotencyKey: input.idempotencyKey
}
});
}
export function createRunDistributionRequest(input: {
requestId: string;
context: PluginBridgeContext;
operation: PluginRunDistributionPayload["operation"];
targetOS?: RuntimePlatform;
targetArch?: RuntimeArch;
artifactId?: string;
idempotencyKey: string;
}): PluginBridgeExecutionRequest<PluginRunDistributionPayload> {
const payload: PluginRunDistributionPayload = {
operation: input.operation,
artifactId: input.artifactId ?? "",
idempotencyKey: input.idempotencyKey
};
if (input.targetOS) {
payload.targetOS = input.targetOS;
}
if (input.targetArch) {
payload.targetArch = input.targetArch;
}
return createBridgeExecutionRequest({
requestId: input.requestId,
context: input.context,
action: "run.distribution.request",
payload
});
}
export function createDependencyActionRequest(input: {
requestId: string;
context: PluginBridgeContext;
operation: PluginDependencyActionPayload["operation"];
probeKey?: string;
planKey?: string;
idempotencyKey: string;
}): PluginBridgeExecutionRequest<PluginDependencyActionPayload> {
return createBridgeExecutionRequest({
requestId: input.requestId,
context: input.context,
action: "dependencies.request",
payload: {
operation: input.operation,
probeKey: input.probeKey ?? "",
planKey: input.planKey ?? "",
idempotencyKey: input.idempotencyKey
}
});
}
export function createLogBackfillRequest(input: {
requestId: string;
context: PluginBridgeContext;
sourceKey: string;
cursor?: string;
limit?: number;
idempotencyKey: string;
}): PluginBridgeExecutionRequest<PluginLogBackfillPayload> {
return createBridgeExecutionRequest({
requestId: input.requestId,
context: input.context,
action: "logs.backfill.request",
payload: {
sourceKey: input.sourceKey,
cursor: input.cursor ?? "",
limit: typeof input.limit === "number" ? String(input.limit) : "",
idempotencyKey: input.idempotencyKey
}
});
}
export function createClientManagerRequest(input: {
requestId: string;
context: PluginBridgeContext;
operation: PluginClientManagerPayload["operation"];
profileKey: string;
targetOS?: RuntimePlatform;
targetArch?: RuntimeArch;
artifactId?: string;
idempotencyKey: string;
}): PluginBridgeExecutionRequest<PluginClientManagerPayload> {
const payload: PluginClientManagerPayload = {
operation: input.operation,
profileKey: input.profileKey,
artifactId: input.artifactId ?? "",
idempotencyKey: input.idempotencyKey
};
if (input.targetOS) {
payload.targetOS = input.targetOS;
}
if (input.targetArch) {
payload.targetArch = input.targetArch;
}
return createBridgeExecutionRequest({
requestId: input.requestId,
context: input.context,
action: "client-manager.request",
payload
});
}
export function parseArtifactReference(result: Record<string, string> | undefined): PluginArtifactReference | undefined {
if (!result) {
return undefined;