Skip to content

Commit 9d2ef87

Browse files
authored
🐛 Bugfix: Fixed an issue where the created_by field was not written when publishing an agent version. (#3287)
1 parent 3bee68b commit 9d2ef87

2 files changed

Lines changed: 131 additions & 4 deletions

File tree

backend/services/agent_version_service.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ def _remove_audit_fields_for_insert(data: dict) -> None:
4444
"""
4545
data.pop('create_time', None)
4646
data.pop('update_time', None)
47-
data.pop('created_by', None)
48-
data.pop('updated_by', None)
4947
data.pop('delete_flag', None)
5048

5149

@@ -90,6 +88,7 @@ def publish_version_impl(
9088
agent_snapshot.pop('version_no', None)
9189
agent_snapshot.pop('current_version_no', None)
9290
agent_snapshot['version_no'] = new_version_no
91+
agent_snapshot['updated_by'] = user_id
9392
_remove_audit_fields_for_insert(agent_snapshot)
9493

9594
# Insert agent snapshot
@@ -100,6 +99,7 @@ def publish_version_impl(
10099
tool_snapshot = tool.copy()
101100
tool_snapshot.pop('version_no', None)
102101
tool_snapshot['version_no'] = new_version_no
102+
tool_snapshot['updated_by'] = user_id
103103
_remove_audit_fields_for_insert(tool_snapshot)
104104
insert_tool_snapshot(tool_snapshot)
105105

@@ -115,6 +115,7 @@ def publish_version_impl(
115115
rel_snapshot.pop('version_no', None)
116116
rel_snapshot['version_no'] = new_version_no
117117
rel_snapshot['selected_agent_version_no'] = child_version
118+
rel_snapshot['updated_by'] = user_id
118119
_remove_audit_fields_for_insert(rel_snapshot)
119120
insert_relation_snapshot(rel_snapshot)
120121

@@ -131,6 +132,7 @@ def publish_version_impl(
131132
skill_snapshot = skill.copy()
132133
skill_snapshot.pop('version_no', None)
133134
skill_snapshot['version_no'] = new_version_no
135+
skill_snapshot['updated_by'] = user_id
134136
_remove_audit_fields_for_insert(skill_snapshot)
135137
insert_skill_snapshot(skill_snapshot)
136138

test/backend/services/test_agent_version_service.py

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,20 @@ def test_publish_version_impl_success(monkeypatch, mock_agent_draft, mock_tools_
305305
assert relation_snapshot["selected_agent_version_no"] == 1
306306
assert mock_insert_skill.call_count == 1
307307

308+
# Verify updated_by is set to user_id on all snapshot types
309+
agent_snapshot = mock_insert_agent.call_args[0][0]
310+
assert agent_snapshot["updated_by"] == "user1"
311+
312+
tool_snapshot_0 = mock_insert_tool.call_args_list[0][0][0]
313+
tool_snapshot_1 = mock_insert_tool.call_args_list[1][0][0]
314+
assert tool_snapshot_0["updated_by"] == "user1"
315+
assert tool_snapshot_1["updated_by"] == "user1"
316+
317+
assert relation_snapshot["updated_by"] == "user1"
318+
319+
skill_snapshot = mock_insert_skill.call_args[0][0]
320+
assert skill_snapshot["updated_by"] == "user1"
321+
308322

309323
def test_publish_version_impl_unpublished_sub_agent(
310324
monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft
@@ -376,6 +390,14 @@ def test_publish_version_impl_with_rollback_source(monkeypatch, mock_agent_draft
376390
assert call_args["source_type"] == "ROLLBACK"
377391
assert call_args["source_version_no"] == 1
378392

393+
# Verify updated_by is set on all snapshot types
394+
agent_snapshot = mock_insert_agent.call_args[0][0]
395+
assert agent_snapshot["updated_by"] == "user1"
396+
for call in mock_insert_tool.call_args_list:
397+
assert call[0][0]["updated_by"] == "user1"
398+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
399+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
400+
379401

380402
def test_publish_version_impl_with_skills(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
381403
"""Test publishing version with skill instances"""
@@ -412,6 +434,11 @@ def test_publish_version_impl_with_skills(monkeypatch, mock_agent_draft, mock_to
412434
assert result["version_no"] == 3
413435
assert mock_insert_skill.call_count == 3
414436

437+
# Verify updated_by is set on all skill snapshots
438+
for i, call in enumerate(mock_insert_skill.call_args_list):
439+
skill_snapshot = call[0][0]
440+
assert skill_snapshot["updated_by"] == "user1"
441+
415442

416443
def test_publish_version_impl_empty_tools_relations(monkeypatch, mock_agent_draft, mock_skills_draft):
417444
"""Test publishing version with no tools or relations"""
@@ -1473,8 +1500,10 @@ def test_remove_audit_fields_for_insert():
14731500
assert "other_field" in data
14741501
assert "create_time" not in data
14751502
assert "update_time" not in data
1476-
assert "created_by" not in data
1477-
assert "updated_by" not in data
1503+
assert "created_by" in data
1504+
assert data["created_by"] == "user1"
1505+
assert "updated_by" in data
1506+
assert data["updated_by"] == "user2"
14781507
assert "delete_flag" not in data
14791508

14801509

@@ -1908,6 +1937,14 @@ def test_publish_version_impl_with_a2a_new_agent(monkeypatch, mock_agent_draft,
19081937
version="1",
19091938
)
19101939

1940+
# Verify updated_by is set on all snapshot types
1941+
agent_snapshot = mock_insert_agent.call_args[0][0]
1942+
assert agent_snapshot["updated_by"] == "user1"
1943+
for call in mock_insert_tool.call_args_list:
1944+
assert call[0][0]["updated_by"] == "user1"
1945+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
1946+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
1947+
19111948

19121949
def test_publish_version_impl_with_a2a_existing_agent(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
19131950
"""Test publishing version with publish_as_a2a=True for an existing A2A agent"""
@@ -2068,6 +2105,14 @@ def test_publish_version_impl_without_a2a(monkeypatch, mock_agent_draft, mock_to
20682105
a2a_agent_db_mock.get_server_agent_by_agent_id.assert_not_called()
20692106
a2a_agent_db_mock.create_server_agent.assert_not_called()
20702107

2108+
# Verify updated_by is set on all snapshot types
2109+
agent_snapshot = mock_insert_agent.call_args[0][0]
2110+
assert agent_snapshot["updated_by"] == "user1"
2111+
for call in mock_insert_tool.call_args_list:
2112+
assert call[0][0]["updated_by"] == "user1"
2113+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2114+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2115+
20712116

20722117
def test_publish_version_impl_with_a2a_streaming_agent(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
20732118
"""Test publishing A2A agent that supports streaming"""
@@ -2109,6 +2154,14 @@ def test_publish_version_impl_with_a2a_streaming_agent(monkeypatch, mock_agent_d
21092154
assert result["a2a_agent"]["streaming"] is True
21102155
assert result["a2a_agent_card"]["streaming"] is True
21112156

2157+
# Verify updated_by is set on all snapshot types
2158+
agent_snapshot = mock_insert_agent.call_args[0][0]
2159+
assert agent_snapshot["updated_by"] == "user1"
2160+
for call in mock_insert_tool.call_args_list:
2161+
assert call[0][0]["updated_by"] == "user1"
2162+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2163+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2164+
21122165

21132166
def test_publish_version_impl_with_a2a_existing_agent_no_name(monkeypatch, mock_tools_draft, mock_relations_draft, mock_skills_draft):
21142167
"""Test publishing version with publish_as_a2a=True for an existing A2A agent that has no name - uses default name"""
@@ -2187,6 +2240,14 @@ def test_publish_version_impl_with_a2a_existing_agent_no_name(monkeypatch, mock_
21872240
version="1",
21882241
)
21892242

2243+
# Verify updated_by is set on all snapshot types
2244+
agent_snapshot = mock_insert_agent.call_args[0][0]
2245+
assert agent_snapshot["updated_by"] == "user1"
2246+
for call in mock_insert_tool.call_args_list:
2247+
assert call[0][0]["updated_by"] == "user1"
2248+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2249+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2250+
21902251

21912252
def test_publish_version_impl_with_a2a_empty_string_name(monkeypatch, mock_tools_draft, mock_relations_draft, mock_skills_draft):
21922253
"""Test publishing with A2A when agent name is empty string - uses default name"""
@@ -2242,6 +2303,14 @@ def test_publish_version_impl_with_a2a_empty_string_name(monkeypatch, mock_tools
22422303
call_kwargs = a2a_agent_db_mock.create_server_agent.call_args[1]
22432304
assert call_kwargs["name"] == "Agent-55"
22442305

2306+
# Verify updated_by is set on all snapshot types
2307+
agent_snapshot = mock_insert_agent.call_args[0][0]
2308+
assert agent_snapshot["updated_by"] == "user1"
2309+
for call in mock_insert_tool.call_args_list:
2310+
assert call[0][0]["updated_by"] == "user1"
2311+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2312+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2313+
22452314

22462315
def test_publish_version_impl_with_a2a_missing_endpoint_id_in_response(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
22472316
"""Test A2A agent creation response without endpoint_id - card is still created with None endpoint_id"""
@@ -2343,6 +2412,14 @@ def test_publish_version_impl_with_a2a_existing_agent_keeps_endpoint_id(monkeypa
23432412
assert result["a2a_agent_card"]["agent_card_url"] == "/nb/a2a/a2a_1_persistent/.well-known/agent-card.json"
23442413
assert result["a2a_agent_card"]["rest_endpoints"]["message_send"] == "/nb/a2a/a2a_1_persistent/message:send"
23452414

2415+
# Verify updated_by is set on all snapshot types
2416+
agent_snapshot = mock_insert_agent.call_args[0][0]
2417+
assert agent_snapshot["updated_by"] == "user1"
2418+
for call in mock_insert_tool.call_args_list:
2419+
assert call[0][0]["updated_by"] == "user1"
2420+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2421+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2422+
23462423

23472424
def test_publish_version_impl_with_a2a_result_contains_both_keys(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
23482425
"""Test that publish_version_impl returns both a2a_agent and a2a_agent_card keys when publish_as_a2a=True"""
@@ -2392,6 +2469,14 @@ def test_publish_version_impl_with_a2a_result_contains_both_keys(monkeypatch, mo
23922469
assert isinstance(result["a2a_agent"], dict)
23932470
assert isinstance(result["a2a_agent_card"], dict)
23942471

2472+
# Verify updated_by is set on all snapshot types
2473+
agent_snapshot = mock_insert_agent.call_args[0][0]
2474+
assert agent_snapshot["updated_by"] == "user1"
2475+
for call in mock_insert_tool.call_args_list:
2476+
assert call[0][0]["updated_by"] == "user1"
2477+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2478+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2479+
23952480

23962481
def test_publish_version_impl_with_a2a_description_none(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
23972482
"""Test A2A agent creation when agent draft has no description"""
@@ -2439,6 +2524,14 @@ def test_publish_version_impl_with_a2a_description_none(monkeypatch, mock_agent_
24392524
# Agent card should reflect None description
24402525
assert result["a2a_agent_card"]["description"] is None
24412526

2527+
# Verify updated_by is set on all snapshot types
2528+
agent_snapshot = mock_insert_agent.call_args[0][0]
2529+
assert agent_snapshot["updated_by"] == "user1"
2530+
for call in mock_insert_tool.call_args_list:
2531+
assert call[0][0]["updated_by"] == "user1"
2532+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2533+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2534+
24422535

24432536
def test_publish_version_impl_with_a2a_existing_agent_description_update(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
24442537
"""Test that existing A2A agent updates its description from agent_draft"""
@@ -2493,6 +2586,14 @@ def test_publish_version_impl_with_a2a_existing_agent_description_update(monkeyp
24932586
assert result["a2a_agent_card"]["name"] == "Test Agent"
24942587
assert result["a2a_agent_card"]["description"] == "Test Description"
24952588

2589+
# Verify updated_by is set on all snapshot types
2590+
agent_snapshot = mock_insert_agent.call_args[0][0]
2591+
assert agent_snapshot["updated_by"] == "user1"
2592+
for call in mock_insert_tool.call_args_list:
2593+
assert call[0][0]["updated_by"] == "user1"
2594+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2595+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2596+
24962597

24972598
def test_publish_version_impl_with_a2a_agent_card_all_fields(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft):
24982599
"""Test A2A agent card contains all expected fields"""
@@ -2554,6 +2655,14 @@ def test_publish_version_impl_with_a2a_agent_card_all_fields(monkeypatch, mock_a
25542655
assert card["jsonrpc_url"] == f"{expected_base_path}/v1"
25552656
assert card["jsonrpc_methods"] == ["SendMessage", "SendStreamingMessage", "GetTask"]
25562657

2658+
# Verify updated_by is set on all snapshot types
2659+
agent_snapshot = mock_insert_agent.call_args[0][0]
2660+
assert agent_snapshot["updated_by"] == "user1"
2661+
for call in mock_insert_tool.call_args_list:
2662+
assert call[0][0]["updated_by"] == "user1"
2663+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2664+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2665+
25572666

25582667
def test_publish_version_impl_a2a_logging_on_create(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft, caplog):
25592668
"""Test that appropriate log messages are emitted for A2A agent creation"""
@@ -2599,6 +2708,14 @@ def test_publish_version_impl_a2a_logging_on_create(monkeypatch, mock_agent_draf
25992708
assert any("Creating/updating A2A Server agent" in msg for msg in log_messages)
26002709
assert any("A2A Server agent created/updated with endpoint_id=a2a_1_log" in msg for msg in log_messages)
26012710

2711+
# Verify updated_by is set on all snapshot types
2712+
agent_snapshot = mock_insert_agent.call_args[0][0]
2713+
assert agent_snapshot["updated_by"] == "user1"
2714+
for call in mock_insert_tool.call_args_list:
2715+
assert call[0][0]["updated_by"] == "user1"
2716+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2717+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"
2718+
26022719

26032720
def test_publish_version_impl_a2a_logging_on_update(monkeypatch, mock_agent_draft, mock_tools_draft, mock_relations_draft, mock_skills_draft, caplog):
26042721
"""Test that appropriate log messages are emitted for A2A agent update"""
@@ -2651,3 +2768,11 @@ def test_publish_version_impl_a2a_logging_on_update(monkeypatch, mock_agent_draf
26512768
assert any("A2A Server agent already exists" in msg for msg in log_messages)
26522769
assert any("Creating/updating A2A Server agent" in msg for msg in log_messages)
26532770
assert any("A2A Server agent created/updated with endpoint_id=a2a_1_existing" in msg for msg in log_messages)
2771+
2772+
# Verify updated_by is set on all snapshot types
2773+
agent_snapshot = mock_insert_agent.call_args[0][0]
2774+
assert agent_snapshot["updated_by"] == "user1"
2775+
for call in mock_insert_tool.call_args_list:
2776+
assert call[0][0]["updated_by"] == "user1"
2777+
assert mock_insert_relation.call_args[0][0]["updated_by"] == "user1"
2778+
assert mock_insert_skill.call_args[0][0]["updated_by"] == "user1"

0 commit comments

Comments
 (0)