repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | import datetime |
| #2 | import enum |
| #3 | import uuid |
| #4 | |
| #5 | import sqlalchemy as sa |
| #6 | from app.database import Base |
| #7 | from app.utils.categorization import get_categories_for_memory |
| #8 | from sqlalchemy import ( |
| #9 | JSON, |
| #10 | UUID, |
| #11 | Boolean, |
| #12 | Column, |
| #13 | DateTime, |
| #14 | Enum, |
| #15 | ForeignKey, |
| #16 | Index, |
| #17 | Integer, |
| #18 | String, |
| #19 | Table, |
| #20 | event, |
| #21 | ) |
| #22 | from sqlalchemy.orm import Session, relationship |
| #23 | |
| #24 | |
| #25 | def get_current_utc_time(): |
| #26 | """Get current UTC time""" |
| #27 | return datetime.datetime.now(datetime.UTC) |
| #28 | |
| #29 | |
| #30 | class MemoryState(enum.Enum): |
| #31 | active = "active" |
| #32 | paused = "paused" |
| #33 | archived = "archived" |
| #34 | deleted = "deleted" |
| #35 | |
| #36 | |
| #37 | class User(Base): |
| #38 | __tablename__ = "users" |
| #39 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #40 | user_id = Column(String, nullable=False, unique=True, index=True) |
| #41 | name = Column(String, nullable=True, index=True) |
| #42 | email = Column(String, unique=True, nullable=True, index=True) |
| #43 | metadata_ = Column('metadata', JSON, default=dict) |
| #44 | created_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #45 | updated_at = Column(DateTime, |
| #46 | default=get_current_utc_time, |
| #47 | onupdate=get_current_utc_time) |
| #48 | |
| #49 | apps = relationship("App", back_populates="owner") |
| #50 | memories = relationship("Memory", back_populates="user") |
| #51 | |
| #52 | |
| #53 | class App(Base): |
| #54 | __tablename__ = "apps" |
| #55 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #56 | owner_id = Column(UUID, ForeignKey("users.id"), nullable=False, index=True) |
| #57 | name = Column(String, nullable=False, index=True) |
| #58 | description = Column(String) |
| #59 | metadata_ = Column('metadata', JSON, default=dict) |
| #60 | is_active = Column(Boolean, default=True, index=True) |
| #61 | created_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #62 | updated_at = Column(DateTime, |
| #63 | default=get_current_utc_time, |
| #64 | onupdate=get_current_utc_time) |
| #65 | |
| #66 | owner = relationship("User", back_populates="apps") |
| #67 | memories = relationship("Memory", back_populates="app") |
| #68 | |
| #69 | __table_args__ = ( |
| #70 | sa.UniqueConstraint('owner_id', 'name', name='idx_app_owner_name'), |
| #71 | ) |
| #72 | |
| #73 | |
| #74 | class Config(Base): |
| #75 | __tablename__ = "configs" |
| #76 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #77 | key = Column(String, unique=True, nullable=False, index=True) |
| #78 | value = Column(JSON, nullable=False) |
| #79 | created_at = Column(DateTime, default=get_current_utc_time) |
| #80 | updated_at = Column(DateTime, |
| #81 | default=get_current_utc_time, |
| #82 | onupdate=get_current_utc_time) |
| #83 | |
| #84 | |
| #85 | class Memory(Base): |
| #86 | __tablename__ = "memories" |
| #87 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #88 | user_id = Column(UUID, ForeignKey("users.id"), nullable=False, index=True) |
| #89 | app_id = Column(UUID, ForeignKey("apps.id"), nullable=False, index=True) |
| #90 | content = Column(String, nullable=False) |
| #91 | vector = Column(String) |
| #92 | metadata_ = Column('metadata', JSON, default=dict) |
| #93 | state = Column(Enum(MemoryState), default=MemoryState.active, index=True) |
| #94 | created_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #95 | updated_at = Column(DateTime, |
| #96 | default=get_current_utc_time, |
| #97 | onupdate=get_current_utc_time) |
| #98 | archived_at = Column(DateTime, nullable=True, index=True) |
| #99 | deleted_at = Column(DateTime, nullable=True, index=True) |
| #100 | |
| #101 | user = relationship("User", back_populates="memories") |
| #102 | app = relationship("App", back_populates="memories") |
| #103 | categories = relationship("Category", secondary="memory_categories", back_populates="memories") |
| #104 | |
| #105 | __table_args__ = ( |
| #106 | Index('idx_memory_user_state', 'user_id', 'state'), |
| #107 | Index('idx_memory_app_state', 'app_id', 'state'), |
| #108 | Index('idx_memory_user_app', 'user_id', 'app_id'), |
| #109 | ) |
| #110 | |
| #111 | |
| #112 | class Category(Base): |
| #113 | __tablename__ = "categories" |
| #114 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #115 | name = Column(String, unique=True, nullable=False, index=True) |
| #116 | description = Column(String) |
| #117 | created_at = Column(DateTime, default=datetime.datetime.now(datetime.UTC), index=True) |
| #118 | updated_at = Column(DateTime, |
| #119 | default=get_current_utc_time, |
| #120 | onupdate=get_current_utc_time) |
| #121 | |
| #122 | memories = relationship("Memory", secondary="memory_categories", back_populates="categories") |
| #123 | |
| #124 | memory_categories = Table( |
| #125 | "memory_categories", Base.metadata, |
| #126 | Column("memory_id", UUID, ForeignKey("memories.id"), primary_key=True, index=True), |
| #127 | Column("category_id", UUID, ForeignKey("categories.id"), primary_key=True, index=True), |
| #128 | Index('idx_memory_category', 'memory_id', 'category_id') |
| #129 | ) |
| #130 | |
| #131 | |
| #132 | class AccessControl(Base): |
| #133 | __tablename__ = "access_controls" |
| #134 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #135 | subject_type = Column(String, nullable=False, index=True) |
| #136 | subject_id = Column(UUID, nullable=True, index=True) |
| #137 | object_type = Column(String, nullable=False, index=True) |
| #138 | object_id = Column(UUID, nullable=True, index=True) |
| #139 | effect = Column(String, nullable=False, index=True) |
| #140 | created_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #141 | |
| #142 | __table_args__ = ( |
| #143 | Index('idx_access_subject', 'subject_type', 'subject_id'), |
| #144 | Index('idx_access_object', 'object_type', 'object_id'), |
| #145 | ) |
| #146 | |
| #147 | |
| #148 | class ArchivePolicy(Base): |
| #149 | __tablename__ = "archive_policies" |
| #150 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #151 | criteria_type = Column(String, nullable=False, index=True) |
| #152 | criteria_id = Column(UUID, nullable=True, index=True) |
| #153 | days_to_archive = Column(Integer, nullable=False) |
| #154 | created_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #155 | |
| #156 | __table_args__ = ( |
| #157 | Index('idx_policy_criteria', 'criteria_type', 'criteria_id'), |
| #158 | ) |
| #159 | |
| #160 | |
| #161 | class MemoryStatusHistory(Base): |
| #162 | __tablename__ = "memory_status_history" |
| #163 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #164 | memory_id = Column(UUID, ForeignKey("memories.id"), nullable=False, index=True) |
| #165 | changed_by = Column(UUID, ForeignKey("users.id"), nullable=False, index=True) |
| #166 | old_state = Column(Enum(MemoryState), nullable=False, index=True) |
| #167 | new_state = Column(Enum(MemoryState), nullable=False, index=True) |
| #168 | changed_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #169 | |
| #170 | __table_args__ = ( |
| #171 | Index('idx_history_memory_state', 'memory_id', 'new_state'), |
| #172 | Index('idx_history_user_time', 'changed_by', 'changed_at'), |
| #173 | ) |
| #174 | |
| #175 | |
| #176 | class MemoryAccessLog(Base): |
| #177 | __tablename__ = "memory_access_logs" |
| #178 | id = Column(UUID, primary_key=True, default=lambda: uuid.uuid4()) |
| #179 | memory_id = Column(UUID, ForeignKey("memories.id"), nullable=False, index=True) |
| #180 | app_id = Column(UUID, ForeignKey("apps.id"), nullable=False, index=True) |
| #181 | accessed_at = Column(DateTime, default=get_current_utc_time, index=True) |
| #182 | access_type = Column(String, nullable=False, index=True) |
| #183 | metadata_ = Column('metadata', JSON, default=dict) |
| #184 | |
| #185 | __table_args__ = ( |
| #186 | Index('idx_access_memory_time', 'memory_id', 'accessed_at'), |
| #187 | Index('idx_access_app_time', 'app_id', 'accessed_at'), |
| #188 | ) |
| #189 | |
| #190 | def categorize_memory(memory: Memory, db: Session) -> None: |
| #191 | """Categorize a memory using OpenAI and store the categories in the database.""" |
| #192 | try: |
| #193 | # Get categories from OpenAI |
| #194 | categories = get_categories_for_memory(memory.content) |
| #195 | |
| #196 | # Get or create categories in the database |
| #197 | for category_name in categories: |
| #198 | category = db.query(Category).filter(Category.name == category_name).first() |
| #199 | if not category: |
| #200 | category = Category( |
| #201 | name=category_name, |
| #202 | description=f"Automatically created category for {category_name}" |
| #203 | ) |
| #204 | db.add(category) |
| #205 | db.flush() # Flush to get the category ID |
| #206 | |
| #207 | # Check if the memory-category association already exists |
| #208 | existing = db.execute( |
| #209 | memory_categories.select().where( |
| #210 | (memory_categories.c.memory_id == memory.id) & |
| #211 | (memory_categories.c.category_id == category.id) |
| #212 | ) |
| #213 | ).first() |
| #214 | |
| #215 | if not existing: |
| #216 | # Create the association |
| #217 | db.execute( |
| #218 | memory_categories.insert().values( |
| #219 | memory_id=memory.id, |
| #220 | category_id=category.id |
| #221 | ) |
| #222 | ) |
| #223 | |
| #224 | db.commit() |
| #225 | except Exception as e: |
| #226 | db.rollback() |
| #227 | print(f"Error categorizing memory: {e}") |
| #228 | |
| #229 | |
| #230 | @event.listens_for(Memory, 'after_insert') |
| #231 | def after_memory_insert(mapper, connection, target): |
| #232 | """Trigger categorization after a memory is inserted.""" |
| #233 | db = Session(bind=connection) |
| #234 | categorize_memory(target, db) |
| #235 | db.close() |
| #236 | |
| #237 | |
| #238 | @event.listens_for(Memory, 'after_update') |
| #239 | def after_memory_update(mapper, connection, target): |
| #240 | """Trigger categorization after a memory is updated.""" |
| #241 | db = Session(bind=connection) |
| #242 | categorize_memory(target, db) |
| #243 | db.close() |
| #244 |