Convert all Chinese comments, docstrings, logger/print output, HTTPException detail messages, and API response messages to English across the entire codebase. Functional zh/ja localized strings (e.g. prompt templates, timezone display names, date formats) are preserved as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
168 lines
5.4 KiB
Python
168 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
PrePrompt Hook - User context loader
|
|
|
|
Executed when system_prompt is loaded, queries user-related information
|
|
via MCP service and injects it into the prompt.
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
import anyio
|
|
from mcp.client.session import ClientSession
|
|
from mcp.client.streamable_http import streamablehttp_client
|
|
|
|
# MCP service configuration
|
|
MCP_BASE_URL = "http://prd-mcp.gbase.ai/mcp/iot/sse"
|
|
MCP_TIMEOUT = 30
|
|
|
|
|
|
async def get_employee_location(user_identifier: str, bot_id: str) -> dict | None:
|
|
"""
|
|
Query employee location information via MCP service.
|
|
|
|
Args:
|
|
user_identifier: User identifier (employee name or email)
|
|
bot_id: Bot ID (currently unused, reserved for future extension)
|
|
|
|
Returns:
|
|
Employee location info dict, or None if the query fails
|
|
"""
|
|
try:
|
|
async with streamablehttp_client(
|
|
url=MCP_BASE_URL,
|
|
timeout=MCP_TIMEOUT,
|
|
terminate_on_close=False,
|
|
) as (read_stream, write_stream, _):
|
|
async with ClientSession(read_stream, write_stream) as session:
|
|
# Initialize MCP session
|
|
await session.initialize()
|
|
|
|
# Call the find_employee_location tool
|
|
result = await session.call_tool(
|
|
name="find_employee_location",
|
|
arguments={"name": user_identifier}
|
|
)
|
|
|
|
# Parse the returned result
|
|
if result.content:
|
|
for item in result.content:
|
|
if hasattr(item, 'text') and item.text:
|
|
try:
|
|
return json.loads(item.text)
|
|
except json.JSONDecodeError:
|
|
# If not JSON, return the text directly
|
|
return {"data": item.text}
|
|
|
|
return None
|
|
|
|
except Exception:
|
|
# Return None on error so as not to affect the main flow
|
|
return None
|
|
|
|
|
|
def format_location_context(location_data: dict | None, user_identifier: str, bot_id: str) -> str:
|
|
"""
|
|
Format location information as Markdown context (Japanese).
|
|
|
|
Args:
|
|
location_data: Location data returned from MCP query
|
|
user_identifier: User identifier (unused)
|
|
bot_id: Bot ID (unused)
|
|
|
|
Returns:
|
|
Formatted Markdown string, or empty string on error or no data
|
|
"""
|
|
# Return empty string on error or no data
|
|
if not location_data:
|
|
return ""
|
|
|
|
matched_count = location_data.get('matched_count', 0)
|
|
results = location_data.get('results', [])
|
|
|
|
# Return empty string when no matches
|
|
if matched_count == 0:
|
|
return ""
|
|
|
|
lines = []
|
|
|
|
# Add note: this is information about the current user (USER_IDENTIFIER)
|
|
lines.append(f"**Current User ({user_identifier}) Information**:")
|
|
lines.append("")
|
|
|
|
for idx, employee in enumerate(results, 1):
|
|
name = employee.get('name', 'Unknown')
|
|
sensor_id = employee.get('sensor_id', '')
|
|
confidence = employee.get('confidence', 0)
|
|
|
|
lines.append(f"- Name: {name}")
|
|
lines.append(f"- Sensor ID: {sensor_id}")
|
|
|
|
location_status = employee.get('location_status', '')
|
|
|
|
if location_status == 'success':
|
|
coordinates = employee.get('coordinates', {})
|
|
location = employee.get('location', {})
|
|
|
|
lines.append(f"- Location Status: Success")
|
|
lines.append(f"- Floor: {coordinates.get('floor', 'N/A')}")
|
|
lines.append(f"- Coordinates: ({coordinates.get('x', 0):.2f}, {coordinates.get('y', 0):.2f}, {coordinates.get('z', 0):.2f})")
|
|
|
|
if location:
|
|
building = location.get('building', '')
|
|
area = location.get('area', '')
|
|
room = location.get('room', '')
|
|
lines.append(f"- Detailed Location: {building} / {area} / {room}")
|
|
|
|
measurement_time = employee.get('measurement_time')
|
|
if measurement_time:
|
|
lines.append(f"- Measurement Time: {measurement_time}")
|
|
|
|
elif location_status == 'not_in_range':
|
|
lines.append(f"- Location Status: Out of Range")
|
|
error_message = employee.get('error_message', '')
|
|
if error_message:
|
|
lines.append(f"- Note: {error_message}")
|
|
|
|
else: # error
|
|
lines.append(f"- Location Status: Failed")
|
|
error_message = employee.get('error_message', 'Unknown Error')
|
|
lines.append(f"- Error: {error_message}")
|
|
|
|
lines.append("")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
async def async_main():
|
|
"""Async main function."""
|
|
user_identifier = os.environ.get('USER_IDENTIFIER', '')
|
|
bot_id = os.environ.get('BOT_ID', '')
|
|
|
|
if not user_identifier:
|
|
return 0
|
|
|
|
# Query employee location information
|
|
location_data = await get_employee_location(user_identifier, bot_id)
|
|
|
|
# Format and output context (returns empty string on error or no data)
|
|
context_info = format_location_context(location_data, user_identifier, bot_id)
|
|
if context_info:
|
|
print(context_info)
|
|
|
|
return 0
|
|
|
|
|
|
def main():
|
|
"""Read parameters from environment variables and query user context via MCP service."""
|
|
try:
|
|
return anyio.run(async_main)
|
|
except Exception:
|
|
# Return empty string on error (output nothing)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|