Skip to content

Commit 316447b

Browse files
committed
COD-661: Rename relations to relationships
1 parent d7643fd commit 316447b

7 files changed

Lines changed: 118 additions & 115 deletions

smoke_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ async def test_list_tools(self) -> bool:
133133
result = await self.session.list_tools()
134134
tools = result.tools
135135

136-
expected_tools = {"codebase_consultant", "get_data_sources", "codebase_search", "fetch_artifacts", "get_artifact_relations"}
136+
expected_tools = {"codebase_consultant", "get_data_sources", "codebase_search", "fetch_artifacts", "get_artifact_relationships"}
137137
actual_tools = {tool.name for tool in tools}
138138

139139
if expected_tools == actual_tools:

src/codealive_mcp_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
# Import core components
2727
from core import codealive_lifespan, setup_debug_logging
2828
from middleware import N8NRemoveParametersMiddleware
29-
from tools import codebase_consultant, get_data_sources, fetch_artifacts, codebase_search, get_artifact_relations
29+
from tools import codebase_consultant, get_data_sources, fetch_artifacts, codebase_search, get_artifact_relationships
3030

3131
# Initialize FastMCP server with lifespan and enhanced system instructions
3232
mcp = FastMCP(
@@ -99,7 +99,7 @@ async def health_check(request: Request) -> JSONResponse:
9999
mcp.tool()(get_data_sources)
100100
mcp.tool()(codebase_search)
101101
mcp.tool()(fetch_artifacts)
102-
mcp.tool()(get_artifact_relations)
102+
mcp.tool()(get_artifact_relationships)
103103

104104

105105
def main():
Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
"""Tests for the get_artifact_relations tool."""
1+
"""Tests for the get_artifact_relationships tool."""
22

33
import pytest
44
from unittest.mock import AsyncMock, MagicMock, patch
55

66
from fastmcp import Context
77

8-
from tools.artifact_relations import get_artifact_relations, _build_relations_xml, PROFILE_MAP
8+
from tools.artifact_relationships import get_artifact_relationships, _build_relationships_xml, PROFILE_MAP
99

1010

1111
class TestProfileMapping:
@@ -25,15 +25,15 @@ def test_references_only_maps_correctly(self):
2525
assert PROFILE_MAP["referencesOnly"] == "ReferencesOnly"
2626

2727

28-
class TestBuildRelationsXml:
29-
"""Test XML rendering of relation responses."""
28+
class TestBuildRelationshipsXml:
29+
"""Test XML rendering of relationship responses."""
3030

31-
def test_found_with_grouped_relations(self):
31+
def test_found_with_grouped_relationships(self):
3232
data = {
3333
"sourceIdentifier": "org/repo::path::Symbol",
3434
"profile": "CallsOnly",
3535
"found": True,
36-
"relations": [
36+
"relationships": [
3737
{
3838
"relationType": "OutgoingCalls",
3939
"totalCount": 57,
@@ -64,7 +64,7 @@ def test_found_with_grouped_relations(self):
6464
],
6565
}
6666

67-
result = _build_relations_xml(data)
67+
result = _build_relationships_xml(data)
6868

6969
assert 'sourceIdentifier="org/repo::path::Symbol"' in result
7070
assert 'profile="callsOnly"' in result
@@ -86,21 +86,21 @@ def test_not_found_renders_self_closing(self):
8686
"sourceIdentifier": "org/repo::path::Missing",
8787
"profile": "CallsOnly",
8888
"found": False,
89-
"relations": [],
89+
"relationships": [],
9090
}
9191

92-
result = _build_relations_xml(data)
92+
result = _build_relationships_xml(data)
9393

9494
assert 'found="false"' in result
9595
assert result.endswith("/>")
96-
assert "<relation_group" not in result
96+
assert "<relationship_group" not in result
9797

9898
def test_empty_group_still_rendered(self):
9999
data = {
100100
"sourceIdentifier": "org/repo::path::Symbol",
101101
"profile": "InheritanceOnly",
102102
"found": True,
103-
"relations": [
103+
"relationships": [
104104
{
105105
"relationType": "Ancestors",
106106
"totalCount": 0,
@@ -118,7 +118,7 @@ def test_empty_group_still_rendered(self):
118118
],
119119
}
120120

121-
result = _build_relations_xml(data)
121+
result = _build_relationships_xml(data)
122122

123123
assert 'type="ancestors"' in result
124124
assert 'type="descendants"' in result
@@ -129,7 +129,7 @@ def test_optional_fields_omitted_when_null(self):
129129
"sourceIdentifier": "org/repo::path::Symbol",
130130
"profile": "CallsOnly",
131131
"found": True,
132-
"relations": [
132+
"relationships": [
133133
{
134134
"relationType": "OutgoingCalls",
135135
"totalCount": 1,
@@ -145,7 +145,7 @@ def test_optional_fields_omitted_when_null(self):
145145
],
146146
}
147147

148-
result = _build_relations_xml(data)
148+
result = _build_relationships_xml(data)
149149

150150
assert 'identifier="org/repo::path::Target"' in result
151151
assert "filePath" not in result
@@ -157,7 +157,7 @@ def test_html_entities_escaped(self):
157157
"sourceIdentifier": "org/repo::path::Class<T>",
158158
"profile": "CallsOnly",
159159
"found": True,
160-
"relations": [
160+
"relationships": [
161161
{
162162
"relationType": "OutgoingCalls",
163163
"totalCount": 1,
@@ -173,7 +173,7 @@ def test_html_entities_escaped(self):
173173
],
174174
}
175175

176-
result = _build_relations_xml(data)
176+
result = _build_relationships_xml(data)
177177

178178
assert "Class&lt;T&gt;" in result
179179
assert "Method&lt;T&gt;" in result
@@ -187,17 +187,17 @@ def test_profile_mapped_back_to_mcp_name(self):
187187
"sourceIdentifier": "id",
188188
"profile": api_name,
189189
"found": False,
190-
"relations": [],
190+
"relationships": [],
191191
}
192-
result = _build_relations_xml(data)
192+
result = _build_relationships_xml(data)
193193
assert f'profile="{mcp_name}"' in result
194194

195195

196-
class TestGetArtifactRelationsTool:
196+
class TestGetArtifactRelationshipsTool:
197197
"""Test the async tool function."""
198198

199199
@pytest.mark.asyncio
200-
@patch("tools.artifact_relations.get_api_key_from_context")
200+
@patch("tools.artifact_relationships.get_api_key_from_context")
201201
async def test_default_profile_sends_calls_only(self, mock_get_api_key):
202202
mock_get_api_key.return_value = "test_key"
203203

@@ -210,7 +210,7 @@ async def test_default_profile_sends_calls_only(self, mock_get_api_key):
210210
"sourceIdentifier": "org/repo::path::Symbol",
211211
"profile": "CallsOnly",
212212
"found": True,
213-
"relations": [],
213+
"relationships": [],
214214
}
215215
mock_response.raise_for_status = MagicMock()
216216

@@ -222,7 +222,7 @@ async def test_default_profile_sends_calls_only(self, mock_get_api_key):
222222
mock_context.base_url = "https://app.codealive.ai"
223223
ctx.request_context.lifespan_context = mock_context
224224

225-
result = await get_artifact_relations(
225+
result = await get_artifact_relationships(
226226
ctx=ctx,
227227
identifier="org/repo::path::Symbol",
228228
)
@@ -233,7 +233,7 @@ async def test_default_profile_sends_calls_only(self, mock_get_api_key):
233233
assert 'found="true"' in result
234234

235235
@pytest.mark.asyncio
236-
@patch("tools.artifact_relations.get_api_key_from_context")
236+
@patch("tools.artifact_relationships.get_api_key_from_context")
237237
async def test_explicit_profile_maps_correctly(self, mock_get_api_key):
238238
mock_get_api_key.return_value = "test_key"
239239

@@ -246,7 +246,7 @@ async def test_explicit_profile_maps_correctly(self, mock_get_api_key):
246246
"sourceIdentifier": "id",
247247
"profile": "InheritanceOnly",
248248
"found": True,
249-
"relations": [],
249+
"relationships": [],
250250
}
251251
mock_response.raise_for_status = MagicMock()
252252

@@ -258,7 +258,7 @@ async def test_explicit_profile_maps_correctly(self, mock_get_api_key):
258258
mock_context.base_url = "https://app.codealive.ai"
259259
ctx.request_context.lifespan_context = mock_context
260260

261-
await get_artifact_relations(
261+
await get_artifact_relationships(
262262
ctx=ctx,
263263
identifier="id",
264264
profile="inheritanceOnly",
@@ -270,21 +270,21 @@ async def test_explicit_profile_maps_correctly(self, mock_get_api_key):
270270
@pytest.mark.asyncio
271271
async def test_empty_identifier_returns_error(self):
272272
ctx = MagicMock(spec=Context)
273-
result = await get_artifact_relations(ctx=ctx, identifier="")
273+
result = await get_artifact_relationships(ctx=ctx, identifier="")
274274
assert "<error>" in result
275275
assert "required" in result
276276

277277
@pytest.mark.asyncio
278278
async def test_unsupported_profile_returns_error(self):
279279
ctx = MagicMock(spec=Context)
280-
result = await get_artifact_relations(
280+
result = await get_artifact_relationships(
281281
ctx=ctx, identifier="id", profile="invalidProfile"
282282
)
283283
assert "<error>" in result
284284
assert "Unsupported profile" in result
285285

286286
@pytest.mark.asyncio
287-
@patch("tools.artifact_relations.get_api_key_from_context")
287+
@patch("tools.artifact_relationships.get_api_key_from_context")
288288
async def test_api_error_returns_error_xml(self, mock_get_api_key):
289289
import httpx
290290

@@ -309,13 +309,13 @@ async def test_api_error_returns_error_xml(self, mock_get_api_key):
309309
mock_context.base_url = "https://app.codealive.ai"
310310
ctx.request_context.lifespan_context = mock_context
311311

312-
result = await get_artifact_relations(ctx=ctx, identifier="id")
312+
result = await get_artifact_relationships(ctx=ctx, identifier="id")
313313

314314
assert "<error>" in result
315315
assert "401" in result
316316

317317
@pytest.mark.asyncio
318-
@patch("tools.artifact_relations.get_api_key_from_context")
318+
@patch("tools.artifact_relationships.get_api_key_from_context")
319319
async def test_not_found_response_renders_correctly(self, mock_get_api_key):
320320
mock_get_api_key.return_value = "test_key"
321321

@@ -328,7 +328,7 @@ async def test_not_found_response_renders_correctly(self, mock_get_api_key):
328328
"sourceIdentifier": "org/repo::path::Missing",
329329
"profile": "CallsOnly",
330330
"found": False,
331-
"relations": [],
331+
"relationships": [],
332332
}
333333
mock_response.raise_for_status = MagicMock()
334334

@@ -340,7 +340,7 @@ async def test_not_found_response_renders_correctly(self, mock_get_api_key):
340340
mock_context.base_url = "https://app.codealive.ai"
341341
ctx.request_context.lifespan_context = mock_context
342342

343-
result = await get_artifact_relations(ctx=ctx, identifier="org/repo::path::Missing")
343+
result = await get_artifact_relationships(ctx=ctx, identifier="org/repo::path::Missing")
344344

345345
assert 'found="false"' in result
346-
assert "<relation_group" not in result
346+
assert "<relationship_group" not in result

src/tests/test_fetch_artifacts.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,15 @@ def test_artifact_structure_has_content_child(self):
9595
assert "<content>" in result
9696

9797

98-
class TestBuildArtifactsXmlRelations:
99-
"""Test relations rendering in _build_artifacts_xml."""
98+
class TestBuildArtifactsXmlRelationships:
99+
"""Test relationships rendering in _build_artifacts_xml."""
100100

101-
def test_relations_with_outgoing_and_incoming(self):
101+
def test_relationships_with_outgoing_and_incoming(self):
102102
data = {"artifacts": [{
103103
"identifier": "repo::src/a.ts::FuncA",
104104
"content": "code",
105105
"contentByteSize": 4,
106-
"relations": {
106+
"relationships": {
107107
"outgoingCallsCount": 12,
108108
"outgoingCalls": [
109109
{"identifier": "repo::src/b.ts::FuncB", "summary": "Validates token"},
@@ -116,21 +116,21 @@ def test_relations_with_outgoing_and_incoming(self):
116116
}
117117
}]}
118118
result = _build_artifacts_xml(data)
119-
assert "<relations>" in result
120-
assert '</relations>' in result
119+
assert "<relationships>" in result
120+
assert '</relationships>' in result
121121
assert '<outgoing_calls count="12">' in result
122122
assert '</outgoing_calls>' in result
123123
assert '<incoming_calls count="3">' in result
124124
assert '</incoming_calls>' in result
125125
assert 'identifier="repo::src/b.ts::FuncB" summary="Validates token"' in result
126126
assert 'identifier="repo::src/d.ts::FuncD" summary="Entry point"' in result
127127

128-
def test_relations_with_only_outgoing(self):
128+
def test_relationships_with_only_outgoing(self):
129129
data = {"artifacts": [{
130130
"identifier": "repo::src/a.ts::FuncA",
131131
"content": "code",
132132
"contentByteSize": 4,
133-
"relations": {
133+
"relationships": {
134134
"outgoingCallsCount": 2,
135135
"outgoingCalls": [
136136
{"identifier": "repo::src/b.ts::FuncB", "summary": "Does stuff"},
@@ -140,36 +140,36 @@ def test_relations_with_only_outgoing(self):
140140
}
141141
}]}
142142
result = _build_artifacts_xml(data)
143-
assert "<relations>" in result
143+
assert "<relationships>" in result
144144
assert "<outgoing_calls" in result
145145
assert "<incoming_calls" not in result
146146

147-
def test_relations_null_omits_relations_element(self):
147+
def test_relationships_null_omits_relationships_element(self):
148148
data = {"artifacts": [{
149149
"identifier": "repo::src/a.ts",
150150
"content": "code",
151151
"contentByteSize": 4,
152-
"relations": None,
152+
"relationships": None,
153153
}]}
154154
result = _build_artifacts_xml(data)
155-
assert "<relations>" not in result
155+
assert "<relationships>" not in result
156156
assert "<content>" in result
157157

158-
def test_relations_absent_omits_relations_element(self):
158+
def test_relationships_absent_omits_relationships_element(self):
159159
data = {"artifacts": [{
160160
"identifier": "repo::src/a.ts",
161161
"content": "code",
162162
"contentByteSize": 4,
163163
}]}
164164
result = _build_artifacts_xml(data)
165-
assert "<relations>" not in result
165+
assert "<relationships>" not in result
166166

167-
def test_relations_call_without_summary_omits_summary_attr(self):
167+
def test_relationships_call_without_summary_omits_summary_attr(self):
168168
data = {"artifacts": [{
169169
"identifier": "repo::src/a.ts::FuncA",
170170
"content": "code",
171171
"contentByteSize": 4,
172-
"relations": {
172+
"relationships": {
173173
"outgoingCallsCount": 1,
174174
"outgoingCalls": [
175175
{"identifier": "repo::src/b.ts::FuncB", "summary": None},
@@ -182,12 +182,12 @@ def test_relations_call_without_summary_omits_summary_attr(self):
182182
assert 'identifier="repo::src/b.ts::FuncB"/>' in result
183183
assert 'summary' not in result.split('FuncB')[1].split('/>')[0]
184184

185-
def test_relations_escapes_xml_in_summary(self):
185+
def test_relationships_escapes_xml_in_summary(self):
186186
data = {"artifacts": [{
187187
"identifier": "repo::src/a.ts::FuncA",
188188
"content": "code",
189189
"contentByteSize": 4,
190-
"relations": {
190+
"relationships": {
191191
"outgoingCallsCount": 1,
192192
"outgoingCalls": [
193193
{"identifier": "repo::src/b.ts::FuncB", "summary": 'Checks if x < 10 & y > 5'},

src/tools/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""Tool implementations for CodeAlive MCP server."""
22

3-
from .artifact_relations import get_artifact_relations
3+
from .artifact_relationships import get_artifact_relationships
44
from .chat import codebase_consultant
55
from .datasources import get_data_sources
66
from .fetch_artifacts import fetch_artifacts
77
from .search import codebase_search
88

9-
__all__ = ['codebase_consultant', 'get_data_sources', 'fetch_artifacts', 'codebase_search', 'get_artifact_relations']
9+
__all__ = ['codebase_consultant', 'get_data_sources', 'fetch_artifacts', 'codebase_search', 'get_artifact_relationships']

0 commit comments

Comments
 (0)