初始化提交

This commit is contained in:
chenxin committed 2026-08-21 16:00:13 +08:00
commit 887c1f449e
963 files changed
+166869

No files matched your search

+1
View File
@@ -0,0 +1 @@
Generic single-database configuration.
+65
View File
@@ -0,0 +1,65 @@
"""Alembic 迁移环境。"""
from sqlalchemy import pool
from sqlalchemy.engine import Connection, make_url
from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
from app.core.config import settings
from app.db.base import Base
config = context.config
config.set_main_option("sqlalchemy.url", settings.resolved_database_url)
target_metadata = Base.metadata
def ensure_sqlite_parent_dir() -> None:
url = make_url(settings.resolved_database_url)
if url.drivername.startswith("sqlite") and url.database:
settings.resolve_from_backend(url.database).parent.mkdir(parents=True, exist_ok=True)
def run_migrations_offline() -> None:
ensure_sqlite_parent_dir()
context.configure(
url=settings.resolved_database_url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def do_run_migrations(connection: Connection) -> None:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_async_migrations() -> None:
ensure_sqlite_parent_dir()
section = config.get_section(config.config_ini_section, {})
connectable = async_engine_from_config(
section,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
def run_migrations_online() -> None:
import asyncio
asyncio.run(run_async_migrations())
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
+28
View File
@@ -0,0 +1,28 @@
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
# revision identifiers, used by Alembic.
revision: str = ${repr(up_revision)}
down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)}
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
def upgrade() -> None:
"""Upgrade schema."""
${upgrades if upgrades else "pass"}
def downgrade() -> None:
"""Downgrade schema."""
${downgrades if downgrades else "pass"}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,56 @@
"""add_chat_session_owner_scope
Revision ID: 002
Revises: 001
Create Date: 2026-07-14 07:54:32.969191
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = '002'
down_revision: str | Sequence[str] | None = '001'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
conn = op.get_bind()
is_sqlite = conn.engine.dialect.name == "sqlite"
if is_sqlite:
# SQLite:用 batch 模式加列(新增 NOT NULL 列需 batch recreating)
with op.batch_alter_table("chat_sessions") as batch_op:
batch_op.add_column(
sa.Column("owner_scope", sa.String(length=80), nullable=False, server_default=""),
)
batch_op.create_index("ix_chat_sessions_owner_scope", ["owner_scope"])
# 移除 server_default(仅 DDL 阶段需要)
with op.batch_alter_table("chat_sessions") as batch_op:
batch_op.alter_column("owner_scope", server_default=None)
else:
op.add_column(
"chat_sessions",
sa.Column("owner_scope", sa.String(length=80), nullable=False, server_default=""),
)
op.create_index(
op.f("ix_chat_sessions_owner_scope"), "chat_sessions", ["owner_scope"], unique=False
)
op.alter_column("chat_sessions", "owner_scope", server_default=None)
def downgrade() -> None:
conn = op.get_bind()
is_sqlite = conn.engine.dialect.name == "sqlite"
if is_sqlite:
with op.batch_alter_table("chat_sessions") as batch_op:
batch_op.drop_index("ix_chat_sessions_owner_scope")
batch_op.drop_column("owner_scope")
else:
op.drop_index(op.f("ix_chat_sessions_owner_scope"), table_name="chat_sessions")
op.drop_column("chat_sessions", "owner_scope")
@@ -0,0 +1,36 @@
"""add daoti soul fields to character
Revision ID: 003
Revises: 002
Create Date: 2026-07-24 10:47:40.993422
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = '003'
down_revision: str | Sequence[str] | None = '002'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('characters', sa.Column('personality_summary', sa.Text(), nullable=True))
op.add_column('characters', sa.Column('mission', sa.Text(), nullable=True))
op.add_column('characters', sa.Column('safety_guidelines', sa.Text(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('characters', 'safety_guidelines')
op.drop_column('characters', 'mission')
op.drop_column('characters', 'personality_summary')
# ### end Alembic commands ###
@@ -0,0 +1,81 @@
"""add lorebook tables
Revision ID: 004
Revises: 003
Create Date: 2026-07-24 12:20:38.453954
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = '004'
down_revision: str | Sequence[str] | None = '003'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('lorebooks',
sa.Column('id', sa.String(length=80), nullable=False),
sa.Column('character_id', sa.String(length=80), nullable=True),
sa.Column('name', sa.String(length=200), nullable=False),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('scan_depth', sa.Integer(), nullable=True),
sa.Column('token_budget', sa.Integer(), nullable=True),
sa.Column('recursive_scanning', sa.Boolean(), nullable=False),
sa.Column('scope', sa.String(length=40), nullable=False),
sa.Column('status', sa.String(length=40), nullable=False),
sa.Column('owner_scope', sa.String(length=80), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['character_id'], ['characters.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_lorebooks_character_id'), 'lorebooks', ['character_id'], unique=False)
op.create_index(op.f('ix_lorebooks_owner_scope'), 'lorebooks', ['owner_scope'], unique=False)
op.create_index(op.f('ix_lorebooks_scope'), 'lorebooks', ['scope'], unique=False)
op.create_index(op.f('ix_lorebooks_status'), 'lorebooks', ['status'], unique=False)
op.create_table('lorebook_entries',
sa.Column('id', sa.String(length=80), nullable=False),
sa.Column('lorebook_id', sa.String(length=80), nullable=False),
sa.Column('keys_json', sa.Text(), nullable=False),
sa.Column('content', sa.Text(), nullable=False),
sa.Column('secondary_keys_json', sa.Text(), nullable=False),
sa.Column('constant', sa.Boolean(), nullable=False),
sa.Column('selective', sa.Boolean(), nullable=False),
sa.Column('enabled', sa.Boolean(), nullable=False),
sa.Column('case_sensitive', sa.Boolean(), nullable=False),
sa.Column('use_regex', sa.Boolean(), nullable=False),
sa.Column('position', sa.String(length=40), nullable=False),
sa.Column('insertion_order', sa.Integer(), nullable=False),
sa.Column('priority', sa.Integer(), nullable=False),
sa.Column('comment', sa.String(length=500), nullable=False),
sa.Column('bound_entity_id', sa.String(length=80), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['lorebook_id'], ['lorebooks.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_lorebook_entries_bound_entity_id'), 'lorebook_entries', ['bound_entity_id'], unique=False)
op.create_index(op.f('ix_lorebook_entries_lorebook_id'), 'lorebook_entries', ['lorebook_id'], unique=False)
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_lorebook_entries_lorebook_id'), table_name='lorebook_entries')
op.drop_index(op.f('ix_lorebook_entries_bound_entity_id'), table_name='lorebook_entries')
op.drop_table('lorebook_entries')
op.drop_index(op.f('ix_lorebooks_status'), table_name='lorebooks')
op.drop_index(op.f('ix_lorebooks_scope'), table_name='lorebooks')
op.drop_index(op.f('ix_lorebooks_owner_scope'), table_name='lorebooks')
op.drop_index(op.f('ix_lorebooks_character_id'), table_name='lorebooks')
op.drop_table('lorebooks')
# ### end Alembic commands ###