Skip to content

Commit 6b99bd8

Browse files
committed
fix(repo): filter empty optional fields from installed manifest
Empty optional fields (exports: {}, imports: {}, etc.) in the repo element manifest caused constant updates in the universal agent due to a diff between target and actual resources on every iteration. - Add MANIFEST_OPTIONAL_FIELDS to InstalledManifest and filter empty values in from_repo_element - Simplify _make_installed_manifest to use a loop over the shared MANIFEST_OPTIONAL_FIELDS tuple instead of individual if-blocks - Add regression tests for empty and non-empty optional field handling Signed-off-by: Anton Kremenetsky <anton.kremenetsky@gmail.com>
1 parent 14a666e commit 6b99bd8

4 files changed

Lines changed: 85 additions & 15 deletions

File tree

exordos_core/repo/agents/universal/drivers/repo_element.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,10 @@ def _make_installed_manifest(
8585
project_id=em_manifest.project_id,
8686
)
8787

88-
if em_manifest.openapi_spec is not None:
89-
installed_manifest.manifest["openapi_spec"] = em_manifest.openapi_spec
90-
91-
if em_manifest.exports:
92-
installed_manifest.manifest["exports"] = em_manifest.exports
93-
94-
if em_manifest.imports:
95-
installed_manifest.manifest["imports"] = em_manifest.imports
96-
97-
if em_manifest.requirements:
98-
installed_manifest.manifest["requirements"] = em_manifest.requirements
99-
100-
if em_manifest.resources:
101-
installed_manifest.manifest["resources"] = em_manifest.resources
88+
for field in re_builder.InstalledManifest.MANIFEST_OPTIONAL_FIELDS:
89+
value = getattr(em_manifest, field)
90+
if value:
91+
installed_manifest.manifest[field] = value
10292

10393
return installed_manifest
10494

exordos_core/repo/builders/element.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ class InstalledManifest(
6565
linked.
6666
"""
6767

68+
MANIFEST_OPTIONAL_FIELDS = (
69+
"openapi_spec",
70+
"exports",
71+
"imports",
72+
"requirements",
73+
"resources",
74+
)
75+
6876
version = properties.property(
6977
ra_types.String(min_length=5, max_length=64), required=True
7078
)
@@ -101,12 +109,21 @@ def get_resource_target_fields(self) -> tp.Collection[str]:
101109
@classmethod
102110
def from_repo_element(cls, element: models.RepoElement) -> "InstalledManifest":
103111
uuid = sys_uuid.UUID(str(element.manifest.get("uuid") or element.uuid))
112+
# Filter out empty optional fields to keep the manifest consistent
113+
# with _make_installed_manifest in the repo element driver, which
114+
# also skips empty values. Without this, the agent detects a diff
115+
# between target and actual resources on every iteration.
116+
manifest = {
117+
k: v
118+
for k, v in element.manifest.items()
119+
if k not in cls.MANIFEST_OPTIONAL_FIELDS or v
120+
}
104121
return cls(
105122
uuid=uuid,
106123
name=element.name,
107124
description=element.manifest.get("description", ""),
108125
version=element.version,
109-
manifest=element.manifest,
126+
manifest=manifest,
110127
project_id=element.project_id,
111128
)
112129

exordos_core/tests/unit/repo/test_element_builder.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,50 @@ def test_from_repo_element_without_manifest_uuid(self):
502502
assert result.name == element.name
503503
assert result.version == "2.0.0"
504504

505+
def test_from_repo_element_filters_empty_optional_fields(self):
506+
"""Empty optional fields should be excluded from the manifest."""
507+
element_uuid = sys_uuid.uuid4()
508+
element = FakeElement(version="1.0.0")
509+
element.uuid = element_uuid
510+
element.manifest = {
511+
"uuid": element_uuid,
512+
"key": "value",
513+
"exports": {},
514+
"imports": {},
515+
"requirements": {},
516+
"resources": {},
517+
"openapi_spec": None,
518+
}
519+
element.project_id = sys_uuid.uuid4()
520+
521+
result = builder_element.InstalledManifest.from_repo_element(element)
522+
523+
assert "exports" not in result.manifest
524+
assert "imports" not in result.manifest
525+
assert "requirements" not in result.manifest
526+
assert "resources" not in result.manifest
527+
assert "openapi_spec" not in result.manifest
528+
assert result.manifest["key"] == "value"
529+
530+
def test_from_repo_element_keeps_non_empty_optional_fields(self):
531+
"""Non-empty optional fields should be preserved in the manifest."""
532+
element_uuid = sys_uuid.uuid4()
533+
element = FakeElement(version="1.0.0")
534+
element.uuid = element_uuid
535+
element.manifest = {
536+
"uuid": element_uuid,
537+
"exports": {"exp1": {}},
538+
"resources": {"res1": {}},
539+
"openapi_spec": {"paths": {}},
540+
}
541+
element.project_id = sys_uuid.uuid4()
542+
543+
result = builder_element.InstalledManifest.from_repo_element(element)
544+
545+
assert result.manifest["exports"] == {"exp1": {}}
546+
assert result.manifest["resources"] == {"res1": {}}
547+
assert result.manifest["openapi_spec"] == {"paths": {}}
548+
505549
def test_get_resource_target_fields(self):
506550
manifest = builder_element.InstalledManifest(
507551
name="test",

exordos_core/tests/unit/repo/test_repo_element_driver.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,25 @@ def test_without_repo_element_without_em_element(self):
146146
}
147147
assert result.manifest == expected_manifest
148148

149+
def test_with_non_empty_optional_fields(self):
150+
"""Should include non-empty optional fields in the manifest."""
151+
client = self._make_client()
152+
em_manifest = self._make_em_manifest()
153+
em_manifest.exports = {"exp1": {}}
154+
em_manifest.imports = {"imp1": {}}
155+
em_manifest.requirements = {"dep": {"from_version": "1.0.0"}}
156+
em_manifest.resources = {"res1": {}}
157+
em_manifest.openapi_spec = {"paths": {}}
158+
em_element = self._make_em_element()
159+
160+
result = client._make_installed_manifest(em_manifest, em_element)
161+
162+
assert result.manifest["exports"] == {"exp1": {}}
163+
assert result.manifest["imports"] == {"imp1": {}}
164+
assert result.manifest["requirements"] == {"dep": {"from_version": "1.0.0"}}
165+
assert result.manifest["resources"] == {"res1": {}}
166+
assert result.manifest["openapi_spec"] == {"paths": {}}
167+
149168

150169
class TestMakeEmManifest:
151170
"""Tests for RepoEmBackendClient._make_em_manifest."""

0 commit comments

Comments
 (0)