fix: log bootstrap errors to daemon.log and add layout debug logging
- Log fatal errors during daemon bootstrap and startup to pino (daemon.log) instead of only writing to stderr, which is invisible on Windows desktop - Delay process.exit to let pino async streams flush - Make voice MCP bridge script resolution non-fatal (warn + disable instead of crashing the daemon) - Add PASEO_ELECTRON_FLAGS env var for passing Chromium flags on Linux - Add layout debug logging to AppContainer for diagnosing sidebar issues
This commit is contained in:
@@ -133,21 +133,28 @@ import { resolveVoiceMcpBridgeFromRuntime } from "./voice-mcp-bridge-command.js"
|
||||
|
||||
type AgentMcpTransportMap = Map<string, StreamableHTTPServerTransport>;
|
||||
|
||||
function resolveVoiceMcpBridgeCommand(logger: Logger): { command: string; baseArgs: string[] } {
|
||||
const decision = resolveVoiceMcpBridgeFromRuntime({
|
||||
bootstrapModuleUrl: import.meta.url,
|
||||
execPath: process.execPath,
|
||||
explicitScriptPath: process.env.PASEO_MCP_STDIO_SOCKET_BRIDGE_SCRIPT,
|
||||
});
|
||||
logger.info(
|
||||
{
|
||||
source: decision.source,
|
||||
command: decision.resolved.command,
|
||||
baseArgs: decision.resolved.baseArgs,
|
||||
},
|
||||
"Resolved voice MCP bridge command",
|
||||
);
|
||||
return decision.resolved;
|
||||
function resolveVoiceMcpBridgeCommand(
|
||||
logger: Logger,
|
||||
): { command: string; baseArgs: string[] } | null {
|
||||
try {
|
||||
const decision = resolveVoiceMcpBridgeFromRuntime({
|
||||
bootstrapModuleUrl: import.meta.url,
|
||||
execPath: process.execPath,
|
||||
explicitScriptPath: process.env.PASEO_MCP_STDIO_SOCKET_BRIDGE_SCRIPT,
|
||||
});
|
||||
logger.info(
|
||||
{
|
||||
source: decision.source,
|
||||
command: decision.resolved.command,
|
||||
baseArgs: decision.resolved.baseArgs,
|
||||
},
|
||||
"Resolved voice MCP bridge command",
|
||||
);
|
||||
return decision.resolved;
|
||||
} catch (err) {
|
||||
logger.warn({ err }, "Voice MCP bridge script not available — voice MCP via stdio disabled");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export type PaseoOpenAIConfig = OpenAiSpeechProviderConfig;
|
||||
@@ -669,14 +676,16 @@ export async function createPaseoDaemon(
|
||||
speechService,
|
||||
terminalManager,
|
||||
{
|
||||
voiceAgentMcpStdio: {
|
||||
command: voiceMcpBridgeCommand.command,
|
||||
baseArgs: [...voiceMcpBridgeCommand.baseArgs],
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: "1",
|
||||
PASEO_HOME: config.paseoHome,
|
||||
},
|
||||
},
|
||||
voiceAgentMcpStdio: voiceMcpBridgeCommand
|
||||
? {
|
||||
command: voiceMcpBridgeCommand.command,
|
||||
baseArgs: [...voiceMcpBridgeCommand.baseArgs],
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: "1",
|
||||
PASEO_HOME: config.paseoHome,
|
||||
},
|
||||
}
|
||||
: null,
|
||||
ensureVoiceMcpSocketForAgent: (agentId) =>
|
||||
voiceMcpBridgeManager?.ensureBridgeForCaller(agentId) ??
|
||||
Promise.reject(new Error("Voice MCP bridge manager is not initialized")),
|
||||
|
||||
@@ -143,6 +143,7 @@ async function main() {
|
||||
logger.error({ pid: err.existingLock?.pid }, err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
logger.fatal({ err }, "Daemon bootstrap failed");
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -153,6 +154,7 @@ async function main() {
|
||||
logger.error({ pid: err.existingLock?.pid }, err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
logger.fatal({ err }, "Daemon failed to start listening");
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -171,10 +173,9 @@ async function main() {
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
if (process.env.PASEO_DEBUG === "1") {
|
||||
process.stderr.write(`${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
|
||||
} else {
|
||||
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
||||
}
|
||||
process.exit(1);
|
||||
process.stderr.write(`${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
|
||||
// Give pino streams a moment to flush the fatal log entry to daemon.log
|
||||
// before the process exits. Without this, async file streams may lose the
|
||||
// last few entries that explain why the daemon crashed.
|
||||
setTimeout(() => process.exit(1), 200);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user