Improve AI structure binary input diagnostics
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled

This commit is contained in:
2026-05-22 01:00:26 +03:00
parent 51d52ccf04
commit d93b7cb07e
3 changed files with 107 additions and 9 deletions
+47 -7
View File
@@ -588,9 +588,14 @@ async def _start_ai_structure_agent_job(
effective_project_id: str,
input_path: str,
detected_binary_relative_path: str | None = None,
detected_binary_relative_paths: list[str] | None = None,
) -> AgentImportJob:
settings = _project_settings_or_404(project_id)
binary_files = _ai_structure_binary_files(input_path, detected_binary_relative_path=detected_binary_relative_path)
binary_files = _ai_structure_binary_files(
input_path,
detected_binary_relative_path=detected_binary_relative_path,
detected_binary_relative_paths=detected_binary_relative_paths,
)
if not binary_files:
raise HTTPException(status_code=400, detail="Во входном пути не найдены файлы .cf или .cfe.")
@@ -599,15 +604,27 @@ async def _start_ai_structure_agent_job(
if cf_files and cfe_files:
raise HTTPException(
status_code=400,
detail="Во входной папке одновременно лежат .cf и .cfe. Укажите конкретный файл, который нужно подготовить для ИИ.",
detail=(
"Во входной папке одновременно лежат .cf и .cfe. "
f"Найдены: {_format_binary_file_list(binary_files)}. "
"Укажите конкретный файл, который нужно подготовить для ИИ."
),
)
source = ImportSourceKind.CF_FILE if cf_files else ImportSourceKind.CFE_FILE
agent_id = _agent_id_for_source(settings, ImportSourceKind.CF_FILE)
if not agent_id:
raise HTTPException(status_code=400, detail="В настройках проекта не выбран Windows Agent для CF/CFE.")
raise HTTPException(
status_code=400,
detail="В настройках проекта не выбран Windows Agent для CF/CFE. Откройте настройки проекта и укажите `cf_agent_id`.",
)
agent_status = _agent_status_with_liveness(_agent_statuses.get(agent_id, AgentStatus(agent_id=agent_id)))
if agent_status.status != "online":
raise HTTPException(status_code=409, detail=f"Windows Agent {agent_id} сейчас офлайн. Запустите агент и повторите.")
last_seen = str(agent_status.last_seen_at or "").strip()
detail = f"Windows Agent {agent_id} сейчас офлайн."
if last_seen:
detail += f" Последний heartbeat: {last_seen}."
detail += " Запустите агент и повторите."
raise HTTPException(status_code=409, detail=detail)
agent = settings.agent if isinstance(settings.agent, dict) else {}
metadata: dict[str, Any] = {
@@ -620,7 +637,10 @@ async def _start_ai_structure_agent_job(
if len(cf_files) != 1:
raise HTTPException(
status_code=400,
detail="Для прямого разбора .cf укажите один конкретный файл .cf, а не папку с несколькими конфигурациями.",
detail=(
"Для прямого разбора .cf укажите один конкретный файл .cf, "
f"а не папку с несколькими конфигурациями. Найдены: {_format_binary_file_list(cf_files)}."
),
)
local_path = str(cf_files[0])
metadata["input_mode"] = "cf_file"
@@ -628,7 +648,10 @@ async def _start_ai_structure_agent_job(
if len(cfe_files) != 1:
raise HTTPException(
status_code=400,
detail="Для прямого разбора расширения укажите один конкретный файл .cfe, а не папку с несколькими расширениями.",
detail=(
"Для прямого разбора расширения укажите один конкретный файл .cfe, "
f"а не папку с несколькими расширениями. Найдены: {_format_binary_file_list(cfe_files)}."
),
)
cfe_file = cfe_files[0]
local_path = str(cfe_file)
@@ -648,10 +671,19 @@ async def _start_ai_structure_agent_job(
)
def _ai_structure_binary_files(raw_input_path: str, detected_binary_relative_path: str | None = None) -> list[Path]:
def _ai_structure_binary_files(
raw_input_path: str,
detected_binary_relative_path: str | None = None,
detected_binary_relative_paths: list[str] | None = None,
) -> list[Path]:
lowered = raw_input_path.strip().casefold()
if lowered.endswith(".cf") or lowered.endswith(".cfe"):
return [Path(raw_input_path)]
if detected_binary_relative_paths:
return [
Path(ntpath.join(raw_input_path, relative_path.replace("/", "\\")))
for relative_path in detected_binary_relative_paths
]
if detected_binary_relative_path:
windows_path = ntpath.join(raw_input_path, detected_binary_relative_path.replace("/", "\\"))
return [Path(windows_path)]
@@ -663,6 +695,14 @@ def _ai_structure_binary_files(raw_input_path: str, detected_binary_relative_pat
return sorted(path for path in input_path.rglob("*") if path.is_file() and path.suffix.casefold() in {".cf", ".cfe"})
def _format_binary_file_list(paths: list[Path]) -> str:
visible = [path.name for path in paths[:5]]
result = ", ".join(visible)
if len(paths) > 5:
result += f" и еще {len(paths) - 5}"
return result
def _cancel_stale_extension_install_jobs(project_id: str, selected_agent_id: str) -> None:
now = _current_timestamp()
for job in list(_agent_import_jobs.values()):