MAESTRO: Add thinking-chunk IPC event for streaming AI reasoning (Phase 3)

Implement the IPC infrastructure for Show Thinking feature:
- Emit 'thinking-chunk' event in process-manager.ts when partial text events arrive
- Forward thinking-chunk events to renderer via index.ts
- Add onThinkingChunk handler to preload.ts process API
- Add TypeScript interface declaration for onThinkingChunk

This enables the renderer to receive real-time streaming content from AI agents
(Claude Code, OpenCode, Codex) for display when the tab's showThinking setting
is enabled. The renderer decides whether to display based on per-tab settings.
This commit is contained in:
Pedram Amini
2025-12-22 18:25:23 -06:00
parent 58dcb73f22
commit e3f8beae45
3 changed files with 20 additions and 0 deletions

View File

@@ -2234,6 +2234,13 @@ function setupProcessListeners() {
mainWindow?.webContents.send('process:slash-commands', sessionId, slashCommands);
});
// Handle thinking/streaming content chunks from AI agents
// Emitted when agents produce partial text events (isPartial: true)
// Renderer decides whether to display based on tab's showThinking setting
processManager.on('thinking-chunk', (sessionId: string, content: string) => {
mainWindow?.webContents.send('process:thinking-chunk', sessionId, content);
});
// Handle stderr separately from runCommand (for clean command execution)
processManager.on('stderr', (sessionId: string, data: string) => {
mainWindow?.webContents.send('process:stderr', sessionId, data);

View File

@@ -130,6 +130,14 @@ contextBridge.exposeInMainWorld('maestro', {
ipcRenderer.on('process:slash-commands', handler);
return () => ipcRenderer.removeListener('process:slash-commands', handler);
},
// Thinking/streaming content chunks from AI agents
// Emitted when agents produce partial text events (isPartial: true)
// Renderer decides whether to display based on tab's showThinking setting
onThinkingChunk: (callback: (sessionId: string, content: string) => void) => {
const handler = (_: any, sessionId: string, content: string) => callback(sessionId, content);
ipcRenderer.on('process:thinking-chunk', handler);
return () => ipcRenderer.removeListener('process:thinking-chunk', handler);
},
// Remote command execution from web interface
// This allows web commands to go through the same code path as desktop commands
// inputMode is optional - if provided, renderer should use it instead of session state
@@ -1181,6 +1189,7 @@ export interface MaestroAPI {
onExit: (callback: (sessionId: string, code: number) => void) => () => void;
onSessionId: (callback: (sessionId: string, agentSessionId: string) => void) => () => void;
onSlashCommands: (callback: (sessionId: string, slashCommands: string[]) => void) => () => void;
onThinkingChunk: (callback: (sessionId: string, content: string) => void) => () => void;
onRemoteCommand: (callback: (sessionId: string, command: string) => void) => () => void;
onRemoteSwitchMode: (callback: (sessionId: string, mode: 'ai' | 'terminal') => void) => () => void;
onRemoteInterrupt: (callback: (sessionId: string) => void) => () => void;

View File

@@ -743,6 +743,10 @@ export class ProcessManager extends EventEmitter {
// Accumulate text from partial streaming events (OpenCode text messages)
// Skip error events - they're handled separately by detectErrorFromLine
if (event.type === 'text' && event.isPartial && event.text) {
// Emit thinking chunk for real-time display (let renderer decide to display based on tab setting)
this.emit('thinking-chunk', sessionId, event.text);
// Existing: accumulate for result fallback
managedProcess.streamedText = (managedProcess.streamedText || '') + event.text;
}