MCPcopy Create free account
hub / github.com/coder/agentapi / SaveState

Method SaveState

lib/screentracker/pty_conversation.go:618–702  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

616}
617
618func (c *PTYConversation) SaveState() error {
619 c.lock.Lock()
620 defer c.lock.Unlock()
621
622 stateFile := c.cfg.StatePersistenceConfig.StateFile
623 saveState := c.cfg.StatePersistenceConfig.SaveState
624
625 if !saveState {
626 c.cfg.Logger.Info("State persistence is disabled")
627 return nil
628 }
629
630 // Skip if not dirty
631 if !c.dirty {
632 c.cfg.Logger.Info("Skipping state save: no changes since last save")
633 return nil
634 }
635
636 conversation := c.messagesLocked()
637
638 // Serialize initial prompt from message parts
639 var initialPromptStr string
640 if len(c.cfg.InitialPrompt) > 0 {
641 initialPromptStr = buildStringFromMessageParts(c.cfg.InitialPrompt)
642 }
643
644 // Create directory if it doesn't exist
645 dir := filepath.Dir(stateFile)
646 if err := os.MkdirAll(dir, 0o700); err != nil {
647 return xerrors.Errorf("failed to create state directory: %w", err)
648 }
649
650 // Use atomic write: write to temp file, then rename to target path
651 tempFile := stateFile + ".tmp"
652 f, err := os.OpenFile(tempFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
653 if err != nil {
654 return xerrors.Errorf("failed to create temp state file: %w", err)
655 }
656
657 // Clean up temp file on error (before successful rename)
658 var renamed bool
659 defer func() {
660 if !renamed {
661 if removeErr := os.Remove(tempFile); removeErr != nil && !os.IsNotExist(removeErr) {
662 c.cfg.Logger.Warn("Failed to clean up temp state file", "path", tempFile, "err", removeErr)
663 }
664 }
665 }()
666
667 // Encode directly to file to avoid loading entire JSON into memory
668 encoder := json.NewEncoder(f)
669 if err := encoder.Encode(AgentState{
670 Version: 1,
671 Messages: conversation,
672 InitialPrompt: initialPromptStr,
673 InitialPromptSent: c.initialPromptSent,
674 }); err != nil {
675 _ = f.Close()

Callers

nothing calls this directly

Calls 3

messagesLockedMethod · 0.95
CloseMethod · 0.80

Tested by

no test coverage detected