From 88da68d8a2b02cc08b085ea3fb3936658e7def10 Mon Sep 17 00:00:00 2001 From: dotta Date: Wed, 18 Mar 2026 08:32:59 -0500 Subject: [PATCH] Log workspace warnings to stdout Co-Authored-By: Paperclip --- .../src/__tests__/heartbeat-workspace-session.test.ts | 10 ++++++++++ server/src/services/heartbeat.ts | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/server/src/__tests__/heartbeat-workspace-session.test.ts b/server/src/__tests__/heartbeat-workspace-session.test.ts index 1be5cbb7..79d781e9 100644 --- a/server/src/__tests__/heartbeat-workspace-session.test.ts +++ b/server/src/__tests__/heartbeat-workspace-session.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest"; import type { agents } from "@paperclipai/db"; import { resolveDefaultAgentWorkspaceDir } from "../home-paths.js"; import { + formatRuntimeWorkspaceWarningLog, prioritizeProjectWorkspaceCandidatesForRun, parseSessionCompactionPolicy, resolveRuntimeSessionParamsForWorkspace, @@ -181,6 +182,15 @@ describe("shouldResetTaskSessionForWake", () => { }); }); +describe("formatRuntimeWorkspaceWarningLog", () => { + it("emits informational workspace warnings on stdout", () => { + expect(formatRuntimeWorkspaceWarningLog("Using fallback workspace")).toEqual({ + stream: "stdout", + chunk: "[paperclip] Using fallback workspace\n", + }); + }); +}); + describe("prioritizeProjectWorkspaceCandidatesForRun", () => { it("moves the explicitly selected workspace to the front", () => { const rows = [ diff --git a/server/src/services/heartbeat.ts b/server/src/services/heartbeat.ts index 31905a5f..8e338b90 100644 --- a/server/src/services/heartbeat.ts +++ b/server/src/services/heartbeat.ts @@ -497,6 +497,13 @@ export function shouldResetTaskSessionForWake( return false; } +export function formatRuntimeWorkspaceWarningLog(warning: string) { + return { + stream: "stdout" as const, + chunk: `[paperclip] ${warning}\n`, + }; +} + function describeSessionResetReason( contextSnapshot: Record | null | undefined, ) { @@ -2055,7 +2062,8 @@ export function heartbeatService(db: Db) { }); }; for (const warning of runtimeWorkspaceWarnings) { - await onLog("stderr", `[paperclip] ${warning}\n`); + const logEntry = formatRuntimeWorkspaceWarningLog(warning); + await onLog(logEntry.stream, logEntry.chunk); } const adapterEnv = Object.fromEntries( Object.entries(parseObject(resolvedConfig.env)).filter(