@@ -28,7 +28,6 @@ import { createBashTool } from "@/services/tools/bash";
2828import type { BashToolResult } from "@/types/tools" ;
2929import { secretsToRecord } from "@/types/secrets" ;
3030import { DisposableTempDir } from "@/services/tempDir" ;
31- import type { WorkspaceMetaEvent } from "@/types/workspace" ;
3231
3332/**
3433 * IpcMain - Manages all IPC handlers and service coordination
@@ -54,28 +53,14 @@ export class IpcMain {
5453 { chat : ( ) => void ; metadata : ( ) => void }
5554 > ( ) ;
5655 private mainWindow : BrowserWindow | null = null ;
57- // Buffer of streaming meta events keyed by workspaceId. Used to replay to late subscribers.
58- private readonly metaEventBuffer : Map < string , WorkspaceMetaEvent [ ] > = new Map <
59- string ,
60- WorkspaceMetaEvent [ ]
61- > ( ) ;
62-
63- // Helper to emit a workspace meta event to the renderer and buffer it for replay
64- private emitWorkspaceMeta ( event : WorkspaceMetaEvent ) : void {
65- if ( ! event ?. workspaceId ) return ;
66- const arr = this . metaEventBuffer . get ( event . workspaceId ) ?? [ ] ;
67- arr . push ( event ) ;
68- this . metaEventBuffer . set ( event . workspaceId , arr ) ;
69- this . mainWindow ?. webContents . send ( IPC_CHANNELS . WORKSPACE_STREAM_META , event ) ;
70- }
7156
7257 // Run optional .cmux/init hook for a newly created workspace and stream its output
7358 private async runWorkspaceInitHook ( params : {
7459 projectPath : string ;
7560 worktreePath : string ;
7661 workspaceId : string ;
7762 } ) : Promise < void > {
78- // Non-blocking fire-and-forget; errors are reported via meta stream
63+ // Non-blocking fire-and-forget; errors are reported via chat stream
7964 try {
8065 const hookPath = path . join ( params . projectPath , ".cmux" , "init" ) ;
8166 // Check if hook exists
@@ -87,12 +72,13 @@ export class IpcMain {
8772 return ; // Nothing to do
8873 }
8974
90- // Emit start event
91- this . emitWorkspaceMeta ( {
92- type : "workspace-init- start" ,
93- workspaceId : params . workspaceId ,
94- timestamp : Date . now ( ) ,
75+ const session = this . getOrCreateSession ( params . workspaceId ) ;
76+
77+ // Emit start event via chat stream
78+ session . emitChatEvent ( {
79+ type : "init-start" ,
9580 hookPath,
81+ timestamp : Date . now ( ) ,
9682 } ) ;
9783
9884 // Spawn bash to run the hook in the new worktree directory
@@ -119,11 +105,11 @@ export class IpcMain {
119105 const partial = lines . pop ( ) ?? "" ;
120106 for ( const line of lines ) {
121107 if ( line . length === 0 ) continue ;
122- this . emitWorkspaceMeta ( {
123- type : isErr ? "workspace-init-error" : "workspace-init-output" ,
124- workspaceId : params . workspaceId ,
125- timestamp : Date . now ( ) ,
108+ session . emitChatEvent ( {
109+ type : "init-output" ,
126110 line,
111+ isError : isErr ,
112+ timestamp : Date . now ( ) ,
127113 } ) ;
128114 }
129115 return partial ;
@@ -142,56 +128,55 @@ export class IpcMain {
142128 child . on ( "close" , ( code : number | null ) => {
143129 // Flush any remaining partials as lines
144130 if ( outBuf . trim ( ) . length > 0 ) {
145- this . emitWorkspaceMeta ( {
146- type : "workspace-init-output" ,
147- workspaceId : params . workspaceId ,
148- timestamp : Date . now ( ) ,
131+ session . emitChatEvent ( {
132+ type : "init-output" ,
149133 line : outBuf ,
134+ isError : false ,
135+ timestamp : Date . now ( ) ,
150136 } ) ;
151137 }
152138 if ( errBuf . trim ( ) . length > 0 ) {
153- this . emitWorkspaceMeta ( {
154- type : "workspace-init-error" ,
155- workspaceId : params . workspaceId ,
156- timestamp : Date . now ( ) ,
139+ session . emitChatEvent ( {
140+ type : "init-output" ,
157141 line : errBuf ,
142+ isError : true ,
143+ timestamp : Date . now ( ) ,
158144 } ) ;
159145 }
160146
161- this . emitWorkspaceMeta ( {
162- type : "workspace-init-end" ,
163- workspaceId : params . workspaceId ,
164- timestamp : Date . now ( ) ,
147+ session . emitChatEvent ( {
148+ type : "init-end" ,
165149 exitCode : typeof code === "number" ? code : - 1 ,
150+ timestamp : Date . now ( ) ,
166151 } ) ;
167152 } ) ;
168153
169154 child . on ( "error" , ( error : unknown ) => {
170- this . emitWorkspaceMeta ( {
171- type : "workspace-init-error" ,
172- workspaceId : params . workspaceId ,
155+ session . emitChatEvent ( {
156+ type : "init-output" ,
157+ line : error instanceof Error ? error . message : String ( error ) ,
158+ isError : true ,
173159 timestamp : Date . now ( ) ,
174- error : error instanceof Error ? error . message : String ( error ) ,
175160 } ) ;
176- this . emitWorkspaceMeta ( {
177- type : "workspace-init-end" ,
178- workspaceId : params . workspaceId ,
179- timestamp : Date . now ( ) ,
161+ // Also emit end with error code
162+ session . emitChatEvent ( {
163+ type : "init-end" ,
180164 exitCode : - 1 ,
165+ timestamp : Date . now ( ) ,
181166 } ) ;
182167 } ) ;
183168 } catch ( error ) {
184- this . emitWorkspaceMeta ( {
185- type : "workspace-init-error" ,
186- workspaceId : params . workspaceId ,
169+ const session = this . getOrCreateSession ( params . workspaceId ) ;
170+ session . emitChatEvent ( {
171+ type : "init-output" ,
172+ line : error instanceof Error ? error . message : String ( error ) ,
173+ isError : true ,
187174 timestamp : Date . now ( ) ,
188- error : error instanceof Error ? error . message : String ( error ) ,
189175 } ) ;
190- this . emitWorkspaceMeta ( {
191- type : "workspace-init-end" ,
192- workspaceId : params . workspaceId ,
193- timestamp : Date . now ( ) ,
176+ session . emitChatEvent ( {
177+ type : "init-end" ,
194178 exitCode : - 1 ,
179+ timestamp : Date . now ( ) ,
195180 } ) ;
196181 }
197182 }
@@ -1332,18 +1317,7 @@ export class IpcMain {
13321317 } ) ( ) ;
13331318 } ) ;
13341319
1335- // Handle subscription events for workspace meta stream (init hook output)
1336- ipcMain . on ( `workspace:meta:subscribe` , ( _event , workspaceId : string ) => {
1337- if ( ! workspaceId || typeof workspaceId !== "string" ) return ;
1338- const buffered = this . metaEventBuffer . get ( workspaceId ) ?? [ ] ;
1339- for ( const ev of buffered ) {
1340- this . mainWindow ?. webContents . send ( IPC_CHANNELS . WORKSPACE_STREAM_META , ev ) ;
1341- }
1342- } ) ;
13431320
1344- ipcMain . on ( `workspace:meta:unsubscribe` , ( _event , _workspaceId : string ) => {
1345- // No-op: we keep buffer for the session; it will be disposed with the session
1346- } ) ;
13471321
13481322 // Handle subscription events for metadata
13491323 ipcMain . on ( IPC_CHANNELS . WORKSPACE_METADATA_SUBSCRIBE , ( ) => {
0 commit comments