mirror of
https://github.com/langgenius/dify.git
synced 2026-11-12 14:21:29 +08:00
70 lines
2.8 KiB
Python
70 lines
2.8 KiB
Python
"""Store the Builder's proposed app name (spec N1).
|
|
|
|
The seam between the model's proposal and the app row. Strictly best-effort: a
|
|
build that is going fine must not fail because a cosmetic rename did, so every
|
|
failure is logged and swallowed and the app keeps its derived name.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
|
|
from core.dify_builder import naming
|
|
from extensions.ext_database import db
|
|
from models.model import App
|
|
from services.app_service import AppService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def rename_app_from_proposal(*, app_id: str, tenant_id: str, account_id: str, proposed: str) -> str:
|
|
"""Store ``proposed`` as the app's name if usable; return what the app is now called.
|
|
|
|
Returns "" when nothing was stored, so the caller never records a name the
|
|
database does not have. Never raises. Opens its own session: this runs in
|
|
the Celery advance task, outside any Flask request.
|
|
"""
|
|
name = naming.normalize_proposed_name(proposed)
|
|
if not name:
|
|
return ""
|
|
try:
|
|
factory = sessionmaker(bind=db.engine, expire_on_commit=False)
|
|
with factory() as session:
|
|
from services.dify_builder.task_controls import lock_execution
|
|
|
|
lock_execution(session, app_id=app_id)
|
|
app = _load_app(session, app_id=app_id, tenant_id=tenant_id)
|
|
if app is None:
|
|
return ""
|
|
if app.name == name:
|
|
return name
|
|
AppService().rename_app(app, name, account_id=account_id, session=session)
|
|
return name
|
|
except Exception:
|
|
# The app keeps its derived name; the card keeps its generic title.
|
|
logger.warning("dify_builder: renaming app %s failed; keeping the derived name", app_id, exc_info=True)
|
|
return ""
|
|
|
|
|
|
def current_app_name(*, app_id: str, tenant_id: str) -> str:
|
|
"""The app's stored name, or "" if it cannot be read. Never raises.
|
|
|
|
Seeds the Builder context so the build-complete card can name the app
|
|
(spec N4) without the engine reaching for the database itself.
|
|
"""
|
|
try:
|
|
factory = sessionmaker(bind=db.engine, expire_on_commit=False)
|
|
with factory() as session:
|
|
app = _load_app(session, app_id=app_id, tenant_id=tenant_id)
|
|
return app.name if app is not None else ""
|
|
except Exception:
|
|
logger.warning("dify_builder: reading the name of app %s failed", app_id, exc_info=True)
|
|
return ""
|
|
|
|
|
|
def _load_app(session: Session, *, app_id: str, tenant_id: str) -> App | None:
|
|
# Tenant-scoped: the actor's tenant is the only authority this path carries,
|
|
# so a cross-tenant id must find nothing rather than rename.
|
|
return session.scalar(select(App).where(App.id == app_id, App.tenant_id == tenant_id))
|