This commit is contained in:
lyon
2026-05-06 07:37:35 +08:00
parent ef70ca972b
commit 4fdca29df3
6 changed files with 263 additions and 11 deletions
+11 -1
View File
@@ -7,6 +7,7 @@ import { jobWithTail, listJobs, readJob, runJob } from "./src/jobs";
import { runChecks } from "./src/check";
import { runSsh } from "./src/ssh";
import { extractRemoteCliOptions, runRemoteCli } from "./src/remote";
import { runMicroserviceCommand } from "./src/microservices";
const remoteOptions = extractRemoteCliOptions(process.argv.slice(2));
const args = remoteOptions.args;
@@ -27,10 +28,14 @@ function help(): unknown {
{ command: "server logs [--tail-bytes N]", description: "Return bounded tails from file logs and docker logs." },
{ command: "server rebuild <backend-core|frontend|provider-gateway>", description: "Build first, then label-replace one service without Docker Compose v1 recreate fallback." },
{ command: "ssh <providerId> [ssh-like args...]", description: "Open a Host SSH / WSL SSH maintenance session through the provider-gateway bridge." },
{ command: "microservice list", description: "List UniDesk-managed microservices and their provider/runtime mapping." },
{ command: "microservice status <id>", description: "Show one microservice config, repository reference, backend mapping, and runtime status." },
{ command: "microservice health <id>", description: "Probe one microservice through backend-core -> provider-gateway HTTP proxy." },
{ command: "microservice proxy <id> <path>", description: "GET a private microservice backend path through the same frontend-only proxy used by WebUI." },
{ command: "job list", description: "List async jobs from .state/jobs." },
{ command: "job status <jobId|latest> [--tail-bytes N]", description: "Show job state with bounded stdout/stderr tails." },
{ command: "debug health", description: "Probe internal core, nodes, system/Docker status, frontend, provider ingress, and public boundary." },
{ command: "debug dispatch [providerId] [docker.ps|provider.upgrade|host.ssh|echo] [--wait-ms N]", description: "Submit a real internal-core dispatch request for CLI debugging." },
{ command: "debug dispatch [providerId] [docker.ps|provider.upgrade|host.ssh|microservice.http|echo] [--wait-ms N]", description: "Submit a real internal-core dispatch request for CLI debugging." },
{ command: "debug task <taskId|latest>", description: "Read a dispatched task record from internal core for CLI debugging." },
{ command: "e2e run", description: "Run public frontend/provider, internal core/database, and Playwright login E2E checks." },
],
@@ -151,6 +156,11 @@ async function main(): Promise<void> {
}
}
if (top === "microservice") {
emitJson(commandName, await runMicroserviceCommand(config, args.slice(1)));
return;
}
if (top === "job") {
if (sub === "list") {
emitJson(commandName, { jobs: listJobs() });
+1 -1
View File
@@ -1,7 +1,7 @@
import { runCommand } from "./command";
import { type UniDeskConfig, repoRoot } from "./config";
export const dispatchCommands = ["docker.ps", "provider.upgrade", "host.ssh", "echo"] as const;
export const dispatchCommands = ["docker.ps", "provider.upgrade", "host.ssh", "microservice.http", "echo"] as const;
export type DebugDispatchCommand = typeof dispatchCommands[number];
export function isDebugDispatchCommand(value: unknown): value is DebugDispatchCommand {
+27 -1
View File
@@ -354,6 +354,28 @@ async function remoteDebugTask(session: FrontendSession, args: string[]): Promis
return { transport: "frontend", tasksResponse, taskId, task: task ?? null };
}
async function remoteMicroservice(session: FrontendSession, args: string[]): Promise<unknown> {
const action = args[1] ?? "list";
const id = args[2];
const path = args[3];
if (action === "list") {
return { transport: "frontend", response: await frontendJson(session, "/api/microservices", undefined, 12_000) };
}
if ((action === "status" || action === "health") && id !== undefined) {
return {
transport: "frontend",
response: await frontendJson(session, `/api/microservices/${encodeURIComponent(id)}/${action}`, undefined, 18_000),
};
}
if (action === "proxy" && id !== undefined && path !== undefined && path.startsWith("/")) {
return {
transport: "frontend",
response: await frontendJson(session, `/api/microservices/${encodeURIComponent(id)}/proxy${path}`, undefined, 24_000),
};
}
throw new Error("remote microservice command must be: microservice list | status <id> | health <id> | proxy <id> <path>");
}
async function runRemoteSshOverFrontend(session: FrontendSession, providerId: string | undefined, args: string[]): Promise<number> {
if (!providerId) throw new Error("remote ssh requires provider id, for example: bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh D601 hostname");
const parsed = parseSshArgs(args);
@@ -399,7 +421,7 @@ async function runRemoteCliOverFrontend(options: RemoteCliOptions, config: UniDe
emitRemoteJson(name, {
transport: "frontend",
baseUrl: session.baseUrl,
commands: ["debug health", "debug dispatch", "debug task", "ssh <providerId> <command>"],
commands: ["debug health", "debug dispatch", "debug task", "ssh <providerId> <command>", "microservice list", "microservice status <id>", "microservice health <id>", "microservice proxy <id> <path>"],
});
return 0;
}
@@ -415,6 +437,10 @@ async function runRemoteCliOverFrontend(options: RemoteCliOptions, config: UniDe
emitRemoteJson(name, await remoteDebugTask(session, args));
return 0;
}
if (top === "microservice") {
emitRemoteJson(name, await remoteMicroservice(session, args));
return 0;
}
if (top === "ssh") {
return await runRemoteSshOverFrontend(session, sub, args.slice(2));
}