fix: improve terminal init error handling and websocket debug logging

This commit is contained in:
Mohamed Boudra
2025-12-03 13:26:28 +07:00
parent 43d2794e2d
commit f4f7790d07
5 changed files with 73 additions and 9 deletions
@@ -644,13 +644,15 @@ function AgentFlowModal({
providerModelRequestTimersRef.current.delete(serverId);
// Send request directly via WebSocket
const requestId = generateMessageId();
const message: WSInboundMessage = {
type: "session",
message: {
type: "request_provider_models",
type: "list_provider_models_request",
provider: selectedProvider,
cwd: options?.cwd,
} as any,
...(options?.cwd ? { cwd: options.cwd } : {}),
requestId,
},
};
sessionState.ws?.send(message);
};
+2
View File
@@ -345,6 +345,8 @@ export const ListProviderModelsRequestMessageSchema = z.object({
requestId: z.string().optional(),
});
// Legacy alias used by older clients; keep for compatibility
export const GitRepoInfoRequestMessageSchema = z.object({
type: z.literal("git_repo_info_request"),
cwd: z.string(),
+28 -3
View File
@@ -224,6 +224,8 @@ export class Session {
> | null = null;
private terminalTools: ToolSet | null = null;
private terminalManager: TerminalManager | null = null;
private terminalInitPromise: Promise<void> | null = null;
private terminalInitError: Error | null = null;
private agentMcpClient: Awaited<
ReturnType<typeof experimental_createMCPClient>
> | null = null;
@@ -265,8 +267,23 @@ export class Session {
this.ttsManager = new TTSManager(this.conversationId);
this.sttManager = new STTManager(this.conversationId);
// Initialize terminal + agent MCP clients asynchronously
void this.initializeTerminalMcp();
// Initialize terminal + agent MCP clients asynchronously, but keep promise handles to avoid orphaned rejections
this.terminalInitPromise = this.initializeTerminalMcp().catch((error) => {
const normalizedError =
error instanceof Error
? error
: new Error(
typeof error === "string"
? error
: "Unknown terminal initialization error"
);
this.terminalInitError = normalizedError;
console.error(
`[Session ${this.clientId}] Terminal MCP init failed:`,
normalizedError
);
});
void this.initializeAgentMcp();
this.subscribeToAgentEvents();
@@ -2013,7 +2030,15 @@ export class Session {
// Get live commands from terminal manager
let commands: any[] = [];
if (this.terminalManager) {
if (this.terminalInitPromise) {
await this.terminalInitPromise;
}
if (this.terminalInitError) {
console.error(
`[Session ${this.clientId}] Skipping command listing due to terminal init failure:`,
this.terminalInitError
);
} else if (this.terminalManager) {
try {
commands = await this.terminalManager.listCommands();
} catch (error) {
@@ -376,16 +376,21 @@ export async function createSession(name: string): Promise<TmuxSession | null> {
homeDir,
]);
// Disable automatic window renaming for all windows in the session
const session = await findSessionByName(name);
if (!session) {
return null;
}
// Disable automatic window renaming for all windows in the session (session target works; ':0' does not)
await executeTmux([
"set-window-option",
"-t",
name,
session.id,
"automatic-rename",
"off",
]);
return findSessionByName(name);
return session;
}
/**
@@ -211,9 +211,39 @@ export class VoiceAssistantWebSocketServer {
// Safe error logging - avoid crashing on large/circular objects
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const errorStack = error instanceof Error ? error.stack : undefined;
let rawPayload: string | null = null;
let parsedPayload: unknown = null;
try {
const buffer = Array.isArray(data)
? Buffer.concat(
data.map((item) =>
Buffer.isBuffer(item)
? item
: Buffer.from(item as ArrayBuffer)
)
)
: Buffer.isBuffer(data)
? data
: Buffer.from(data as ArrayBuffer);
rawPayload = buffer.toString();
parsedPayload = JSON.parse(rawPayload);
} catch (payloadError) {
rawPayload = rawPayload ?? "<unreadable>";
parsedPayload = parsedPayload ?? rawPayload;
console.error("[WS] Failed to decode raw payload:", payloadError);
}
const trimmedRawPayload =
typeof rawPayload === "string" && rawPayload.length > 2000
? `${rawPayload.slice(0, 2000)}... (truncated)`
: rawPayload;
console.error("[WS] Failed to parse/handle message:", {
message: errorMessage,
stack: errorStack,
rawPayload: trimmedRawPayload,
parsedPayload,
});
// Send error to client
this.sendToClient(