Codex/avatar integrated 20260819 #2
@@ -38,8 +38,9 @@ def init_db():
|
||||
("authorizations", "takeover_enabled", "BOOLEAN DEFAULT 0"),
|
||||
("authorizations", "takeover_mode", "VARCHAR DEFAULT 'immediate'"),
|
||||
("authorizations", "takeover_delay_seconds", "INTEGER DEFAULT 30"),
|
||||
("avatars", "share_token", "VARCHAR DEFAULT ''"),
|
||||
("avatars", "share_token", "VARCHAR DEFAULT NULL"),
|
||||
)
|
||||
_normalize_optional_unique_values()
|
||||
|
||||
|
||||
def _try_add_columns(*cols):
|
||||
@@ -51,3 +52,8 @@ def _try_add_columns(*cols):
|
||||
except Exception:
|
||||
# 列已存在(或全新库由 create_all 建好)则忽略
|
||||
pass
|
||||
|
||||
|
||||
def _normalize_optional_unique_values():
|
||||
with engine.begin() as conn:
|
||||
conn.exec_driver_sql("UPDATE avatars SET share_token = NULL WHERE share_token = ''")
|
||||
|
||||
@@ -20,7 +20,7 @@ class Avatar(Base):
|
||||
photo_url = Column(String, default="")
|
||||
emoji = Column(String, default="🤖")
|
||||
status = Column(String, default="active") # active | inactive | training
|
||||
share_token = Column(String, default="", unique=True, index=True) # 对外分享使用的不可猜测令牌
|
||||
share_token = Column(String, nullable=True, default=None, unique=True, index=True) # 对外分享使用的不可猜测令牌
|
||||
token_balance = Column(Integer, default=0)
|
||||
config = Column(JSON, default=dict)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
@@ -36,7 +36,7 @@ class Avatar(Base):
|
||||
"photoUrl": self.photo_url,
|
||||
"emoji": self.emoji,
|
||||
"status": self.status,
|
||||
"shareToken": self.share_token,
|
||||
"shareToken": self.share_token or "",
|
||||
"tokenBalance": self.token_balance,
|
||||
"config": self.config or {},
|
||||
"createdAt": _iso(self.created_at),
|
||||
|
||||
@@ -133,4 +133,3 @@ def delete_avatar(avatar_id: str, db: Session = Depends(get_db)):
|
||||
db.delete(a)
|
||||
db.commit()
|
||||
return ok({"success": True})
|
||||
|
||||
|
||||
@@ -121,6 +121,12 @@ class ChatOrchestrationTests(unittest.TestCase):
|
||||
self.assertNotIn("config", payload)
|
||||
self.assertNotIn("ownerId", payload)
|
||||
|
||||
def test_unshared_avatars_do_not_reuse_a_unique_share_token(self):
|
||||
first = Avatar(name="first")
|
||||
second = Avatar(name="second")
|
||||
self.assertIsNone(first.share_token)
|
||||
self.assertIsNone(second.share_token)
|
||||
|
||||
def test_standard_answer_can_be_emitted_as_sse_chunks(self):
|
||||
self.assertEqual(list(_iter_text_chunks("标准答案内容", size=2)), ["标准", "答案", "内容"])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user