|
20 | 20 | from consts.model import ( |
21 | 21 | AgentInfoRequest, |
22 | 22 | AgentRequest, |
| 23 | + AgentNameBatchCheckRequest, |
| 24 | + AgentNameBatchRegenerateRequest, |
23 | 25 | ExportAndImportAgentInfo, |
24 | 26 | ExportAndImportDataFormat, |
25 | 27 | MCPInfo, |
@@ -410,6 +412,150 @@ def _regenerate_agent_display_name_with_llm( |
410 | 412 |
|
411 | 413 |
|
412 | 414 |
|
| 415 | +async def check_agent_name_conflict_batch_impl( |
| 416 | + request: AgentNameBatchCheckRequest, |
| 417 | + authorization: str |
| 418 | +) -> list[dict]: |
| 419 | + """ |
| 420 | + Batch check name/display_name duplication for multiple agents. |
| 421 | + """ |
| 422 | + _, tenant_id, _ = get_current_user_info(authorization) |
| 423 | + agents_cache = query_all_agent_info_by_tenant_id(tenant_id) |
| 424 | + |
| 425 | + results: list[dict] = [] |
| 426 | + for item in request.items: |
| 427 | + if not item.name: |
| 428 | + results.append({ |
| 429 | + "name_conflict": False, |
| 430 | + "display_name_conflict": False, |
| 431 | + "conflict_agents": [] |
| 432 | + }) |
| 433 | + continue |
| 434 | + |
| 435 | + conflicts: list[dict] = [] |
| 436 | + name_conflict = False |
| 437 | + display_name_conflict = False |
| 438 | + for agent in agents_cache: |
| 439 | + if item.agent_id and agent.get("agent_id") == item.agent_id: |
| 440 | + continue |
| 441 | + matches_name = item.name and agent.get("name") == item.name |
| 442 | + matches_display = item.display_name and agent.get( |
| 443 | + "display_name") == item.display_name |
| 444 | + if matches_name: |
| 445 | + name_conflict = True |
| 446 | + if matches_display: |
| 447 | + display_name_conflict = True |
| 448 | + if matches_name or matches_display: |
| 449 | + conflicts.append({ |
| 450 | + "name": agent.get("name"), |
| 451 | + "display_name": agent.get("display_name"), |
| 452 | + }) |
| 453 | + |
| 454 | + results.append({ |
| 455 | + "name_conflict": name_conflict, |
| 456 | + "display_name_conflict": display_name_conflict, |
| 457 | + "conflict_agents": conflicts |
| 458 | + }) |
| 459 | + return results |
| 460 | + |
| 461 | + |
| 462 | +async def regenerate_agent_name_batch_impl( |
| 463 | + request: AgentNameBatchRegenerateRequest, |
| 464 | + authorization: str |
| 465 | +) -> list[dict]: |
| 466 | + """ |
| 467 | + Batch regenerate agent name/display_name with LLM (or suffix fallback). |
| 468 | + """ |
| 469 | + _, tenant_id, _ = get_current_user_info(authorization) |
| 470 | + agents_cache = query_all_agent_info_by_tenant_id(tenant_id) |
| 471 | + |
| 472 | + existing_names = [agent.get("name") for agent in agents_cache if agent.get("name")] |
| 473 | + existing_display_names = [agent.get("display_name") for agent in agents_cache if agent.get("display_name")] |
| 474 | + |
| 475 | + # Always use tenant quick-config LLM model |
| 476 | + quick_config_model = tenant_config_manager.get_model_config( |
| 477 | + key=MODEL_CONFIG_MAPPING["llm"], |
| 478 | + tenant_id=tenant_id |
| 479 | + ) |
| 480 | + resolved_model_id = quick_config_model.get("model_id") if quick_config_model else None |
| 481 | + if not resolved_model_id: |
| 482 | + raise ValueError("No available model for regeneration. Please configure an LLM model first.") |
| 483 | + |
| 484 | + results: list[dict] = [] |
| 485 | + # Use local mutable caches to avoid regenerated duplicates in the same batch |
| 486 | + name_set = set(existing_names) |
| 487 | + display_name_set = set(existing_display_names) |
| 488 | + |
| 489 | + for item in request.items: |
| 490 | + agent_name = item.name or "" |
| 491 | + agent_display_name = item.display_name or "" |
| 492 | + task_description = item.task_description or "" |
| 493 | + exclude_agent_id = item.agent_id |
| 494 | + |
| 495 | + # Regenerate name if duplicate and non-empty |
| 496 | + if agent_name and _check_agent_name_duplicate( |
| 497 | + agent_name, tenant_id, agents_cache=agents_cache, exclude_agent_id=exclude_agent_id |
| 498 | + ): |
| 499 | + try: |
| 500 | + agent_name = await asyncio.to_thread( |
| 501 | + _regenerate_agent_name_with_llm, |
| 502 | + original_name=agent_name, |
| 503 | + existing_names=list(name_set), |
| 504 | + task_description=task_description, |
| 505 | + model_id=resolved_model_id, |
| 506 | + tenant_id=tenant_id, |
| 507 | + language=LANGUAGE["ZH"], |
| 508 | + agents_cache=agents_cache, |
| 509 | + exclude_agent_id=exclude_agent_id |
| 510 | + ) |
| 511 | + except Exception as e: |
| 512 | + logger.error(f"Failed to regenerate agent name with LLM: {str(e)}, using fallback") |
| 513 | + agent_name = _generate_unique_agent_name_with_suffix( |
| 514 | + agent_name, |
| 515 | + tenant_id=tenant_id, |
| 516 | + agents_cache=agents_cache, |
| 517 | + exclude_agent_id=exclude_agent_id |
| 518 | + ) |
| 519 | + |
| 520 | + # Regenerate display_name if duplicate and non-empty |
| 521 | + if agent_display_name and _check_agent_display_name_duplicate( |
| 522 | + agent_display_name, tenant_id, agents_cache=agents_cache, exclude_agent_id=exclude_agent_id |
| 523 | + ): |
| 524 | + try: |
| 525 | + agent_display_name = await asyncio.to_thread( |
| 526 | + _regenerate_agent_display_name_with_llm, |
| 527 | + original_display_name=agent_display_name, |
| 528 | + existing_display_names=list(display_name_set), |
| 529 | + task_description=task_description, |
| 530 | + model_id=resolved_model_id, |
| 531 | + tenant_id=tenant_id, |
| 532 | + language=LANGUAGE["ZH"], |
| 533 | + agents_cache=agents_cache, |
| 534 | + exclude_agent_id=exclude_agent_id |
| 535 | + ) |
| 536 | + except Exception as e: |
| 537 | + logger.error(f"Failed to regenerate agent display_name with LLM: {str(e)}, using fallback") |
| 538 | + agent_display_name = _generate_unique_display_name_with_suffix( |
| 539 | + agent_display_name, |
| 540 | + tenant_id=tenant_id, |
| 541 | + agents_cache=agents_cache, |
| 542 | + exclude_agent_id=exclude_agent_id |
| 543 | + ) |
| 544 | + |
| 545 | + # Track regenerated names to avoid duplicates within batch |
| 546 | + if agent_name: |
| 547 | + name_set.add(agent_name) |
| 548 | + if agent_display_name: |
| 549 | + display_name_set.add(agent_display_name) |
| 550 | + |
| 551 | + results.append({ |
| 552 | + "name": agent_name, |
| 553 | + "display_name": agent_display_name |
| 554 | + }) |
| 555 | + |
| 556 | + return results |
| 557 | + |
| 558 | + |
413 | 559 | async def _stream_agent_chunks( |
414 | 560 | agent_request: "AgentRequest", |
415 | 561 | user_id: str, |
@@ -1002,84 +1148,9 @@ async def import_agent_by_agent_id( |
1002 | 1148 | tenant_id=tenant_id |
1003 | 1149 | ) |
1004 | 1150 |
|
1005 | | - # Check for duplicate names and regenerate if needed (unless forced import) |
1006 | 1151 | agent_name = import_agent_info.name |
1007 | 1152 | agent_display_name = import_agent_info.display_name |
1008 | 1153 |
|
1009 | | - # Get all existing agent names and display names for duplicate checking |
1010 | | - all_agents = query_all_agent_info_by_tenant_id(tenant_id) |
1011 | | - existing_names = [agent.get("name") for agent in all_agents if agent.get("name")] |
1012 | | - existing_display_names = [agent.get("display_name") for agent in all_agents if agent.get("display_name")] |
1013 | | - |
1014 | | - if not skip_duplicate_regeneration: |
1015 | | - # Check and regenerate name if duplicate |
1016 | | - if _check_agent_name_duplicate(agent_name, tenant_id, agents_cache=all_agents): |
1017 | | - logger.info(f"Agent name '{agent_name}' already exists, regenerating with LLM") |
1018 | | - # Get model for regeneration (use business_logic_model_id if available, otherwise use model_id) |
1019 | | - regeneration_model_id = business_logic_model_id or model_id |
1020 | | - if regeneration_model_id: |
1021 | | - try: |
1022 | | - # Offload blocking LLM regeneration to a thread to avoid blocking the event loop |
1023 | | - agent_name = await asyncio.to_thread( |
1024 | | - _regenerate_agent_name_with_llm, |
1025 | | - original_name=agent_name, |
1026 | | - existing_names=existing_names, |
1027 | | - task_description=import_agent_info.business_description or import_agent_info.description or "", |
1028 | | - model_id=regeneration_model_id, |
1029 | | - tenant_id=tenant_id, |
1030 | | - language=LANGUAGE["ZH"], # Default to Chinese, can be enhanced later |
1031 | | - agents_cache=all_agents, |
1032 | | - ) |
1033 | | - logger.info(f"Regenerated agent name: '{agent_name}'") |
1034 | | - except Exception as e: |
1035 | | - logger.error(f"Failed to regenerate agent name with LLM: {str(e)}, using fallback") |
1036 | | - agent_name = _generate_unique_agent_name_with_suffix( |
1037 | | - agent_name, |
1038 | | - tenant_id=tenant_id, |
1039 | | - agents_cache=all_agents |
1040 | | - ) |
1041 | | - else: |
1042 | | - logger.warning("No model available for regeneration, using fallback") |
1043 | | - agent_name = _generate_unique_agent_name_with_suffix( |
1044 | | - agent_name, |
1045 | | - tenant_id=tenant_id, |
1046 | | - agents_cache=all_agents |
1047 | | - ) |
1048 | | - |
1049 | | - # Check and regenerate display_name if duplicate |
1050 | | - if _check_agent_display_name_duplicate(agent_display_name, tenant_id, agents_cache=all_agents): |
1051 | | - logger.info(f"Agent display_name '{agent_display_name}' already exists, regenerating with LLM") |
1052 | | - # Get model for regeneration (use business_logic_model_id if available, otherwise use model_id) |
1053 | | - regeneration_model_id = business_logic_model_id or model_id |
1054 | | - if regeneration_model_id: |
1055 | | - try: |
1056 | | - # Offload blocking LLM regeneration to a thread to avoid blocking the event loop |
1057 | | - agent_display_name = await asyncio.to_thread( |
1058 | | - _regenerate_agent_display_name_with_llm, |
1059 | | - original_display_name=agent_display_name, |
1060 | | - existing_display_names=existing_display_names, |
1061 | | - task_description=import_agent_info.business_description or import_agent_info.description or "", |
1062 | | - model_id=regeneration_model_id, |
1063 | | - tenant_id=tenant_id, |
1064 | | - language=LANGUAGE["ZH"], # Default to Chinese, can be enhanced later |
1065 | | - agents_cache=all_agents, |
1066 | | - ) |
1067 | | - logger.info(f"Regenerated agent display_name: '{agent_display_name}'") |
1068 | | - except Exception as e: |
1069 | | - logger.error(f"Failed to regenerate agent display_name with LLM: {str(e)}, using fallback") |
1070 | | - agent_display_name = _generate_unique_display_name_with_suffix( |
1071 | | - agent_display_name, |
1072 | | - tenant_id=tenant_id, |
1073 | | - agents_cache=all_agents |
1074 | | - ) |
1075 | | - else: |
1076 | | - logger.warning("No model available for regeneration, using fallback") |
1077 | | - agent_display_name = _generate_unique_display_name_with_suffix( |
1078 | | - agent_display_name, |
1079 | | - tenant_id=tenant_id, |
1080 | | - agents_cache=all_agents |
1081 | | - ) |
1082 | | - |
1083 | 1154 | # create a new agent |
1084 | 1155 | new_agent = create_agent(agent_info={"name": agent_name, |
1085 | 1156 | "display_name": agent_display_name, |
|
0 commit comments