mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-22 02:15:26 -06:00
fix(cli): render task flow JSON failures (#127080)
* fix(cli): render task flow JSON failures * test(cli): stabilize entry console capture * fix(cli): keep JSON terminal resets off stdout * fix(cli): keep task JSON resets off stdout
This commit is contained in:
committed by
GitHub
parent
5edc2a7f21
commit
32fb2fc766
@@ -318,6 +318,28 @@ describe("flows commands", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps terminal reset bytes off stdout for JSON lookup failures", async () => {
|
||||
await withTaskFlowCommandStateDir(async () => {
|
||||
const runtime = createRuntime();
|
||||
|
||||
await flowsShowCommand({ lookup: "missing-flow", json: true }, runtime);
|
||||
|
||||
expect(runtime.error).not.toHaveBeenCalled();
|
||||
expect(runtime.writeJson).toHaveBeenCalledWith(
|
||||
{
|
||||
ok: false,
|
||||
error: {
|
||||
type: "cli_error",
|
||||
message:
|
||||
"TaskFlow not found: missing-flow. Run openclaw tasks flow list to see recent flow ids.",
|
||||
},
|
||||
},
|
||||
2,
|
||||
);
|
||||
expect(runtime.exit).toHaveBeenCalledWith(1, { resetStream: process.stderr });
|
||||
});
|
||||
});
|
||||
|
||||
it("shows one TaskFlow with linked task details in text mode", async () => {
|
||||
await withTaskFlowCommandStateDir(async () => {
|
||||
const flow = createManagedTaskFlow({
|
||||
|
||||
@@ -7,10 +7,10 @@ import { sanitizeTerminalText } from "../../packages/terminal-core/src/safe-text
|
||||
import { isRich, theme } from "../../packages/terminal-core/src/theme.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import { parseCliEnumFilter } from "../cli/enum-filter.js";
|
||||
import { formatCliJsonFailure } from "../cli/failure-output.js";
|
||||
import { getRuntimeConfig } from "../config/config.js";
|
||||
import { info } from "../globals.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { writeRuntimeJson } from "../runtime.js";
|
||||
import { type RuntimeEnv, writeRuntimeJson } from "../runtime.js";
|
||||
import { listTasksForFlowId } from "../tasks/runtime-internal.js";
|
||||
import { cancelFlowById, getFlowTaskSummary } from "../tasks/task-executor.js";
|
||||
import {
|
||||
@@ -211,8 +211,13 @@ export async function flowsShowCommand(
|
||||
) {
|
||||
const flow = resolveTaskFlowForLookupToken(opts.lookup);
|
||||
if (!flow) {
|
||||
runtime.error(formatFlowLookupMiss(opts.lookup));
|
||||
runtime.exit(1);
|
||||
const message = formatFlowLookupMiss(opts.lookup);
|
||||
if (opts.json) {
|
||||
writeRuntimeJson(runtime, formatCliJsonFailure(message));
|
||||
} else {
|
||||
runtime.error(message);
|
||||
}
|
||||
runtime.exit(1, opts.json ? { resetStream: process.stderr } : undefined);
|
||||
return;
|
||||
}
|
||||
const tasks = listTasksForFlowId(flow.flowId);
|
||||
|
||||
@@ -811,6 +811,7 @@ describe("tasks commands", () => {
|
||||
message: expect.stringContaining("Task not found: missing"),
|
||||
},
|
||||
});
|
||||
expect(jsonLookupRuntime.exit).toHaveBeenCalledWith(1, { resetStream: process.stderr });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ export async function tasksShowCommand(
|
||||
} else {
|
||||
runtime.error(message);
|
||||
}
|
||||
runtime.exit(1);
|
||||
runtime.exit(1, opts.json ? { resetStream: process.stderr } : undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { ExpectedCliError } from "./cli/failure-output.js";
|
||||
import { runMainOrRootHelp } from "./entry.js";
|
||||
import { enableConsoleCapture } from "./logging.js";
|
||||
|
||||
describe("entry run-main boundary", () => {
|
||||
it("retains JSON console routing through process finalization", async () => {
|
||||
@@ -25,6 +26,7 @@ describe("entry run-main boundary", () => {
|
||||
humanOutput: message,
|
||||
machineOutput: message,
|
||||
});
|
||||
enableConsoleCapture();
|
||||
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
process.exitCode = undefined;
|
||||
|
||||
|
||||
@@ -295,6 +295,27 @@ describe("cli json stdout contract", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("renders a missing TaskFlow as one canonical JSON document without stderr", async () => {
|
||||
await withTempHome(
|
||||
async (tempHome) => {
|
||||
const result = runBuiltCli(tempHome, ["tasks", "flow", "show", "missing-flow", "--json"]);
|
||||
|
||||
expect(result.status, result.stderr).toBe(1);
|
||||
expect(result.stdout, result.stderr).not.toBe("");
|
||||
expect(JSON.parse(result.stdout)).toEqual({
|
||||
ok: false,
|
||||
error: {
|
||||
type: "cli_error",
|
||||
message:
|
||||
"TaskFlow not found: missing-flow. Run openclaw tasks flow list to see recent flow ids.",
|
||||
},
|
||||
});
|
||||
expect(result.stderr).toBe("");
|
||||
},
|
||||
{ prefix: "openclaw-task-flow-json-failure-e2e-" },
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ name: "qr", command: ["qr"] },
|
||||
{ name: "clawbot qr", command: ["clawbot", "qr"] },
|
||||
|
||||
Reference in New Issue
Block a user