1515from openviking .server .identity import AuthMode , RequestContext
1616from openviking .server .models import ErrorInfo , Response
1717from openviking .server .responses import error_response
18+ from openviking .server .telemetry import run_operation
19+ from openviking .telemetry import TelemetryRequest
1820
1921router = APIRouter (prefix = "/api/v1/sessions" , tags = ["sessions" ])
2022logger = logging .getLogger (__name__ )
@@ -67,6 +69,7 @@ class AddMessageRequest(BaseModel):
6769 content : Optional [str ] = None
6870 parts : Optional [List [Dict [str , Any ]]] = None
6971 created_at : Optional [str ] = None
72+ telemetry : TelemetryRequest = False
7073
7174 @model_validator (mode = "after" )
7275 def validate_content_or_parts (self ) -> "AddMessageRequest" :
@@ -86,6 +89,7 @@ class CreateSessionRequest(BaseModel):
8689 """Request model for creating a session."""
8790
8891 session_id : Optional [str ] = None
92+ telemetry : TelemetryRequest = False
8993
9094
9195def _to_jsonable (value : Any ) -> Any :
@@ -109,7 +113,7 @@ def _request_auth_mode(request: Request) -> AuthMode:
109113
110114@router .post ("" )
111115async def create_session (
112- request : Optional [ CreateSessionRequest ] = None ,
116+ request : CreateSessionRequest = Body ( default_factory = CreateSessionRequest ) ,
113117 _ctx : RequestContext = Depends (get_request_context ),
114118):
115119 """Create a new session.
@@ -118,17 +122,22 @@ async def create_session(
118122 If session_id is None, creates a new session with auto-generated ID.
119123 """
120124 service = get_service ()
121- await service .initialize_user_directories (_ctx )
122- await service .initialize_agent_directories (_ctx )
123- session_id = request .session_id if request else None
124- session = await service .sessions .create (_ctx , session_id )
125- return Response (
126- status = "ok" ,
127- result = {
125+
126+ async def _create () -> dict [str , Any ]:
127+ await service .initialize_user_directories (_ctx )
128+ await service .initialize_agent_directories (_ctx )
129+ session = await service .sessions .create (_ctx , request .session_id )
130+ return {
128131 "session_id" : session .session_id ,
129132 "user" : session .user .to_dict (),
130- },
133+ }
134+
135+ execution = await run_operation (
136+ operation = "session.create" ,
137+ telemetry = request .telemetry ,
138+ fn = _create ,
131139 )
140+ return Response (status = "ok" , result = execution .result , telemetry = execution .telemetry )
132141
133142
134143@router .get ("" )
@@ -237,6 +246,7 @@ class CommitRequest(BaseModel):
237246 "(default 10); compact path passes 0 to archive everything."
238247 ),
239248 )
249+ telemetry : TelemetryRequest = False
240250
241251
242252@router .post ("/{session_id}/commit" )
@@ -252,10 +262,18 @@ async def commit_session(
252262 polling progress via ``GET /tasks/{task_id}``.
253263 """
254264 service = get_service ()
255- result = await service .sessions .commit_async (
256- session_id , _ctx , keep_recent_count = body .keep_recent_count
265+ execution = await run_operation (
266+ operation = "session.commit" ,
267+ telemetry = body .telemetry ,
268+ fn = lambda : service .sessions .commit_async (
269+ session_id , _ctx , keep_recent_count = body .keep_recent_count
270+ ),
257271 )
258- return Response (status = "ok" , result = result ).model_dump (exclude_none = True )
272+ return Response (
273+ status = "ok" ,
274+ result = execution .result ,
275+ telemetry = execution .telemetry ,
276+ ).model_dump (exclude_none = True )
259277
260278
261279@router .post ("/{session_id}/extract" )
@@ -291,42 +309,47 @@ async def add_message(
291309 Missing sessions are auto-created on first add.
292310 """
293311 service = get_service ()
294- session = await service .sessions .get (session_id , _ctx , auto_create = True )
295- role_id = _ctx .resolve_role_id (request .role , request .role_id )
296-
297- if request .parts is not None :
298- # Resolve path variables in URIs within parts
299- resolved_parts = []
300- for p in request .parts :
301- part_copy = dict (p )
302- # Resolve uri in context parts
303- if part_copy .get ("type" ) == "context" and "uri" in part_copy :
304- part_copy ["uri" ] = resolve_path_variables (part_copy ["uri" ])
305- # Resolve tool_uri and skill_uri in tool parts
306- if part_copy .get ("type" ) == "tool" :
307- if "tool_uri" in part_copy :
308- part_copy ["tool_uri" ] = resolve_path_variables (part_copy ["tool_uri" ])
309- if "skill_uri" in part_copy :
310- part_copy ["skill_uri" ] = resolve_path_variables (part_copy ["skill_uri" ])
311- resolved_parts .append (part_copy )
312- parts = [part_from_dict (p ) for p in resolved_parts ]
313- else :
314- parts = [TextPart (text = request .content or "" )]
315-
316- # created_at 直接传递给 session (ISO string)
317- session .add_message (
318- request .role ,
319- parts ,
320- role_id = role_id ,
321- created_at = request .created_at ,
322- )
323- return Response (
324- status = "ok" ,
325- result = {
312+
313+ async def _add () -> dict [str , Any ]:
314+ session = await service .sessions .get (session_id , _ctx , auto_create = True )
315+ role_id = _ctx .resolve_role_id (request .role , request .role_id )
316+
317+ if request .parts is not None :
318+ # Resolve path variables in URIs within parts
319+ resolved_parts = []
320+ for p in request .parts :
321+ part_copy = dict (p )
322+ # Resolve uri in context parts
323+ if part_copy .get ("type" ) == "context" and "uri" in part_copy :
324+ part_copy ["uri" ] = resolve_path_variables (part_copy ["uri" ])
325+ # Resolve tool_uri and skill_uri in tool parts
326+ if part_copy .get ("type" ) == "tool" :
327+ if "tool_uri" in part_copy :
328+ part_copy ["tool_uri" ] = resolve_path_variables (part_copy ["tool_uri" ])
329+ if "skill_uri" in part_copy :
330+ part_copy ["skill_uri" ] = resolve_path_variables (part_copy ["skill_uri" ])
331+ resolved_parts .append (part_copy )
332+ parts = [part_from_dict (p ) for p in resolved_parts ]
333+ else :
334+ parts = [TextPart (text = request .content or "" )]
335+
336+ session .add_message (
337+ request .role ,
338+ parts ,
339+ role_id = role_id ,
340+ created_at = request .created_at ,
341+ )
342+ return {
326343 "session_id" : session_id ,
327344 "message_count" : len (session .messages ),
328- },
345+ }
346+
347+ execution = await run_operation (
348+ operation = "session.add_message" ,
349+ telemetry = request .telemetry ,
350+ fn = _add ,
329351 )
352+ return Response (status = "ok" , result = execution .result , telemetry = execution .telemetry )
330353
331354
332355@router .post ("/{session_id}/used" )
0 commit comments