package store import ( "encoding/json" "fmt" "os" "path/filepath" "superwork-tui/internal/config" ) // ManagedSession is a Claude session created via the session manager tab. type ManagedSession struct { ID string `json:"id"` Name string `json:"name"` ProfilePath string `json:"profilePath,omitempty"` CreatedAt int64 `json:"createdAt"` } // ManagedSessionsData is the workspace-level managed sessions list. type ManagedSessionsData struct { Sessions []ManagedSession `json:"sessions"` } func sessionsFile(workspaceRoot string) string { return filepath.Join(config.SpxDir(workspaceRoot), "session-names.json") } // ReadManagedSessions reads the managed sessions list. // A missing or malformed file returns an empty list without error. func ReadManagedSessions(workspaceRoot string) (ManagedSessionsData, error) { raw, err := os.ReadFile(sessionsFile(workspaceRoot)) if err != nil { return ManagedSessionsData{Sessions: []ManagedSession{}}, nil } var data ManagedSessionsData if err := json.Unmarshal(raw, &data); err != nil { return ManagedSessionsData{Sessions: []ManagedSession{}}, nil } if data.Sessions == nil { data.Sessions = []ManagedSession{} } return data, nil } // WriteManagedSessions persists the sessions list. Creates .spx if needed. func WriteManagedSessions(workspaceRoot string, data ManagedSessionsData) error { if err := os.MkdirAll(config.SpxDir(workspaceRoot), 0o755); err != nil { return fmt.Errorf("create .spx dir: %w", err) } b, err := json.MarshalIndent(data, "", " ") if err != nil { return fmt.Errorf("marshal sessions: %w", err) } if err := os.WriteFile(sessionsFile(workspaceRoot), append(b, '\n'), 0o644); err != nil { return fmt.Errorf("write sessions: %w", err) } return nil } // AddSession appends s to data and returns the new data. func AddSession(data ManagedSessionsData, s ManagedSession) ManagedSessionsData { out := make([]ManagedSession, len(data.Sessions), len(data.Sessions)+1) copy(out, data.Sessions) return ManagedSessionsData{Sessions: append(out, s)} } // RenameSession sets the Name of the session with the given id. func RenameSession(data ManagedSessionsData, id, name string) ManagedSessionsData { out := make([]ManagedSession, len(data.Sessions)) copy(out, data.Sessions) for i := range out { if out[i].ID == id { out[i].Name = name break } } return ManagedSessionsData{Sessions: out} } // DeleteSession removes the session with the given id. func DeleteSession(data ManagedSessionsData, id string) ManagedSessionsData { out := make([]ManagedSession, 0, len(data.Sessions)) for _, s := range data.Sessions { if s.ID != id { out = append(out, s) } } data.Sessions = out return data } // FindSession returns the session with the given id, if present. func FindSession(data ManagedSessionsData, id string) (ManagedSession, bool) { for _, s := range data.Sessions { if s.ID == id { return s, true } } return ManagedSession{}, false }