from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean, Float, ForeignKey from sqlalchemy.sql import func from app.core.config import Base class ProviderAccount(Base): __tablename__ = 'provider_accounts' id = Column(Integer, primary_key=True, index=True) provider = Column(String(32), nullable=False, index=True) # anthropic/openai/minimax/kimi/qwen label = Column(String(128), nullable=False) credential = Column(Text, nullable=False) # TODO: encrypt at rest is_enabled = Column(Boolean, default=True) created_by = Column(Integer, nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) class ProviderUsageSnapshot(Base): __tablename__ = 'provider_usage_snapshots' id = Column(Integer, primary_key=True, index=True) account_id = Column(Integer, ForeignKey('provider_accounts.id'), nullable=False, index=True) window_label = Column(String(32), nullable=True) # e.g. 1h / 7d used = Column(Float, nullable=True) limit = Column(Float, nullable=True) usage_pct = Column(Float, nullable=True) reset_at = Column(DateTime(timezone=True), nullable=True) status = Column(String(32), nullable=False, default='unknown') # ok/error/pending/unsupported error = Column(Text, nullable=True) raw_payload = Column(Text, nullable=True) fetched_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) class MonitoredServer(Base): __tablename__ = 'monitored_servers' id = Column(Integer, primary_key=True, index=True) identifier = Column(String(128), nullable=False, unique=True) display_name = Column(String(128), nullable=True) is_enabled = Column(Boolean, default=True) api_key = Column(String(64), nullable=True, unique=True, index=True) # API Key for server heartbeat v2 created_by = Column(Integer, nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) class ServerState(Base): __tablename__ = 'server_states' id = Column(Integer, primary_key=True, index=True) server_id = Column(Integer, ForeignKey('monitored_servers.id'), nullable=False, unique=True) openclaw_version = Column(String(64), nullable=True) plugin_version = Column(String(64), nullable=True) agents_json = Column(Text, nullable=True) # json list cpu_pct = Column(Float, nullable=True) mem_pct = Column(Float, nullable=True) disk_pct = Column(Float, nullable=True) swap_pct = Column(Float, nullable=True) last_seen_at = Column(DateTime(timezone=True), nullable=True) updated_at = Column(DateTime(timezone=True), onupdate=func.now())