feat: auto-deploy guided servers on run registration

This commit is contained in:
npc0-hue
2026-07-28 16:57:09 +08:00
parent e2d0bc0595
commit 7f64765c1c
15 changed files with 191 additions and 55 deletions
+2 -32
View File
@@ -1,4 +1,4 @@
import { ChevronDown, ChevronRight, Download, MoonStar, PackageOpen, Pencil, Rocket, ShieldCheck, Sparkles, Square, UserRoundMinus, UserRoundPlus, WandSparkles } from "lucide-react";
import { ChevronDown, ChevronRight, Download, MoonStar, PackageOpen, Pencil, ShieldCheck, Sparkles, Square, UserRoundMinus, UserRoundPlus, WandSparkles } from "lucide-react";
import { type FormEvent, type ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import { platformApiClient } from "../api/client";
@@ -50,7 +50,7 @@ import { DiagnosticSummary, EmptyState, ErrorState, LoadingState, ResultBadge }
import type { PageComponentProps } from "../contracts/page";
import { jobCapabilityLabel } from "../contracts/jobPresentation";
import type { PluginBridgeAction, PluginBridgeManifestContract } from "../contracts/pluginBridge";
import { canDeployServer, canStartServer, canStopServer, defaultServerCreateForm, endpointLabel, pluginCreateInputDefaults, pluginLabel, runtimeBindingFields, serverMetadataFormFromInstance, type ServerCreateFormState, type ServerMetadataFormState } from "../contracts/serverManagement";
import { canStartServer, canStopServer, defaultServerCreateForm, endpointLabel, pluginCreateInputDefaults, pluginLabel, runtimeBindingFields, serverMetadataFormFromInstance, type ServerCreateFormState, type ServerMetadataFormState } from "../contracts/serverManagement";
import {
serverDetailSections,
serverIsOnline,
@@ -212,26 +212,6 @@ export function ServerDetailPage({ session, params, operations, onNavigate }: Pa
});
}
function requestDeployment(current: ServerInstanceResponse) {
const retry = current.state === "failed";
const intent = retry ? "重试部署服务器" : "部署服务器";
setConfirm({
title: intent,
description: `${retry ? "重新" : ""}部署 ${current.name}${current.id})将向已注册的专属 Run 提交安装任务,确认继续?`,
run: async () => {
const operationId = operations.begin({ intent, targetKind: "server", targetId: current.id, requester: session.displayName });
try {
const result = await platformApiClient.deployServerInstance(current.id, serverLifecycleCommandRequest(current, "deploy"));
operations.succeed(operationId, `部署任务 ${result.job.id}${result.job.capability})已派发`, result.job);
await refresh();
} catch (error) {
operations.fail(operationId, error instanceof Error ? error.message : "部署任务提交失败", operationId);
await refresh();
}
}
});
}
async function saveDeploymentWorkflow(form: ServerCreateFormState) {
if (instance.status !== "ready") return;
const current = instance.data;
@@ -296,16 +276,6 @@ export function ServerDetailPage({ session, params, operations, onNavigate }: Pa
</div>
<div className="action-strip">
<span className={cx("status-pill", statusClass(instance.data.state))}>{stateLabel(instance.data.state)}</span>
{canDeployServer(instance.data.state) && <button
type="button"
className="primary-command"
disabled={deployment.status !== "ready" || !deployment.data.mode || operations.isPending(instance.data.id, instance.data.state === "failed" ? "重试部署服务器" : "部署服务器")}
title={deployment.status !== "ready" || !deployment.data.mode ? "请先配置部署定义" : undefined}
onClick={() => requestDeployment(instance.data)}
>
<Rocket size={15} />
<span>{instance.data.state === "failed" ? "重试部署" : "部署"}</span>
</button>}
<button
type="button"
className="icon-command"