package models import ( "encoding/json" "fmt" "time" ) // WorkspaceState represents the current state of the workspace type WorkspaceState struct { // CurrentCommitSHA is the SHA of the current ephemeral commit CurrentCommitSHA string `json:"current_commit_sha"` // WorkstreamName is the name of the active workstream WorkstreamName string `json:"workstream_name"` // LastSnapshot is when the last automatic snapshot was created LastSnapshot time.Time `json:"last_snapshot"` // IsDirty indicates if there are uncommitted changes IsDirty bool `json:"is_dirty"` // TreeHash is the hash of the current working tree TreeHash string `json:"tree_hash,omitempty"` // IndexHash is the hash of the staging area IndexHash string `json:"index_hash,omitempty"` // Metadata contains additional workspace-specific data Metadata map[string]string `json:"metadata,omitempty"` } // NewWorkspaceState creates a new workspace state func NewWorkspaceState(commitSHA, workstreamName string) *WorkspaceState { return &WorkspaceState{ CurrentCommitSHA: commitSHA, WorkstreamName: workstreamName, LastSnapshot: time.Now(), IsDirty: false, Metadata: make(map[string]string), } } // UpdateSnapshot updates the workspace state with a new snapshot func (ws *WorkspaceState) UpdateSnapshot(commitSHA, treeHash, indexHash string, isDirty bool) { ws.CurrentCommitSHA = commitSHA ws.TreeHash = treeHash ws.IndexHash = indexHash ws.IsDirty = isDirty ws.LastSnapshot = time.Now() } // SetWorkstream changes the active workstream func (ws *WorkspaceState) SetWorkstream(workstreamName string) { ws.WorkstreamName = workstreamName } // MarkDirty marks the workspace as having uncommitted changes func (ws *WorkspaceState) MarkDirty() { ws.IsDirty = true } // MarkClean marks the workspace as clean (no uncommitted changes) func (ws *WorkspaceState) MarkClean() { ws.IsDirty = false } // Serialize converts the workspace state to JSON func (ws *WorkspaceState) Serialize() ([]byte, error) { data, err := json.MarshalIndent(ws, "", " ") if err != nil { return nil, fmt.Errorf("failed to marshal workspace state: %w", err) } return data, nil } // DeserializeWorkspaceState converts JSON data to a workspace state func DeserializeWorkspaceState(data []byte) (*WorkspaceState, error) { ws := &WorkspaceState{} if err := json.Unmarshal(data, ws); err != nil { return nil, fmt.Errorf("failed to unmarshal workspace state: %w", err) } return ws, nil } // GetTimeSinceLastSnapshot returns the duration since the last snapshot func (ws *WorkspaceState) GetTimeSinceLastSnapshot() time.Duration { return time.Since(ws.LastSnapshot) } // Clone creates a deep copy of the workspace state func (ws *WorkspaceState) Clone() *WorkspaceState { metadata := make(map[string]string, len(ws.Metadata)) for k, v := range ws.Metadata { metadata[k] = v } return &WorkspaceState{ CurrentCommitSHA: ws.CurrentCommitSHA, WorkstreamName: ws.WorkstreamName, LastSnapshot: ws.LastSnapshot, IsDirty: ws.IsDirty, TreeHash: ws.TreeHash, IndexHash: ws.IndexHash, Metadata: metadata, } }