feat: aggregate Workbench native status

This commit is contained in:
root
2026-07-21 02:29:19 +02:00
parent 4315611c02
commit 7f6c329206
3 changed files with 55 additions and 1 deletions
+3 -1
View File
@@ -1,10 +1,11 @@
import type { WorkbenchCommand } from "../../internal/workbench/contracts.ts";
import { workbenchRuntime } from "../../internal/workbench/runtime.ts";
import { workbenchNativeServiceCommand } from "./workbench-native-service.ts";
import { workbenchNativeServiceCommand, workbenchNativeServicesStatus } from "./workbench-native-service.ts";
export async function runWorkbenchCli(argv: string[], env: Record<string, string | undefined> = process.env) {
const parsed = parse(argv);
if (parsed.help || parsed.positionals.length === 0) return help();
if (parsed.positionals[0] === "service" && parsed.positionals[1] === "status") return workbenchNativeServicesStatus({ cwd: process.cwd(), env });
if (parsed.positionals[0] === "service") return workbenchNativeServiceCommand({ service: parsed.positionals[1], action: parsed.positionals[2] ?? "status", cwd: process.cwd(), env });
if (parsed.positionals[0] === "events" && parsed.positionals[1] === "inspect") return inspectEvents(parsed, env);
const command = commandFrom(parsed, env);
@@ -29,6 +30,7 @@ function help() {
"hwlab-cli workbench turn submit --actor-id ID --session-id ID --message TEXT [--trace-id ID] [--over-api]",
"hwlab-cli workbench events inspect --session-id ID [--trace-id ID] --over-api [--timeout-ms MS] [--wait-for user,backend,assistant,terminal,final] [--min-events N] [--timing-detail summary|full]",
"hwlab-cli workbench turn cancel --actor-id ID --trace-id ID [--over-api]",
"hwlab-cli workbench service status",
"hwlab-cli workbench service api|worker|web start|stop|restart|status|logs"
],
transportContract: "--over-api only changes transport; --overapi is unsupported",
@@ -0,0 +1,28 @@
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { expect, test } from "bun:test";
import { workbenchNativeServicesStatus } from "./workbench-native-service.ts";
test("aggregates all Workbench native service states in one query", async () => {
const cwd = mkdtempSync(join(tmpdir(), "hwlab-workbench-status-"));
try {
const result = await workbenchNativeServicesStatus({
cwd,
env: { WORKBENCH_NATIVE_SERVICE_STATE_DIR: ".state/services" }
});
expect(result).toMatchObject({
ok: false,
operation: "workbench.service.status",
status: "stopped",
summary: { total: 3, running: 0, unavailable: 3 },
valuesPrinted: false
});
expect(Object.keys(result.services).sort()).toEqual(["api", "web", "worker"]);
} finally {
rmSync(cwd, { recursive: true, force: true });
}
});
+24
View File
@@ -4,6 +4,30 @@ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
import path from "node:path";
type ServiceName = "api" | "worker" | "web";
const SERVICE_NAMES: ServiceName[] = ["api", "worker", "web"];
export async function workbenchNativeServicesStatus(input: { cwd: string; env: Record<string, string | undefined> }) {
const results = await Promise.all(SERVICE_NAMES.map((service) => workbenchNativeServiceCommand({
service,
action: "status",
cwd: input.cwd,
env: input.env
})));
const services = Object.fromEntries(results.map((result) => [result.service, result]));
const runningCount = results.filter((result) => result.ok).length;
return {
ok: runningCount === SERVICE_NAMES.length,
operation: "workbench.service.status",
status: runningCount === SERVICE_NAMES.length ? "running" : runningCount === 0 ? "stopped" : "degraded",
summary: {
total: SERVICE_NAMES.length,
running: runningCount,
unavailable: SERVICE_NAMES.length - runningCount
},
services,
valuesPrinted: false
};
}
export async function workbenchNativeServiceCommand(input: { service: string; action: string; cwd: string; env: Record<string, string | undefined> }) {
const service = validService(input.service);