Skip to content

Commit 8464f3b

Browse files
committed
Add team_id to Plan model and enforce in API
Added the team_id field to the Plan data model and updated the create_plan endpoint to require team_id, returning an error if missing. Also updated CosmosDB queries to include user_id and serialize datetime fields. Removed the /generate_plan endpoint from the router.
1 parent 794fe63 commit 8464f3b

File tree

3 files changed

+16
-158
lines changed

3 files changed

+16
-158
lines changed

src/backend/common/database/cosmosdb.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import json
44
import logging
55
import uuid
6-
from datetime import datetime, timezone
6+
7+
import datetime
78
from typing import Any, Dict, List, Optional, Type
89

910
from azure.cosmos import PartitionKey, exceptions
@@ -111,7 +112,10 @@ async def add_item(self, item: BaseDataModel) -> None:
111112
try:
112113
# Convert to dictionary and handle datetime serialization
113114
document = item.model_dump()
114-
document = json.loads(json.dumps(document, cls=DateTimeEncoder))
115+
116+
for key, value in list(document.items()):
117+
if isinstance(value, datetime.datetime):
118+
document[key] = value.isoformat()
115119

116120
await self.container.create_item(body=document)
117121
except Exception as e:
@@ -160,6 +164,7 @@ async def query_items(
160164
items = self.container.query_items(query=query, parameters=parameters)
161165
result_list = []
162166
async for item in items:
167+
item["ts"] = item["_ts"]
163168
try:
164169
result_list.append(model_class.model_validate(item))
165170
except Exception as validation_error:
@@ -233,6 +238,7 @@ async def get_plan_by_plan_id(self, plan_id: str) -> Optional[Plan]:
233238
parameters = [
234239
{"name": "@plan_id", "value": plan_id},
235240
{"name": "@data_type", "value": "plan"},
241+
{"name": "@user_id", "value": self.user_id},
236242
]
237243
results = await self.query_items(query, parameters, Plan)
238244
return results[0] if results else None

src/backend/common/models/messages_kernel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class Plan(BaseDataModel):
103103
"""Represents a plan containing multiple steps."""
104104

105105
data_type: Literal["plan"] = Field("plan", Literal=True)
106+
team_id: str
106107
session_id: str
107108
user_id: str
108109
initial_goal: str

src/backend/v3/api/router.py

Lines changed: 7 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ async def create_plan_endpoint(input_task: InputTask, request: Request):
113113
)
114114
raise HTTPException(status_code=400, detail="no user")
115115

