Persist bot mode across restarts via database
Adds a BotSettings key-value table. The active mode is saved when changed via /bcs-mode and restored on startup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -126,6 +126,15 @@ class Database:
|
||||
ALTER TABLE UserState ADD UserNotes NVARCHAR(MAX) NULL
|
||||
""")
|
||||
|
||||
cursor.execute("""
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'BotSettings')
|
||||
CREATE TABLE BotSettings (
|
||||
SettingKey NVARCHAR(100) NOT NULL PRIMARY KEY,
|
||||
SettingValue NVARCHAR(MAX) NULL,
|
||||
UpdatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
|
||||
)
|
||||
""")
|
||||
|
||||
cursor.execute("""
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'LlmLog')
|
||||
CREATE TABLE LlmLog (
|
||||
@@ -414,6 +423,57 @@ class Database:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Bot Settings (key-value store)
|
||||
# ------------------------------------------------------------------
|
||||
async def save_setting(self, key: str, value: str) -> None:
|
||||
if not self._available:
|
||||
return
|
||||
try:
|
||||
await asyncio.to_thread(self._save_setting_sync, key, value)
|
||||
except Exception:
|
||||
logger.exception("Failed to save setting %s", key)
|
||||
|
||||
def _save_setting_sync(self, key: str, value: str):
|
||||
conn = self._connect()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"""MERGE BotSettings AS target
|
||||
USING (SELECT ? AS SettingKey) AS source
|
||||
ON target.SettingKey = source.SettingKey
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET SettingValue = ?, UpdatedAt = SYSUTCDATETIME()
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (SettingKey, SettingValue) VALUES (?, ?);""",
|
||||
key, value, key, value,
|
||||
)
|
||||
cursor.close()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
async def load_setting(self, key: str, default: str | None = None) -> str | None:
|
||||
if not self._available:
|
||||
return default
|
||||
try:
|
||||
return await asyncio.to_thread(self._load_setting_sync, key, default)
|
||||
except Exception:
|
||||
logger.exception("Failed to load setting %s", key)
|
||||
return default
|
||||
|
||||
def _load_setting_sync(self, key: str, default: str | None) -> str | None:
|
||||
conn = self._connect()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"SELECT SettingValue FROM BotSettings WHERE SettingKey = ?", key
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
return row[0] if row else default
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
async def close(self):
|
||||
"""No persistent connection to close (connections are per-operation)."""
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user