Skip to content

Commit 96313c8

Browse files
Local_date_fix_updated
1 parent 8a041cf commit 96313c8

File tree

7 files changed

+389
-70
lines changed

7 files changed

+389
-70
lines changed

src/backend/app_kernel.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,25 @@
8585
async def input_task_endpoint(input_task: InputTask, request: Request):
8686
"""
8787
Receive the initial input task from the user.
88+
89+
---
90+
parameters:
91+
- name: body
92+
in: body
93+
required: true
94+
schema:
95+
type: object
96+
properties:
97+
session_id:
98+
type: string
99+
description: Session ID for the task
100+
description:
101+
type: string
102+
description: Description of the task to be performed
103+
user_locale:
104+
type: string
105+
description: User's locale preference (e.g., 'en_US', 'en_GB', 'de_DE')
106+
default: 'en_GB'
88107
"""
89108
# Fix 1: Properly await the async rai_success function
90109
if not await rai_success(input_task.description):
@@ -115,6 +134,9 @@ async def input_task_endpoint(input_task: InputTask, request: Request):
115134
if not input_task.session_id:
116135
input_task.session_id = str(uuid.uuid4())
117136

137+
# Extract user locale from request headers or input task
138+
user_locale = request.headers.get("X-User-Locale", input_task.user_locale or "en_GB")
139+
118140
try:
119141
# Create all agents instead of just the planner agent
120142
# This ensures other agents are created first and the planner has access to them
@@ -132,6 +154,7 @@ async def input_task_endpoint(input_task: InputTask, request: Request):
132154
user_id=user_id,
133155
memory_store=memory_store,
134156
client=client,
157+
user_locale=user_locale, # ✅ Add this
135158
)
136159

