From 14a32778f73c2535cdcba177b2d93c6d5d0dec76 Mon Sep 17 00:00:00 2001 From: Ke Sun Date: Tue, 24 Mar 2026 10:38:47 +0800 Subject: [PATCH 1/3] fix(memory-config): Resolve legacy config_id_old to UUID format - Update config ID validation to query config_id_old field instead of user_id - Raise InvalidConfigError when config_id_old mapping is not found instead of returning raw ID - Add _resolve_config_id_old method to map legacy integer config IDs to UUID format - Enhance agent memory config extraction to resolve legacy int/string formats to UUID - Improve workflow memory node config ID resolution with proper legacy format handling - Fix memory config serialization to always use UUID string format - Update log messages to clarify config_id_old field references and resolution status --- api/app/services/memory_config_service.py | 78 +++++++++++++++------- api/app/services/memory_storage_service.py | 6 +- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/api/app/services/memory_config_service.py b/api/app/services/memory_config_service.py index 1a4af531..66c110b1 100644 --- a/api/app/services/memory_config_service.py +++ b/api/app/services/memory_config_service.py @@ -52,16 +52,20 @@ def _validate_config_id(config_id, db: Session = None): field_name="config_id", invalid_value=config_id, ) - # 如果提供了数据库会话,尝试通过 user_id 查询 config_id + # 如果提供了数据库会话,尝试通过 config_id_old 查询 config_id if db is not None: - # 查询 user_id 匹配的记录 - stmt = select(MemoryConfigModel).where(MemoryConfigModel.config_id_old == str(config_id)) + # 查询 config_id_old 匹配的记录 + stmt = select(MemoryConfigModel).where(MemoryConfigModel.config_id_old == config_id) result = db.execute(stmt).scalars().first() if result: - logger.info(f"Found config_id {result.config_id} for user_id {config_id}") + logger.info(f"Found config_id {result.config_id} for config_id_old {config_id}") return result.config_id - - return config_id + + raise InvalidConfigError( + f"未找到 config_id_old={config_id} 对应的配置", + field_name="config_id", + invalid_value=config_id, + ) if isinstance(config_id, str): config_id_stripped = config_id.strip() @@ -84,15 +88,19 @@ def _validate_config_id(config_id, db: Session = None): # 如果提供了数据库会话,尝试通过 user_id 查询 config_id if db is not None: - # 查询 user_id 匹配的记录 - stmt = select(MemoryConfigModel).where(MemoryConfigModel.user_id == str(parsed_id)) + # 查询 config_id_old 匹配的记录 + stmt = select(MemoryConfigModel).where(MemoryConfigModel.config_id_old == parsed_id) result = db.execute(stmt).scalars().first() if result: - logger.info(f"Found config_id {result.config_id} for user_id {parsed_id}") + logger.info(f"Found config_id {result.config_id} for config_id_old {parsed_id}") return result.config_id - - return parsed_id + + raise InvalidConfigError( + f"未找到 config_id_old={parsed_id} 对应的配置", + field_name="config_id", + invalid_value=config_id, + ) except ValueError: raise InvalidConfigError( f"Invalid configuration ID format: '{config_id}' (must be UUID or positive integer)", @@ -869,6 +877,23 @@ class MemoryConfigService: logger.warning(f"不支持的应用类型,无法提取记忆配置: app_type={app_type}") return None, False + def _resolve_config_id_old(self, config_id_old: int) -> Optional[uuid.UUID]: + """通过 config_id_old 查询对应的 UUID config_id。 + + Args: + config_id_old: 旧格式的整数配置ID + + Returns: + 对应的 UUID config_id,未找到返回 None + """ + from app.models.memory_config_model import MemoryConfig as MemoryConfigModel + result = self.db.query(MemoryConfigModel).filter( + MemoryConfigModel.config_id_old == config_id_old + ).first() + if result: + return result.config_id + return None + def _extract_memory_config_id_from_agent( self, config: dict @@ -900,10 +925,11 @@ class MemoryConfigService: elif isinstance(memory_value, str): # Check if it's a numeric string (legacy int format) if memory_value.isdigit(): - logger.warning( - f"Agent 配置中 memory_config_id 为旧格式 int 字符串,将使用工作空间默认配置: " - f"value={memory_value}" - ) + resolved = self._resolve_config_id_old(int(memory_value)) + if resolved: + logger.info(f"Resolved legacy config_id_old={memory_value} to config_id={resolved}") + return resolved, False + logger.warning(f"未找到 config_id_old={memory_value} 对应的配置,将使用工作空间默认配置") return None, True try: return uuid.UUID(memory_value), False @@ -911,11 +937,11 @@ class MemoryConfigService: logger.warning(f"Invalid UUID string: {memory_value}") return None, False elif isinstance(memory_value, int): - # 旧数据存储为 int,需要回退到工作空间默认配置 - logger.warning( - f"Agent 配置中 memory_config_id 为旧格式 int,将使用工作空间默认配置: " - f"value={memory_value}" - ) + resolved = self._resolve_config_id_old(memory_value) + if resolved: + logger.info(f"Resolved legacy config_id_old={memory_value} to config_id={resolved}") + return resolved, False + logger.warning(f"未找到 config_id_old={memory_value} 对应的配置,将使用工作空间默认配置") return None, True else: logger.warning( @@ -963,10 +989,16 @@ class MemoryConfigService: elif isinstance(config_id, str): return uuid.UUID(config_id), False elif isinstance(config_id, int): - # 旧数据存储为 int,需要回退到工作空间默认配置 + resolved = self._resolve_config_id_old(config_id) + if resolved: + logger.info( + f"Resolved workflow legacy config_id_old={config_id} to config_id={resolved}: " + f"node_id={node.get('id')}, node_type={node_type}" + ) + return resolved, False logger.warning( - f"工作流记忆节点 config_id 为旧格式 int,将使用工作空间默认配置: " - f"node_id={node.get('id')}, node_type={node_type}, value={config_id}" + f"未找到工作流记忆节点 config_id_old={config_id} 对应的配置,将使用工作空间默认配置: " + f"node_id={node.get('id')}, node_type={node_type}" ) return None, True else: diff --git a/api/app/services/memory_storage_service.py b/api/app/services/memory_storage_service.py index 264ae4df..58f3e8bd 100644 --- a/api/app/services/memory_storage_service.py +++ b/api/app/services/memory_storage_service.py @@ -241,12 +241,8 @@ class DataConfigService: # 数据配置服务类(PostgreSQL) except (ValueError, TypeError): config_id_old = None - if config_id_old: - memory_config = config_id_old - else: - memory_config = config.config_id config_dict = { - "config_id": memory_config, + "config_id": str(config.config_id), "config_name": config.config_name, "config_desc": config.config_desc, "workspace_id": str(config.workspace_id) if config.workspace_id else None, From 7a3220aff52424847cebe1d2d1ca23ed0f78235c Mon Sep 17 00:00:00 2001 From: Ke Sun Date: Tue, 24 Mar 2026 12:11:35 +0800 Subject: [PATCH 2/3] chore: Move LICENSE file to project root - Relocate LICENSE from api/ directory to project root - Simplifies license visibility and accessibility for the entire project - Aligns with standard project structure conventions --- api/LICENSE => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename api/LICENSE => LICENSE (100%) diff --git a/api/LICENSE b/LICENSE similarity index 100% rename from api/LICENSE rename to LICENSE From 8c6f395818320b95ed2c00ba2b44f85292392fb9 Mon Sep 17 00:00:00 2001 From: Ke Sun Date: Thu, 26 Mar 2026 16:36:53 +0800 Subject: [PATCH 3/3] refactor(app-service): Rename memory config extraction method for clarity - Rename `_extract_memory_config_id` to `_get_memory_config_id_from_release` to better reflect its purpose of retrieving memory config from release objects - Update method call in release creation flow - Update method call in release retrieval flow - Improves code readability by making the method's scope and responsibility more explicit --- api/app/services/app_service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/app/services/app_service.py b/api/app/services/app_service.py index 19aaac42..4dcabff8 100644 --- a/api/app/services/app_service.py +++ b/api/app/services/app_service.py @@ -1638,7 +1638,7 @@ class AppService: # ==================== 记忆配置提取方法 ==================== - def _extract_memory_config_id( + def _get_memory_config_id_from_release( self, app_type: str, config: Dict[str, Any] @@ -1863,7 +1863,7 @@ class AppService: self.db.flush() # 先 flush,确保 release 已插入数据库 # 提取记忆配置ID并更新终端用户 - memory_config_id, is_legacy_int = self._extract_memory_config_id(app.type, config) + memory_config_id, is_legacy_int = self._get_memory_config_id_from_release(app.type, config) # 如果检测到旧格式 int 数据,回退到工作空间默认配置 if is_legacy_int and not memory_config_id: @@ -2001,7 +2001,7 @@ class AppService: raise ResourceNotFoundException("发布版本", f"app_id={app_id}, version={version}") # 提取记忆配置ID并更新终端用户 - memory_config_id, is_legacy_int = self._extract_memory_config_id(release.type, release.config) + memory_config_id, is_legacy_int = self._get_memory_config_id_from_release(release.type, release.config) # 如果检测到旧格式 int 数据,回退到工作空间默认配置 if is_legacy_int and not memory_config_id: