diff --git a/packages/coding-agent/src/system-prompt.test.ts b/packages/coding-agent/src/system-prompt.test.ts index 67308506844..8aba25d6b26 100644 --- a/packages/coding-agent/src/system-prompt.test.ts +++ b/packages/coding-agent/src/system-prompt.test.ts @@ -189,3 +189,41 @@ describe.skipIf(process.platform !== "linux")("system prompt CPU model", () => { } }); }); + +// #4755: on non-Linux hosts getCpuModel must fall back to os.cpus()[0].model +// (Linux keeps the /proc/cpuinfo path from #4717 to avoid the #4712 stall). +describe.skipIf(process.platform === "linux")("system prompt CPU model on non-Linux", () => { + it("populates CPU model via os.cpus() on macOS/Windows", async () => { + const cpus = spyOn(os, "cpus").mockImplementation(() => [ + { + model: "Synthetic Non-Linux CPU", + speed: 0, + times: { user: 0, nice: 0, sys: 0, idle: 0, irq: 0 }, + }, + ]); + try { + const result = await buildSystemPrompt({ + resolvedCustomPrompt: "Base prompt", + contextFiles: [], + skills: [], + rules: [], + workspaceTree: { + rootPath: import.meta.dir, + rendered: "", + truncated: false, + totalLines: 0, + agentsMdFiles: [], + }, + activeRepoContext: null, + }); + + expect(cpus).toHaveBeenCalled(); + // CPU model is rendered into the environment/workstation block in + // the systemPrompt string array, not returned as a separate field. + const blockWithCpu = result.systemPrompt.find(s => s.includes("Synthetic Non-Linux CPU")); + expect(blockWithCpu).toBeDefined(); + } finally { + cpus.mockRestore(); + } + }); +}); diff --git a/packages/coding-agent/src/system-prompt.ts b/packages/coding-agent/src/system-prompt.ts index e64a9858726..299be97361c 100644 --- a/packages/coding-agent/src/system-prompt.ts +++ b/packages/coding-agent/src/system-prompt.ts @@ -251,7 +251,19 @@ async function getCachedGpu(): Promise { } async function getCpuModel(): Promise { - if (process.platform !== "linux") return undefined; + if (process.platform !== "linux") { + // #4717 switched Linux to /proc/cpuinfo to avoid an os.cpus() startup + // stall (#4712). On macOS/Windows the os.cpus() stall does not occur, + // so fall back to it here to keep the CPU model populated on every + // platform — otherwise the workstation block drops `CPU:` on non-Linux + // hosts (#4755). + try { + return os.cpus()[0]?.model || undefined; + } catch (error) { + logger.debug("Could not read CPU model via os.cpus()", { error: String(error) }); + return undefined; + } + } try { const cpuInfo = await Bun.file("/proc/cpuinfo").text(); const match = /^model name\s*:\s*(.+)$/m.exec(cpuInfo);