116+
if not input_task.team_id:
117+
track_event_if_configured(
118+
"TeamIDNofound", {"status_code": 400, "detail": "no team id"}
119+
)
120+
raise HTTPException(status_code=400, detail="no team id")
121+
116122
# Generate session ID if not provided
117123
if not input_task.session_id:
118124
input_task.session_id = str(uuid.uuid4())
@@ -124,6 +130,7 @@ async def create_plan_endpoint(input_task: InputTask, request: Request):
124130
# Create a new Plan object
125131
plan = Plan(
126132
session_id=input_task.session_id,
133+
team_id=input_task.team_id,
127134
user_id=user_id,
128135
initial_goal=input_task.description,
129136
overall_status=PlanStatus.in_progress,
@@ -162,162 +169,6 @@ async def create_plan_endpoint(input_task: InputTask, request: Request):
162169
raise HTTPException(status_code=400, detail=f"Error creating plan: {e}") from e
163170

164171

165-
@app_v3.post("/generate_plan")
166-
async def generate_plan_endpoint(
167-
generate_plan_request: GeneratePlanRequest, request: Request
168-
):
169-
"""
170-
Generate plan steps for an existing plan using the planner agent.
171-
172-
---
173-
tags:
174-
- Plans
175-
parameters:
176-
- name: user_principal_id
177-
in: header
178-
type: string
179-
required: true
180-
description: User ID extracted from the authentication header
181-
- name: body
182-
in: body
183-
required: true
184-
schema:
185-
type: object
186-
properties:
187-
plan_id:
188-
type: string
189-
description: The ID of the existing plan to generate steps for
190-
responses:
191-
200:
192-
description: Plan generation completed successfully
193-
schema:
194-
type: object
195-
properties:
196-
status:
197-
type: string
198-
description: Success message
199-
plan_id:
200-
type: string
201-
description: The ID of the plan that was generated
202-
steps_created:
203-
type: integer
204-
description: Number of steps created
205-
400:
206-
description: Invalid request or processing error
207-
schema:
208-
type: object
209-
properties:
210-
detail:
211-
type: string
212-
description: Error message
213-
404:
214-
description: Plan not found
215-
schema:
216-
type: object
217-
properties:
218-
detail:
219-
type: string
220-
description: Error message
221-
"""
222-
# Get authenticated user
223-
authenticated_user = get_authenticated_user_details(request_headers=request.headers)
224-
user_id = authenticated_user["user_principal_id"]
225-
226-
if not user_id:
227-
track_event_if_configured(
228-
"UserIdNotFound", {"status_code": 400, "detail": "no user"}
229-
)
230-
raise HTTPException(status_code=400, detail="no user")
231-
232-
try:
233-
# Initialize memory store
234-
memory_store = await DatabaseFactory.get_database(user_id=user_id)
235-
236-
# Get the existing plan
237-
plan = await memory_store.get_plan_by_plan_id(
238-
plan_id=generate_plan_request.plan_id
239-
)
240-
if not plan:
241-
track_event_if_configured(
242-
"GeneratePlanNotFound",
243-
{
244-
"status_code": 404,
245-
"detail": "Plan not found",
246-
"plan_id": generate_plan_request.plan_id,
247-
},
248-
)
249-
raise HTTPException(status_code=404, detail="Plan not found")
250-
251-
# Create the agents for this session
252-
client = None
253-
try:
254-
client = config.get_ai_project_client()
255-
except Exception as client_exc:
256-
logging.error(f"Error creating AIProjectClient: {client_exc}")
257-
258-
agents = await AgentFactory.create_all_agents(
259-
session_id=plan.session_id,
260-
user_id=user_id,
261-
memory_store=memory_store,
262-
client=client,
263-
)
264-
265-
# Get the group chat manager to process the plan
266-
group_chat_manager = agents[AgentType.GROUP_CHAT_MANAGER.value]
267-
268-
# Create an InputTask from the plan's initial goal
269-
input_task = InputTask(
270-
session_id=plan.session_id, description=plan.initial_goal
271-
)
272-
273-
# Use the group chat manager to generate the plan steps
274-
await group_chat_manager.handle_input_task(input_task)
275-
276-
# Get the updated plan with steps
277-
updated_plan = await memory_store.get_plan_by_plan_id(
278-
plan_id=generate_plan_request.plan_id
279-
)
280-
steps = await memory_store.get_steps_by_plan(
281-
plan_id=generate_plan_request.plan_id
282-
)
283-
284-
# Log successful plan generation
285-
track_event_if_configured(
286-
"PlanGenerated",
287-
{
288-
"status": f"Plan generation completed for plan ID: {generate_plan_request.plan_id}",
289-
"plan_id": generate_plan_request.plan_id,
290-
"session_id": plan.session_id,
291-
"steps_created": len(steps),
292-
},
293-
)
294-
295-
if client:
296-
try:
297-
client.close()
298-
except Exception as e:
299-
logging.error(f"Error closing AIProjectClient: {e}")
300-
301-
return {
302-
"status": "Plan generation completed successfully",
303-
"plan_id": generate_plan_request.plan_id,
304-
"steps_created": len(steps),
305-
}
306-
307-
except HTTPException:
308-
# Re-raise HTTP exceptions
309-
raise
310-
except Exception as e:
311-
track_event_if_configured(
312-
"GeneratePlanError",
313-
{
314-
"plan_id": generate_plan_request.plan_id,
315-
"error": str(e),
316-
},
317-
)
318-
raise HTTPException(status_code=400, detail=f"Error generating plan: {e}")
319-
320-
321172
@app_v3.post("/upload_team_config")
322173
async def upload_team_config_endpoint(request: Request, file: UploadFile = File(...)):
323174
"""

0 commit comments

Comments
 (0)