Skip to content

Commit 8404fd8

Browse files
committed
fix(logging): 重定向 JS 日志到 stderr 以避免污染 stdout #536
在 ACP 代理模式下,stdout 专用于 JSON-RPC 通信。修改 Kotlin 和 TypeScript 代码,将所有 console 方法重定向到 console.error(stderr),防止日志输出干扰 JSON-RPC 消息。
1 parent be1236a commit 8404fd8

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/logging/PlatformLogging.js.kt

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ package cc.unitmesh.agent.logging
33
/**
44
* JavaScript implementation of platform-specific logging initialization
55
* JS uses console logging, no file storage needed
6+
*
7+
* IMPORTANT: For ACP agent mode, all logs should go to stderr (console.error)
8+
* to avoid polluting stdout which is used for JSON-RPC communication.
69
*/
710
actual fun initializePlatformLogging(config: LoggingConfig) {
8-
// JavaScript platform uses console logging by default
9-
// No additional configuration needed
11+
// Redirect all console.log/info/warn to console.error for stderr output
12+
// This ensures that only JSON-RPC messages go to stdout
13+
redirectConsoleToStderr()
1014
}
1115

1216
/**
@@ -16,3 +20,22 @@ actual fun initializePlatformLogging(config: LoggingConfig) {
1620
actual fun getPlatformLogDirectory(): String {
1721
return "console-only" // JS platform doesn't support file logging
1822
}
23+
24+
/**
25+
* Redirect console logging to stderr
26+
* This is critical for ACP agent mode where stdout is used for JSON-RPC
27+
*/
28+
@Suppress("UNUSED_VARIABLE")
29+
private fun redirectConsoleToStderr() {
30+
// Use js() to execute raw JavaScript code
31+
val result = js("""
32+
(function() {
33+
// Redirect all console methods to console.error (stderr)
34+
console.log = console.error;
35+
console.info = console.error;
36+
console.warn = console.error;
37+
console.debug = console.error;
38+
return true;
39+
})()
40+
""")
41+
}

mpp-ui/src/jsMain/typescript/agents/acp/AcpAgentServer.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ class AcpSessionRenderer {
335335
* This is the entry point for `xiuper acp` command.
336336
*/
337337
export async function startAcpAgentServer(): Promise<void> {
338+
// CRITICAL: Redirect all console output to stderr BEFORE any Kotlin code runs
339+
// This prevents Kotlin logging from polluting stdout (which is used for JSON-RPC)
340+
redirectConsoleToStderr();
341+
338342
console.error('[ACP Agent] Starting AutoDev Xiuper ACP Agent Server...');
339343

340344
// For ACP ndJsonStream: first param is output (where we write), second is input (where we read)
@@ -355,3 +359,20 @@ export async function startAcpAgentServer(): Promise<void> {
355359
await connection.closed;
356360
console.error('[ACP Agent] Connection closed.');
357361
}
362+
363+
/**
364+
* Redirect all console methods to stderr.
365+
* This is critical for ACP mode where stdout is reserved for JSON-RPC messages.
366+
*/
367+
function redirectConsoleToStderr(): void {
368+
// Save original console.error
369+
const originalError = console.error;
370+
371+
// Redirect all console methods to stderr
372+
console.log = originalError;
373+
console.info = originalError;
374+
console.warn = originalError;
375+
console.debug = originalError;
376+
377+
// console.error already goes to stderr
378+
}

0 commit comments

Comments
 (0)