From f878e5e63577028129e43d805f599de12b389c9e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 7 Dec 2025 15:09:26 +0000 Subject: [PATCH] fix(mac): keep pnpm health output json-safe --- apps/macos/Sources/Clawdis/HealthStore.swift | 7 +++++-- apps/macos/Sources/Clawdis/Utilities.swift | 3 ++- .../ClawdisIPCTests/CommandResolverTests.swift | 15 ++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/macos/Sources/Clawdis/HealthStore.swift b/apps/macos/Sources/Clawdis/HealthStore.swift index 47cde6035..2a80335b3 100644 --- a/apps/macos/Sources/Clawdis/HealthStore.swift +++ b/apps/macos/Sources/Clawdis/HealthStore.swift @@ -99,10 +99,13 @@ final class HealthStore: ObservableObject { return } + var env = ProcessInfo.processInfo.environment + env["PATH"] = CommandResolver.preferredPaths().joined(separator: ":") + let response = await ShellRunner.run( command: CommandResolver.clawdisCommand(subcommand: "health", extraArgs: ["--json"]), - cwd: nil, - env: nil, + cwd: CommandResolver.projectRootPath(), + env: env, timeout: 15) guard response.ok, let data = response.payload, !data.isEmpty else { diff --git a/apps/macos/Sources/Clawdis/Utilities.swift b/apps/macos/Sources/Clawdis/Utilities.swift index 2393e5ccd..76096769c 100644 --- a/apps/macos/Sources/Clawdis/Utilities.swift +++ b/apps/macos/Sources/Clawdis/Utilities.swift @@ -250,7 +250,8 @@ enum CommandResolver { } } if let pnpm = self.findExecutable(named: "pnpm") { - return [pnpm, "clawdis", subcommand] + extraArgs + // Use --silent to avoid pnpm lifecycle banners that would corrupt JSON outputs. + return [pnpm, "--silent", "clawdis", subcommand] + extraArgs } return ["clawdis", subcommand] + extraArgs } diff --git a/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift b/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift index 3f956099a..c034f9afa 100644 --- a/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift +++ b/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift @@ -54,7 +54,20 @@ import Testing let cmd = CommandResolver.clawdisCommand(subcommand: "rpc") - #expect(cmd.prefix(3).elementsEqual([pnpmPath.path, "clawdis", "rpc"])) + #expect(cmd.prefix(4).elementsEqual([pnpmPath.path, "--silent", "clawdis", "rpc"])) + } + + @Test func pnpmKeepsExtraArgsAfterSubcommand() async throws { + let tmp = try makeTempDir() + CommandResolver.setProjectRoot(tmp.path) + + let pnpmPath = tmp.appendingPathComponent("node_modules/.bin/pnpm") + try makeExec(at: pnpmPath) + + let cmd = CommandResolver.clawdisCommand(subcommand: "health", extraArgs: ["--json", "--timeout", "5"]) + + #expect(cmd.prefix(5).elementsEqual([pnpmPath.path, "--silent", "clawdis", "health", "--json"])) + #expect(cmd.suffix(2).elementsEqual(["--timeout", "5"])) } @Test func preferredPathsStartWithProjectNodeBins() async throws {