diff --git a/api/services/agent/composer_service.py b/api/services/agent/composer_service.py index 30910a0f4d9..be418b60507 100644 --- a/api/services/agent/composer_service.py +++ b/api/services/agent/composer_service.py @@ -284,10 +284,7 @@ class AgentComposerService: "active_config_snapshot": cls._serialize_version(version), "draft": cls._serialize_draft(draft), "agent_soul": draft.config_snapshot_dict, - "save_options": [ - ComposerSaveStrategy.SAVE_TO_CURRENT_VERSION.value, - ComposerSaveStrategy.SAVE_AS_NEW_VERSION.value, - ], + "save_options": [ComposerSaveStrategy.SAVE_TO_CURRENT_VERSION.value], } @classmethod @@ -296,6 +293,10 @@ class AgentComposerService: ) -> dict[str, Any]: if payload.variant != ComposerVariant.AGENT_APP: raise ValueError("Agent App composer endpoint only accepts agent_app variant") + if payload.save_strategy != ComposerSaveStrategy.SAVE_TO_CURRENT_VERSION: + raise InvalidComposerConfigError( + "Agent App composer only saves the normal draft. Use the publish endpoint to create a version." + ) _backfill_cli_tool_ids(payload.agent_soul) _validate_composer_payload_for_strategy(payload) cls.validate_knowledge_datasets(tenant_id=tenant_id, agent_soul=payload.agent_soul) diff --git a/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py b/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py index 9c60da00216..93372bd42c2 100644 --- a/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py +++ b/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py @@ -99,7 +99,7 @@ def _agent_app_composer_response() -> dict: }, "active_config_snapshot": _version_response(), "agent_soul": {}, - "save_options": ["save_to_current_version", "save_as_new_version"], + "save_options": ["save_to_current_version"], } diff --git a/api/tests/unit_tests/services/agent/test_agent_services.py b/api/tests/unit_tests/services/agent/test_agent_services.py index fcb4a8fb231..badaa766b25 100644 --- a/api/tests/unit_tests/services/agent/test_agent_services.py +++ b/api/tests/unit_tests/services/agent/test_agent_services.py @@ -282,7 +282,7 @@ def test_save_agent_app_composer_creates_agent_when_missing(monkeypatch: pytest. payload = ComposerSavePayload.model_validate( { "variant": ComposerVariant.AGENT_APP.value, - "save_strategy": ComposerSaveStrategy.SAVE_AS_NEW_VERSION.value, + "save_strategy": ComposerSaveStrategy.SAVE_TO_CURRENT_VERSION.value, "new_agent_name": "Analyst", "agent_soul": {"prompt": {"system_prompt": "x"}}, } @@ -299,6 +299,45 @@ def test_save_agent_app_composer_creates_agent_when_missing(monkeypatch: pytest. assert fake_session.commits == 1 +def test_load_agent_app_composer_exposes_draft_save_only(monkeypatch: pytest.MonkeyPatch): + agent = SimpleNamespace( + id="agent-1", + active_config_snapshot_id="version-1", + updated_by="account-1", + created_by="account-1", + ) + draft = SimpleNamespace(config_snapshot_dict={"prompt": {"system_prompt": "x"}}) + + monkeypatch.setattr(AgentComposerService, "_require_agent_app_agent", lambda **kwargs: agent) + monkeypatch.setattr(AgentComposerService, "_get_or_create_agent_draft", lambda **kwargs: draft) + monkeypatch.setattr(AgentComposerService, "_get_version_if_present", lambda **kwargs: None) + monkeypatch.setattr(AgentComposerService, "_serialize_agent", lambda _agent: {"id": _agent.id}) + monkeypatch.setattr(AgentComposerService, "_serialize_version", lambda _version: None) + monkeypatch.setattr(AgentComposerService, "_serialize_draft", lambda _draft: {"id": "draft-1"}) + + result = AgentComposerService.load_agent_app_composer(tenant_id="tenant-1", app_id="app-1") + + assert result["save_options"] == [ComposerSaveStrategy.SAVE_TO_CURRENT_VERSION.value] + + +def test_save_agent_app_composer_rejects_version_save_strategy(): + payload = ComposerSavePayload.model_validate( + { + "variant": ComposerVariant.AGENT_APP.value, + "save_strategy": ComposerSaveStrategy.SAVE_AS_NEW_VERSION.value, + "agent_soul": {"prompt": {"system_prompt": "x"}}, + } + ) + + with pytest.raises(InvalidComposerConfigError, match="Use the publish endpoint"): + AgentComposerService.save_agent_app_composer( + tenant_id="tenant-1", + app_id="app-1", + account_id="account-1", + payload=payload, + ) + + def test_save_agent_app_composer_updates_normal_draft(monkeypatch: pytest.MonkeyPatch): agent = SimpleNamespace(id="agent-1", active_config_snapshot_id="version-1", updated_by=None) fake_session = FakeSession(scalar=[agent])