Support combined CF and CFE AI structure imports
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled

This commit is contained in:
2026-05-22 07:29:51 +03:00
parent 2e86d25205
commit 519f10dd6b
3 changed files with 394 additions and 78 deletions
+102 -1
View File
@@ -1962,6 +1962,107 @@ def test_html5_ai_structure_routes_binary_cfe_through_windows_agent(tmp_path: Pa
assert (output / f"codex-1c-context-{project_id}" / "AGENTS.md").exists()
def test_html5_ai_structure_routes_cf_and_cfe_as_single_project(tmp_path: Path):
base_root = tmp_path / "base-export"
base_root.mkdir()
(base_root / "metadata.xml").write_text(
"""
<Configuration>
<Catalog name="Контрагенты" qualifiedName="Справочник.Контрагенты" />
</Configuration>
""",
encoding="utf-8",
)
extension_root = tmp_path / "extension-export"
extension_root.mkdir()
(extension_root / "РасширениеCRM.mdo").write_text(
"""
<mdclass:ConfigurationExtension xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass/extension">
<name>CRM</name>
<version>1.0</version>
<catalogs>
<name>КонтрагентыCRM</name>
</catalogs>
</mdclass:ConfigurationExtension>
""",
encoding="utf-8",
)
source_dir = tmp_path / "binary"
source_dir.mkdir()
(source_dir / "1Cv8.cf").write_bytes(b"binary-cf")
(source_dir / "Marketplace.cfe").write_bytes(b"binary-cfe")
output = tmp_path / "ai-out-mixed"
client = TestClient(app)
project_id = f"ai-agent-mixed-{uuid4()}"
agent_id = f"win-agent-{uuid4()}"
settings = client.post(
f"/projects/{project_id}/settings",
json={"name": "AI Agent Mixed Demo", "structure_source": "CF_FILE", "agent": {"cf_agent_id": agent_id}},
)
assert settings.status_code == 200
heartbeat = client.post("/agent/heartbeat", json={"agent_id": agent_id, "host": "test-host"})
assert heartbeat.status_code == 200
queued = client.post(
f"/html5/projects/{project_id}/ai-structure/run",
data={"project_id": project_id, "input_path": str(source_dir), "output_path": str(output)},
)
assert queued.status_code == 200
assert "конфигураций 1, расширений 1" in queued.text
match = re.search(r"/html5/projects/[^/]+/ai-structure/jobs/([A-Za-z0-9-]+)", queued.text)
assert match is not None
job_id = match.group(1)
first_claimed = client.get("/agent/jobs/next", params={"agent_id": agent_id})
assert first_claimed.status_code == 200
assert first_claimed.json()["job_id"] == job_id
assert first_claimed.json()["source"] == "CF_FILE"
completed_cf = client.post(
f"/agent/jobs/{job_id}/result",
json={"status": "SUCCEEDED", "server_path": str(base_root), "logs": ["Выгрузка конфигурации завершена."]},
)
assert completed_cf.status_code == 200
main._agent_import_jobs[job_id].status = main.AgentImportJobStatus.SUCCEEDED
main._agent_import_jobs[job_id].import_summary = {"source_path": str(base_root)}
deadline = time.monotonic() + 10
second_job = None
while time.monotonic() < deadline:
polled = client.get(f"/html5/projects/{project_id}/ai-structure/jobs/{job_id}")
assert polled.status_code == 200
second_claimed = client.get("/agent/jobs/next", params={"agent_id": agent_id})
assert second_claimed.status_code == 200
second_job = second_claimed.json()
if second_job:
break
time.sleep(0.05)
assert second_job is not None
assert second_job["source"] == "CFE_FILE"
second_job_id = second_job["job_id"]
completed_cfe = client.post(
f"/agent/jobs/{second_job_id}/result",
json={"status": "SUCCEEDED", "server_path": str(extension_root), "logs": ["Выгрузка расширения завершена."]},
)
assert completed_cfe.status_code == 200
main._agent_import_jobs[second_job_id].status = main.AgentImportJobStatus.SUCCEEDED
main._agent_import_jobs[second_job_id].import_summary = {"source_path": str(extension_root)}
deadline = time.monotonic() + 10
fragment = ""
while time.monotonic() < deadline:
polled = client.get(f"/html5/projects/{project_id}/ai-structure/jobs/{job_id}")
assert polled.status_code == 200
fragment = polled.text
if "готово" in fragment:
break
time.sleep(0.05)
assert "готово" in fragment
assert (output / f"codex-1c-context-{project_id}" / "AGENTS.md").exists()
def test_html5_ai_structure_routes_unc_directory_with_cf_through_windows_agent(monkeypatch, tmp_path: Path):
from api_server import html5_ai_structure_controller as controller
@@ -2041,7 +2142,7 @@ def test_html5_ai_structure_reports_multiple_binary_files_in_directory(tmp_path:
data={"project_id": project_id, "input_path": str(tmp_path), "output_path": str(tmp_path / 'out')},
)
assert queued.status_code == 200
assert "один конкретный файл .cf" in queued.text
assert "одна основная конфигурация .cf" in queued.text
assert "first.cf" in queued.text
assert "second.cf" in queued.text