package store import ( "database/sql" "fmt" "time" "github.com/local-mcp/local-mcp-go/internal/models" ) // AgentStore records and retrieves agent connectivity data. type AgentStore struct { db *sql.DB } // NewAgentStore creates an AgentStore backed by db. func NewAgentStore(db *sql.DB) *AgentStore { return &AgentStore{db: db} } // Record upserts agent activity for agentID with the given result type. func (s *AgentStore) Record(agentID, resultType string) error { now := time.Now().UTC().Format(time.RFC3339Nano) _, err := s.db.Exec(` INSERT INTO agent_activity (agent_id, last_seen_at, last_fetch_at, last_result_type) VALUES (?, ?, ?, ?) ON CONFLICT(agent_id) DO UPDATE SET last_seen_at = excluded.last_seen_at, last_fetch_at = excluded.last_fetch_at, last_result_type = excluded.last_result_type`, agentID, now, now, resultType) return err } // Latest returns the most recently active agent, or nil if no agent has ever // called get_user_request. func (s *AgentStore) Latest() (*models.AgentActivity, error) { row := s.db.QueryRow(` SELECT agent_id, last_seen_at, last_fetch_at, last_result_type FROM agent_activity ORDER BY last_seen_at DESC LIMIT 1`) var a models.AgentActivity var seenStr, fetchStr string err := row.Scan(&a.AgentID, &seenStr, &fetchStr, &a.LastResultType) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("latest agent: %w", err) } a.LastSeenAt, _ = time.Parse(time.RFC3339Nano, seenStr) a.LastFetchAt, _ = time.Parse(time.RFC3339Nano, fetchStr) return &a, nil }