@@ -22,6 +22,33 @@ function getPersistedSessions(): PersistedSession[] {
2222 return ( store as any ) . get ( "sessions" , [ ] ) ;
2323}
2424
25+ function isTerminalReady ( buffer : string , startPos : number = 0 ) : boolean {
26+ const searchBuffer = buffer . slice ( startPos ) ;
27+ const promptSymbols = [ "$ " , "% " , "> " , "➜ " , "➜ " , "✗ " , "✓ " ] ;
28+ const endSymbols = [ "$" , "%" , ">" , "➜" , "✗" , "✓" ] ;
29+
30+ // Check for bracketed paste mode
31+ if ( searchBuffer . includes ( "\x1b[?2004h" ) ) {
32+ return true ;
33+ }
34+
35+ // Check for prompt symbols
36+ for ( const symbol of promptSymbols ) {
37+ if ( searchBuffer . includes ( symbol ) ) {
38+ return true ;
39+ }
40+ }
41+
42+ // Check for end symbols
43+ for ( const symbol of endSymbols ) {
44+ if ( searchBuffer . endsWith ( symbol ) ) {
45+ return true ;
46+ }
47+ }
48+
49+ return false ;
50+ }
51+
2552function savePersistedSessions ( sessions : PersistedSession [ ] ) {
2653 ( store as any ) . set ( "sessions" , sessions ) ;
2754}
@@ -220,6 +247,9 @@ function spawnSessionPty(
220247 activePtyProcesses . set ( sessionId , ptyProcess ) ;
221248
222249 let terminalReady = false ;
250+ let readyChecksCompleted = 0 ;
251+ let lastReadyCheckPos = 0 ;
252+ let setupCommandsIdx = 0 ;
223253 let dataBuffer = "" ;
224254
225255 ptyProcess . onData ( ( data ) => {
@@ -232,44 +262,34 @@ function spawnSessionPty(
232262 if ( ! terminalReady ) {
233263 dataBuffer += data ;
234264
235- // Method 1: Look for bracketed paste mode enable sequence
236- // Method 2: Fallback - look for common prompt indicators
237- const isReady = dataBuffer . includes ( "\x1b[?2004h" ) ||
238- dataBuffer . includes ( "$ " ) || dataBuffer . includes ( "% " ) ||
239- dataBuffer . includes ( "> " ) || dataBuffer . includes ( "➜ " ) ||
240- dataBuffer . includes ( "➜ " ) || dataBuffer . includes ( "✗ " ) ||
241- dataBuffer . includes ( "✓ " ) || dataBuffer . endsWith ( "$" ) ||
242- dataBuffer . endsWith ( "%" ) || dataBuffer . endsWith ( ">" ) ||
243- dataBuffer . endsWith ( "➜" ) || dataBuffer . endsWith ( "✗" ) ||
244- dataBuffer . endsWith ( "✓" ) ;
245-
246- if ( isReady ) {
247- terminalReady = true ;
248-
249- // Run setup commands if provided
250- if ( config . setupCommands && config . setupCommands . length > 0 ) {
251- config . setupCommands . forEach ( cmd => {
252- ptyProcess . write ( cmd + "\r" ) ;
253- } ) ;
254- }
255-
256- // Auto-run the selected coding agent
257- if ( config . codingAgent === "claude" ) {
258- const sessionFlag = isNewSession
259- ? `--session-id ${ sessionUuid } `
260- : `--resume ${ sessionUuid } ` ;
261- const skipPermissionsFlag = config . skipPermissions ? "--dangerously-skip-permissions" : "" ;
262- const mcpConfigFlag = mcpConfigPath ? `--mcp-config ${ mcpConfigPath } ` : "" ;
263- const flags = [ sessionFlag , skipPermissionsFlag , mcpConfigFlag ] . filter ( f => f ) . join ( " " ) ;
264- const claudeCmd = `claude ${ flags } \r` ;
265- ptyProcess . write ( claudeCmd ) ;
266-
267- // Start MCP poller immediately (auth is handled by shell environment)
268- if ( ! mcpPollerPtyProcesses . has ( sessionId ) && projectDir ) {
269- spawnMcpPoller ( sessionId , projectDir ) ;
265+ if ( isTerminalReady ( dataBuffer , lastReadyCheckPos ) ) {
266+ readyChecksCompleted ++ ;
267+ lastReadyCheckPos = dataBuffer . length ;
268+
269+ if ( config . setupCommands && setupCommandsIdx < config . setupCommands . length ) {
270+ ptyProcess . write ( config . setupCommands [ setupCommandsIdx ] + "\r" ) ;
271+ setupCommandsIdx ++ ;
272+ } else {
273+ terminalReady = true ;
274+
275+ // Auto-run the selected coding agent
276+ if ( config . codingAgent === "claude" ) {
277+ const sessionFlag = isNewSession
278+ ? `--session-id ${ sessionUuid } `
279+ : `--resume ${ sessionUuid } ` ;
280+ const skipPermissionsFlag = config . skipPermissions ? "--dangerously-skip-permissions" : "" ;
281+ const mcpConfigFlag = mcpConfigPath ? `--mcp-config ${ mcpConfigPath } ` : "" ;
282+ const flags = [ sessionFlag , skipPermissionsFlag , mcpConfigFlag ] . filter ( f => f ) . join ( " " ) ;
283+ const claudeCmd = `claude ${ flags } \r` ;
284+ ptyProcess . write ( claudeCmd ) ;
285+
286+ // Start MCP poller immediately (auth is handled by shell environment)
287+ if ( ! mcpPollerPtyProcesses . has ( sessionId ) && projectDir ) {
288+ spawnMcpPoller ( sessionId , projectDir ) ;
289+ }
290+ } else if ( config . codingAgent === "codex" ) {
291+ ptyProcess . write ( "codex\r" ) ;
270292 }
271- } else if ( config . codingAgent === "codex" ) {
272- ptyProcess . write ( "codex\r" ) ;
273293 }
274294 }
275295 }
0 commit comments