fix: improve terminal init error handling and websocket debug logging
This commit is contained in:
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user