137160
group_chat_manager = agents[AgentType.GROUP_CHAT_MANAGER.value]
@@ -229,6 +252,10 @@ async def human_feedback_endpoint(human_feedback: HumanFeedback, request: Reques
229252
user_id:
230253
type: string
231254
description: The user ID providing the feedback
255+
user_locale:
256+
type: string
257+
description: User's locale preference (e.g., 'en_US', 'en_GB', 'de_DE')
258+
default: 'en_GB'
232259
responses:
233260
200:
234261
description: Feedback received successfully
@@ -256,6 +283,9 @@ async def human_feedback_endpoint(human_feedback: HumanFeedback, request: Reques
256283
human_feedback.session_id, user_id
257284
)
258285

286+
# Extract user locale from request headers or feedback object
287+
user_locale = request.headers.get("X-User-Locale", human_feedback.user_locale or "en_GB")
288+
259289
client = None
260290
try:
261291
client = config.get_ai_project_client()
@@ -268,6 +298,7 @@ async def human_feedback_endpoint(human_feedback: HumanFeedback, request: Reques
268298
user_id=user_id,
269299
memory_store=memory_store,
270300
client=client,
301+
user_locale=user_locale, # ✅ Add this
271302
)
272303

273304
if human_agent is None:
@@ -476,6 +507,10 @@ async def approve_step_endpoint(
476507
kernel, memory_store = await initialize_runtime_and_context(
477508
human_feedback.session_id, user_id
478509
)
510+
511+
# Extract user locale from request headers or feedback object
512+
user_locale = request.headers.get("X-User-Locale", human_feedback.user_locale or "en_GB")
513+
479514
client = None
480515
try:
481516
client = config.get_ai_project_client()
@@ -486,6 +521,7 @@ async def approve_step_endpoint(
486521
user_id=user_id,
487522
memory_store=memory_store,
488523
client=client,
524+
user_locale=user_locale, # ✅ Add this
489525
)
490526

491527
# Send the approval to the group chat manager
@@ -970,6 +1006,187 @@ async def get_agent_tools():
9701006
return []
9711007

9721008

1009+
@app.post("/api/tasks")
1010+
async def handle_task(request: Request):
1011+
"""
1012+
Handle individual tasks with user locale support.
1013+
This endpoint demonstrates how to pass user_locale to agent tools.
1014+
1015+
Expected request body:
1016+
{
1017+
"task_type": "schedule_orientation",
1018+
"employee_name": "John Doe",
1019+
"date": "2025-07-15",
1020+
"user_locale": "en_US"
1021+
}
1022+
"""
1023+
authenticated_user = get_authenticated_user_details(request_headers=request.headers)
1024+
user_id = authenticated_user["user_principal_id"]
1025+
if not user_id:
1026+
track_event_if_configured(
1027+
"UserIdNotFound", {"status_code": 400, "detail": "no user"}
1028+
)
1029+
raise HTTPException(status_code=400, detail="no user")
1030+
1031+
try:
1032+
data = await request.json()
1033+
user_locale = data.get("user_locale", "en_GB") # fallback to en_GB
1034+
task_type = data.get("task_type")
1035+
1036+
# Import the HR tools
1037+
from kernel_tools.hr_tools import HrTools
1038+
1039+
if task_type == "schedule_orientation":
1040+
employee_name = data.get("employee_name")
1041+
date = data.get("date")
1042+
1043+
if not employee_name or not date:
1044+
raise HTTPException(status_code=400, detail="employee_name and date are required")
1045+
1046+
# Example: Call the HR tool function with user_locale
1047+
result = await HrTools.schedule_orientation_session(
1048+
employee_name=employee_name,
1049+
date=date,
1050+
user_locale=user_locale
1051+
)
1052+
1053+
track_event_if_configured(
1054+
"TaskExecuted",
1055+
{
1056+
"task_type": task_type,
1057+
"user_locale": user_locale,
1058+
"employee_name": employee_name,
1059+
"date": date,
1060+
},
1061+
)
1062+
1063+
return {
1064+
"status": "success",
1065+
"result": result,
1066+
"user_locale": user_locale
1067+
}
1068+
1069+
elif task_type == "schedule_performance_review":
1070+
employee_name = data.get("employee_name")
1071+
date = data.get("date")
1072+
1073+
if not employee_name or not date:
1074+
raise HTTPException(status_code=400, detail="employee_name and date are required")
1075+
1076+
result = await HrTools.schedule_performance_review(
1077+
employee_name=employee_name,
1078+
date=date,
1079+
user_locale=user_locale
1080+
)
1081+
1082+
return {
1083+
"status": "success",
1084+
"result": result,
1085+
"user_locale": user_locale
1086+
}
1087+
1088+
elif task_type == "process_leave_request":
1089+
employee_name = data.get("employee_name")
1090+
leave_type = data.get("leave_type")
1091+
start_date = data.get("start_date")
1092+
end_date = data.get("end_date")
1093+
1094+
if not all([employee_name, leave_type, start_date, end_date]):
1095+
raise HTTPException(status_code=400, detail="employee_name, leave_type, start_date, and end_date are required")
1096+
1097+
result = await HrTools.process_leave_request(
1098+
employee_name=employee_name,
1099+
leave_type=leave_type,
1100+
start_date=start_date,
1101+
end_date=end_date,
1102+
user_locale=user_locale
1103+
)
1104+
1105+
return {
1106+
"status": "success",
1107+
"result": result,
1108+
"user_locale": user_locale
1109+
}
1110+
1111+
elif task_type == "add_mobile_extras_pack":
1112+
# Example for Product tools
1113+
from kernel_tools.product_tools import ProductTools
1114+
1115+
new_extras_pack_name = data.get("new_extras_pack_name")
1116+
start_date = data.get("start_date")
1117+
1118+
if not new_extras_pack_name or not start_date:
1119+
raise HTTPException(status_code=400, detail="new_extras_pack_name and start_date are required")
1120+
1121+
result = await ProductTools.add_mobile_extras_pack(
1122+
new_extras_pack_name=new_extras_pack_name,
1123+
start_date=start_date,
1124+
user_locale=user_locale
1125+
)
1126+
1127+
return {
1128+
"status": "success",
1129+
"result": result,
1130+
"user_locale": user_locale
1131+
}
1132+
1133+
else:
1134+
raise HTTPException(status_code=400, detail=f"Unsupported task_type: {task_type}")
1135+
1136+
except Exception as e:
1137+
track_event_if_configured(
1138+
"TaskError",
1139+
{
1140+
"error": str(e),
1141+
"task_type": data.get("task_type") if 'data' in locals() else "unknown",
1142+
},
1143+
)
1144+
raise HTTPException(status_code=400, detail=f"Error executing task: {e}")
1145+
1146+
1147+
@app.get("/api/tasks/examples")
1148+
async def get_task_examples():
1149+
"""
1150+
Get examples of how to use the /api/tasks endpoint with different locales.
1151+
1152+
Returns example request payloads for testing the user_locale functionality.
1153+
"""
1154+
examples = {
1155+
"schedule_orientation_us": {
1156+
"task_type": "schedule_orientation",
1157+
"employee_name": "John Doe",
1158+
"date": "2025-07-15",
1159+
"user_locale": "en_US"
1160+
},
1161+
"schedule_orientation_uk": {
1162+
"task_type": "schedule_orientation",
1163+
"employee_name": "Jane Smith",
1164+
"date": "2025-07-15",
1165+
"user_locale": "en_GB"
1166+
},
1167+
"process_leave_request": {
1168+
"task_type": "process_leave_request",
1169+
"employee_name": "Alice Johnson",
1170+
"leave_type": "Annual Leave",
1171+
"start_date": "2025-08-01",
1172+
"end_date": "2025-08-15",
1173+
"user_locale": "en_GB"
1174+
},
1175+
"add_mobile_extras": {
1176+
"task_type": "add_mobile_extras_pack",
1177+
"new_extras_pack_name": "International Roaming Pack",
1178+
"start_date": "2025-07-20",
1179+
"user_locale": "en_US"
1180+
}
1181+
}
1182+
1183+
return {
1184+
"message": "Example requests for /api/tasks endpoint",
1185+
"examples": examples,
1186+
"usage": "POST /api/tasks with any of the example payloads to see locale-specific date formatting"
1187+
}
1188+
1189+
9731190
# Run the app
9741191
if __name__ == "__main__":
9751192
import uvicorn

src/backend/kernel_agents/agent_base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,12 @@ def default_system_message(agent_name=None) -> str:
8686
name = agent_name
8787
return f"You are an AI assistant named {name}. Help the user by providing accurate and helpful information."
8888

89-
async def handle_action_request(self, action_request: ActionRequest) -> str:
89+
async def handle_action_request(self, action_request: ActionRequest, **kwargs) -> str:
9090
"""Handle an action request from another agent or the system.
9191
9292
Args:
93-
action_request_json: The action request as a JSON string
93+
action_request: The action request object
94+
**kwargs: Additional keyword arguments (e.g., user_locale)
9495
9596
Returns:
9697
A JSON string containing the action response

src/backend/kernel_agents/agent_factory.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
from kernel_agents.product_agent import ProductAgent
2222
from kernel_agents.tech_support_agent import TechSupportAgent
2323
from models.messages_kernel import AgentType, PlannerResponsePlan
24+
# Import all tool classes to generate agent_tools_list
25+
from kernel_tools.hr_tools import HrTools
26+
from kernel_tools.marketing_tools import MarketingTools
27+
from kernel_tools.product_tools import ProductTools
28+
from kernel_tools.procurement_tools import ProcurementTools
29+
from kernel_tools.tech_support_tools import TechSupportTools
30+
from kernel_tools.generic_tools import GenericTools
2431
# pylint:disable=E0611
2532
from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent
2633

@@ -190,6 +197,7 @@ async def create_all_agents(
190197
temperature: float = 0.0,
191198
memory_store: Optional[CosmosMemoryContext] = None,
192199
client: Optional[Any] = None,
200+
user_locale: str = "en_GB", # ✅ Add this
193201
) -> Dict[AgentType, BaseAgent]:
194202
"""Create all agent types for a session in a specific order.
195203
@@ -279,13 +287,18 @@ async def create_all_agents(
279287
agents[planner_agent_type] = planner_agent
280288

281289
# Phase 3: Create group chat manager with all agents including the planner
290+
# Generate the agent tools list for the GroupChatManager
291+
agent_tools_list = cls._generate_agent_tools_list()
292+
282293
group_chat_manager = await cls.create_agent(
283294
agent_type=AgentType.GROUP_CHAT_MANAGER,
284295
session_id=session_id,
285296
user_id=user_id,
286297
temperature=temperature,
287298
client=client,
288299
agent_instances=agent_instances, # Pass agent instances to the planner
300+
agent_tools_list=agent_tools_list, # ✅ Add this
301+
user_locale=user_locale, # ✅ Add this
289302
)
290303
agents[group_chat_manager_type] = group_chat_manager
291304

@@ -327,3 +340,34 @@ def clear_cache(cls, session_id: Optional[str] = None) -> None:
327340
cls._agent_cache.clear()
328341
cls._azure_ai_agent_cache.clear()
329342
logger.info("Cleared all agent caches")
343+
344+
@classmethod
345+
def _generate_agent_tools_list(cls) -> list[str]:
346+
"""Generate a list of all available tool names across all agents.
347+
348+
Returns:
349+
List of tool names that can be used by agents
350+
"""
351+
tool_classes = [
352+
HrTools,
353+
MarketingTools,
354+
ProductTools,
355+
ProcurementTools,
356+
TechSupportTools,
357+
GenericTools,
358+
]
359+
360+
all_tools = []
361+
for tool_class in tool_classes:
362+
# Get all methods from the tool class
363+
for name in dir(tool_class):
364+
# Skip private methods and special methods
365+
if not name.startswith("_") and name != "generate_tools_json_doc":
366+
# Check if it's a callable method
367+
method = getattr(tool_class, name)
368+
if callable(method):
369+
all_tools.append(f"{tool_class.__name__}.{name}")
370+
371+
return all_tools
372+
373+

0 commit comments

Comments
 (0)