























@@ -47,6 +47,7 @@ describe("tryRouteCli", () => {
4747let loggingState: typeof import("../logging/state.js").loggingState;
4848let originalDisableRouteFirst: string | undefined;
4949let originalHideBanner: string | undefined;
50+let originalLogLevel: string | undefined;
5051let originalForceStderr: boolean;
51525253beforeAll(async () => {
@@ -58,8 +59,10 @@ describe("tryRouteCli", () => {
5859vi.clearAllMocks();
5960originalDisableRouteFirst = process.env.OPENCLAW_DISABLE_ROUTE_FIRST;
6061originalHideBanner = process.env.OPENCLAW_HIDE_BANNER;
62+originalLogLevel = process.env.OPENCLAW_LOG_LEVEL;
6163delete process.env.OPENCLAW_DISABLE_ROUTE_FIRST;
6264delete process.env.OPENCLAW_HIDE_BANNER;
65+delete process.env.OPENCLAW_LOG_LEVEL;
6366originalForceStderr = loggingState.forceConsoleToStderr;
6467loggingState.forceConsoleToStderr = false;
6568findRoutedCommandMock.mockReturnValue({
@@ -82,6 +85,11 @@ describe("tryRouteCli", () => {
8285} else {
8386process.env.OPENCLAW_HIDE_BANNER = originalHideBanner;
8487}
88+if (originalLogLevel === undefined) {
89+delete process.env.OPENCLAW_LOG_LEVEL;
90+} else {
91+process.env.OPENCLAW_LOG_LEVEL = originalLogLevel;
92+}
8593});
86948795it("keeps config guard for routed status --json commands", async () => {
@@ -166,6 +174,11 @@ describe("tryRouteCli", () => {
166174});
167175168176it("routes status when root options precede the command", async () => {
177+const capturedLogLevels: Array<string | undefined> = [];
178+ensureConfigReadyMock.mockImplementationOnce(async () => {
179+capturedLogLevels.push(process.env.OPENCLAW_LOG_LEVEL);
180+});
181+169182await expect(tryRouteCli(["node", "openclaw", "--log-level", "debug", "status"])).resolves.toBe(
170183true,
171184);
@@ -181,6 +194,50 @@ describe("tryRouteCli", () => {
181194expect(ensurePluginRegistryLoadedMock).toHaveBeenCalledWith({
182195scope: "channels",
183196});
197+expect(capturedLogLevels).toEqual(["debug"]);
198+expect(process.env.OPENCLAW_LOG_LEVEL).toBe("debug");
199+});
200+201+it("applies routed log level options after the command", async () => {
202+const capturedLogLevels: Array<string | undefined> = [];
203+ensureConfigReadyMock.mockImplementationOnce(async () => {
204+capturedLogLevels.push(process.env.OPENCLAW_LOG_LEVEL);
205+});
206+207+await expect(tryRouteCli(["node", "openclaw", "status", "--log-level=trace"])).resolves.toBe(
208+true,
209+);
210+211+expect(ensureConfigReadyMock).toHaveBeenCalledTimes(1);
212+expect(runRouteMock).toHaveBeenCalledTimes(1);
213+expect(capturedLogLevels).toEqual(["trace"]);
214+expect(process.env.OPENCLAW_LOG_LEVEL).toBe("trace");
215+});
216+217+it("uses the last valid routed log level option", async () => {
218+await expect(
219+tryRouteCli(["node", "openclaw", "--log-level", "debug", "status", "--log-level=trace"]),
220+).resolves.toBe(true);
221+222+expect(ensureConfigReadyMock).toHaveBeenCalledTimes(1);
223+expect(runRouteMock).toHaveBeenCalledTimes(1);
224+expect(process.env.OPENCLAW_LOG_LEVEL).toBe("trace");
225+});
226+227+it.each([
228+["invalid value", ["node", "openclaw", "status", "--log-level", "verbose"]],
229+["missing value", ["node", "openclaw", "status", "--log-level"]],
230+[
231+"later invalid value",
232+["node", "openclaw", "--log-level", "debug", "status", "--log-level", "verbose"],
233+],
234+])("falls back for %s routed log level options before bootstrap", async (_name, argv) => {
235+await expect(tryRouteCli(argv)).resolves.toBe(false);
236+237+expect(ensureConfigReadyMock).not.toHaveBeenCalled();
238+expect(ensurePluginRegistryLoadedMock).not.toHaveBeenCalled();
239+expect(runRouteMock).not.toHaveBeenCalled();
240+expect(process.env.OPENCLAW_LOG_LEVEL).toBeUndefined();
184241});
185242186243it("respects OPENCLAW_HIDE_BANNER for routed commands", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。