Skip to content

Commit 01c7a68

Browse files
Merge pull request #438 from microsoft/macae-v3-fr-dev-92
feat: Macae v3 fr dev 92
2 parents 6039bf7 + fe32cfa commit 01c7a68

File tree

8 files changed

+288
-182
lines changed

8 files changed

+288
-182
lines changed

src/backend/common/database/cosmosdb.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
AgentMessage,
3131
TeamConfiguration,
3232
DataType,
33+
UserCurrentTeam,
3334
)
3435

3536

@@ -42,6 +43,7 @@ class CosmosDBClient(DatabaseBase):
4243
"step": Step,
4344
"agent_message": AgentMessage,
4445
"team_config": TeamConfiguration,
46+
"user_current_team": UserCurrentTeam,
4547
}
4648

4749
def __init__(
@@ -431,3 +433,31 @@ async def update_team(self, team: TeamConfiguration) -> None:
431433
team: The TeamConfiguration to update
432434
"""
433435
await self.update_item(team)
436+
437+
async def get_current_team(self, user_id: str, team_id: str) -> UserCurrentTeam:
438+
"""Retrieve the current team for a user."""
439+
await self._ensure_initialized()
440+
if self.container is None:
441+
return None
442+
443+
query = "SELECT * FROM c WHERE c.user_id=@user_id AND c.is_default=true"
444+
parameters = [
445+
{"name": "@user_id", "value": user_id},
446+
{"name": "@team_id", "value": team_id},
447+
]
448+
449+
items = self.container.query_items(query=query, parameters=parameters)
450+
async for item in items:
451+
return UserCurrentTeam(**item)
452+
453+
return None
454+
async def set_current_team(self, current_team: UserCurrentTeam) -> None:
455+
"""Set the current team for a user."""
456+
await self._ensure_initialized()
457+
await self.add_item(current_team)
458+
459+
460+
async def update_current_team(self, current_team: UserCurrentTeam) -> None:
461+
"""Update the current team for a user."""
462+
await self._ensure_initialized()
463+
await self.update_item(current_team)

src/backend/common/database/database_base.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
Plan,
1010
Step,
1111
TeamConfiguration,
12+
UserCurrentTeam,
1213
)
1314

1415

@@ -80,6 +81,7 @@ async def add_plan(self, plan: Plan) -> None:
8081
"""Add a plan to the database."""
8182
pass
8283

84+
8385
@abstractmethod
8486
async def update_plan(self, plan: Plan) -> None:
8587
"""Update a plan in the database."""
@@ -184,7 +186,21 @@ async def __aexit__(self, exc_type, exc, tb):
184186
"""Async context manager exit."""
185187
await self.close()
186188

187-
# Convenience aliases
189+
@abstractmethod
188190
async def get_steps_for_plan(self, plan_id: str) -> List[Step]:
189191
"""Convenience method aliasing get_steps_by_plan for compatibility."""
190192
pass
193+
194+
@abstractmethod
195+
async def get_current_team(self, user_id: str, team_id: str) -> UserCurrentTeam:
196+
"""Retrieve the current team for a user."""
197+
pass
198+
199+
@abstractmethod
200+
async def set_current_team(self, current_team: UserCurrentTeam) -> None:
201+
pass
202+
203+
@abstractmethod
204+
async def update_current_team(self, current_team: UserCurrentTeam) -> None:
205+
"""Update the current team for a user."""
206+
pass

src/backend/common/models/messages_kernel.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ class StartingTask(KernelBaseModel):
188188
class TeamSelectionRequest(KernelBaseModel):
189189
"""Request model for team selection."""
190190
team_id: str
191-
session_id: Optional[str] = None
192191

193192
class TeamConfiguration(BaseDataModel):
194193
"""Represents a team configuration stored in the database."""

src/backend/v3/api/router.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from common.database.database_factory import DatabaseFactory
1111
from common.models.messages_kernel import (GeneratePlanRequest, InputTask,
1212
Plan, PlanStatus,
13-
TeamSelectionRequest)
13+
TeamSelectionRequest, UserCurrentTeam)
1414
from common.utils.event_utils import track_event_if_configured
1515
from common.utils.utils_kernel import rai_success, rai_validate_team_config
1616
from fastapi import (APIRouter, BackgroundTasks, Depends, FastAPI, File,
@@ -813,9 +813,21 @@ async def select_team_endpoint(selection: TeamSelectionRequest, request: Request
813813
status_code=404,
814814
detail=f"Team configuration '{selection.team_id}' not found or access denied"
815815
)
816-
817-
# Generate session ID if not provided
818-
session_id = selection.session_id or str(uuid.uuid4())
816+
set_team = await team_service.handle_team_selection(user_id=user_id, team_id=selection.team_id)
817+
if not set_team:
818+
track_event_if_configured(
819+
"Team selected",
820+
{
821+
"status": "failed",
822+
"team_id": selection.team_id,
823+
"team_name": team_configuration.name,
824+
"user_id": user_id
825+
},
826+
)
827+
raise HTTPException(
828+
status_code=404,
829+
detail=f"Team configuration '{selection.team_id}' failed to set"
830+
)
819831

820832
# save to in-memory config for current user
821833
team_config.set_current_team(user_id=user_id, team_configuration=team_configuration)
@@ -827,8 +839,7 @@ async def select_team_endpoint(selection: TeamSelectionRequest, request: Request
827839
"status": "success",
828840
"team_id": selection.team_id,
829841
"team_name": team_configuration.name,
830-
"user_id": user_id,
831-
"session_id": session_id,
842+
"user_id": user_id
832843
},
833844
)
834845

@@ -837,7 +848,6 @@ async def select_team_endpoint(selection: TeamSelectionRequest, request: Request
837848
"message": f"Team '{team_configuration.name}' selected successfully",
838849
"team_id": selection.team_id,
839850
"team_name": team_configuration.name,
840-
"session_id": session_id,
841851
"agents_count": len(team_configuration.agents),
842852
"team_description": team_configuration.description,
843853
}

src/backend/v3/common/services/team_service.py

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@
55
from datetime import datetime, timezone
66
from typing import Any, Dict, List, Optional, Tuple
77

8-
from azure.core.credentials import AzureKeyCredential
9-
from azure.core.exceptions import (ClientAuthenticationError,
10-
HttpResponseError, ResourceNotFoundError)
11-
from azure.identity import DefaultAzureCredential
8+
from azure.core.exceptions import (
9+
ClientAuthenticationError,
10+
HttpResponseError,
11+
ResourceNotFoundError,
12+
)
13+
1214
from azure.search.documents.indexes import SearchIndexClient
1315
from common.config.app_config import config
1416
from common.database.database_base import DatabaseBase
15-
from common.models.messages_kernel import (StartingTask, TeamAgent,
16-
TeamConfiguration)
17+
from common.models.messages_kernel import (
18+
StartingTask,
19+
TeamAgent,
20+
TeamConfiguration,
21+
UserCurrentTeam,
22+
)
1723
from v3.common.services.foundry_service import FoundryService
1824

1925

@@ -218,6 +224,52 @@ async def get_team_configuration(
218224
self.logger.error("Error retrieving team configuration: %s", str(e))
219225
return None
220226

227+
async def delete_user_current_team(self, user_id: str) -> bool:
228+
"""
229+
Delete the current team for a user.
230+
231+
Args:
232+
user_id: User ID to delete the current team for
233+
234+
Returns:
235+
True if successful, False otherwise
236+
"""
237+
try:
238+
await self.memory_context.delete_user_current_team(user_id)
239+
self.logger.info("Successfully deleted current team for user %s", user_id)
240+
return True
241+
242+
except Exception as e:
243+
self.logger.error("Error deleting current team: %s", str(e))
244+
return False
245+
246+
async def handle_team_selection(self, user_id: str, team_id: str) -> bool:
247+
"""
248+
Set a default team for a user.
249+
250+
Args:
251+
user_id: User ID to set the default team for
252+
team_id: Team ID to set as default
253+
254+
Returns:
255+
True if successful, False otherwise
256+
"""
257+
try:
258+
current_team = await self.memory_context.get_current_team(user_id, team_id)
259+
260+
if current_team is None:
261+
current_team = UserCurrentTeam(user_id=user_id, team_id=team_id)
262+
await self.memory_context.set_current_team(current_team)
263+
return True
264+
else:
265+
current_team.team_id = team_id
266+
await self.memory_context.update_current_team(current_team)
267+
return True
268+
269+
except Exception as e:
270+
self.logger.error("Error setting default team: %s", str(e))
271+
return False
272+
221273
async def get_all_team_configurations(
222274
self, user_id: str
223275
) -> List[TeamConfiguration]:
@@ -345,7 +397,7 @@ async def validate_team_models(
345397
missing_models: List[str] = []
346398
for model in required_models:
347399
# Temporary bypass for known deployed models
348-
if model.lower() in ['gpt-4o', 'o3', 'gpt-4', 'gpt-35-turbo']:
400+
if model.lower() in ["gpt-4o", "o3", "gpt-4", "gpt-35-turbo"]:
349401
continue
350402
if model not in available_models:
351403
missing_models.append(model)

0 commit comments

Comments
 (0)