@@ -350,16 +350,11 @@ func (s *Server) StartSnapshotLoop(ctx context.Context) {
350350 for {
351351 currentStatus := s .conversation .Status ()
352352
353- // Send initial prompt when agent becomes stable for the first time
353+ // Send initial prompt & load state when agent becomes stable for the first time
354354 if convertStatus (currentStatus ) == AgentStatusStable {
355355
356356 if ! s .stateLoadComplete && s .statePersistenceCfg .LoadState {
357- _ , err := s .conversation .LoadState (s .statePersistenceCfg .StateFile )
358- if err != nil {
359- s .logger .Warn ("Failed to load state file" , "path" , s .statePersistenceCfg .StateFile , "err" , err )
360- } else {
361- s .logger .Info ("Successfully loaded state" , "path" , s .statePersistenceCfg .StateFile )
362- }
357+ _ , _ = s .conversation .LoadState (s .statePersistenceCfg .StateFile )
363358 s .stateLoadComplete = true
364359 }
365360 if ! s .conversation .InitialPromptSent {
@@ -612,6 +607,11 @@ func (s *Server) Start() error {
612607 Handler : s .router ,
613608 }
614609
610+ // Write PID file if configured
611+ if err := s .writePIDFile (); err != nil {
612+ return xerrors .Errorf ("failed to write PID file: %w" , err )
613+ }
614+
615615 return s .srv .ListenAndServe ()
616616}
617617
@@ -626,6 +626,9 @@ func (s *Server) Stop(ctx context.Context) error {
626626 }
627627 }
628628
629+ // Clean up PID file
630+ s .cleanupPIDFile ()
631+
629632 // Clean up temporary directory
630633 s .cleanupTempDir ()
631634
@@ -644,6 +647,43 @@ func (s *Server) cleanupTempDir() {
644647 }
645648}
646649
650+ // writePIDFile writes the current process ID to the configured PID file
651+ func (s * Server ) writePIDFile () error {
652+ if s .statePersistenceCfg .PidFile == "" {
653+ return nil
654+ }
655+
656+ pid := os .Getpid ()
657+ pidContent := fmt .Sprintf ("%d\n " , pid )
658+
659+ // Create directory if it doesn't exist
660+ dir := filepath .Dir (s .statePersistenceCfg .PidFile )
661+ if err := os .MkdirAll (dir , 0o755 ); err != nil {
662+ return xerrors .Errorf ("failed to create PID file directory: %w" , err )
663+ }
664+
665+ // Write PID file
666+ if err := os .WriteFile (s .statePersistenceCfg .PidFile , []byte (pidContent ), 0o644 ); err != nil {
667+ return xerrors .Errorf ("failed to write PID file: %w" , err )
668+ }
669+
670+ s .logger .Info ("Wrote PID file" , "pidFile" , s .statePersistenceCfg .PidFile , "pid" , pid )
671+ return nil
672+ }
673+
674+ // cleanupPIDFile removes the PID file if it exists
675+ func (s * Server ) cleanupPIDFile () {
676+ if s .statePersistenceCfg .PidFile == "" {
677+ return
678+ }
679+
680+ if err := os .Remove (s .statePersistenceCfg .PidFile ); err != nil && ! os .IsNotExist (err ) {
681+ s .logger .Error ("Failed to remove PID file" , "pidFile" , s .statePersistenceCfg .PidFile , "error" , err )
682+ } else if err == nil {
683+ s .logger .Info ("Removed PID file" , "pidFile" , s .statePersistenceCfg .PidFile )
684+ }
685+ }
686+
647687// HandleSignals sets up signal handlers for:
648688// - SIGTERM, SIGINT, SIGHUP: save conversation state, then close the process
649689// - SIGUSR1: save conversation state without exiting
@@ -664,6 +704,9 @@ func (s *Server) HandleSignals(ctx context.Context, process *termexec.Process) {
664704 }
665705 }
666706
707+ // Clean up PID file
708+ s .cleanupPIDFile ()
709+
667710 // Now close the process
668711 if err := process .Close (s .logger , 5 * time .Second ); err != nil {
669712 s .logger .Error ("Error closing process" , "signal" , sig , "error" , err )
0 commit comments