@@ -27,6 +27,7 @@ using json = nlohmann::json;
2727// Forward declarations
2828class Session ;
2929struct SessionEvent ;
30+ using EventHandler = std::function<void (const SessionEvent&)>;
3031
3132// =============================================================================
3233// Protocol Version
@@ -380,6 +381,258 @@ struct UserInputInvocation
380381// / Handler for user input requests from the agent
381382using UserInputHandler = std::function<UserInputResponse(const UserInputRequest&, const UserInputInvocation&)>;
382383
384+ // =============================================================================
385+ // Elicitation Types
386+ // =============================================================================
387+
388+ // / Elicitation display mode
389+ enum class ElicitationRequestedMode
390+ {
391+ Form,
392+ Url
393+ };
394+
395+ NLOHMANN_JSON_SERIALIZE_ENUM (
396+ ElicitationRequestedMode,
397+ {
398+ {ElicitationRequestedMode::Form, " form" },
399+ {ElicitationRequestedMode::Url, " url" },
400+ }
401+ )
402+
403+ // / JSON Schema for elicitation form fields
404+ struct ElicitationSchema
405+ {
406+ std::string type = " object" ;
407+ std::optional<std::map<std::string, json>> properties;
408+ std::optional<std::vector<std::string>> required;
409+ };
410+
411+ inline void to_json (json& j, const ElicitationSchema& s)
412+ {
413+ j = json{{" type" , s.type }};
414+ if (s.properties )
415+ j[" properties" ] = *s.properties ;
416+ if (s.required )
417+ j[" required" ] = *s.required ;
418+ }
419+
420+ inline void from_json (const json& j, ElicitationSchema& s)
421+ {
422+ if (j.contains (" type" ))
423+ j.at (" type" ).get_to (s.type );
424+ if (j.contains (" properties" ))
425+ s.properties = j.at (" properties" ).get <std::map<std::string, json>>();
426+ if (j.contains (" required" ))
427+ s.required = j.at (" required" ).get <std::vector<std::string>>();
428+ }
429+
430+ // / User action for elicitation response
431+ enum class ElicitationAction
432+ {
433+ Accept,
434+ Decline,
435+ Cancel
436+ };
437+
438+ NLOHMANN_JSON_SERIALIZE_ENUM (
439+ ElicitationAction,
440+ {
441+ {ElicitationAction::Accept, " accept" },
442+ {ElicitationAction::Decline, " decline" },
443+ {ElicitationAction::Cancel, " cancel" },
444+ }
445+ )
446+
447+ // / Context for an elicitation request from the server
448+ struct ElicitationContext
449+ {
450+ std::string session_id;
451+ std::string message;
452+ std::optional<ElicitationSchema> requested_schema;
453+ std::optional<ElicitationRequestedMode> mode;
454+ std::optional<std::string> elicitation_source;
455+ std::optional<std::string> url;
456+ };
457+
458+ inline void from_json (const json& j, ElicitationContext& c)
459+ {
460+ if (j.contains (" sessionId" ))
461+ j.at (" sessionId" ).get_to (c.session_id );
462+ j.at (" message" ).get_to (c.message );
463+ if (j.contains (" requestedSchema" ) && !j[" requestedSchema" ].is_null ())
464+ c.requested_schema = j.at (" requestedSchema" ).get <ElicitationSchema>();
465+ if (j.contains (" mode" ) && !j[" mode" ].is_null ())
466+ c.mode = j.at (" mode" ).get <ElicitationRequestedMode>();
467+ if (j.contains (" elicitationSource" ) && !j[" elicitationSource" ].is_null ())
468+ c.elicitation_source = j.at (" elicitationSource" ).get <std::string>();
469+ if (j.contains (" url" ) && !j[" url" ].is_null ())
470+ c.url = j.at (" url" ).get <std::string>();
471+ }
472+
473+ inline void to_json (json& j, const ElicitationContext& c)
474+ {
475+ j = json{{" message" , c.message }};
476+ if (!c.session_id .empty ())
477+ j[" sessionId" ] = c.session_id ;
478+ if (c.requested_schema )
479+ j[" requestedSchema" ] = *c.requested_schema ;
480+ if (c.mode )
481+ j[" mode" ] = *c.mode ;
482+ if (c.elicitation_source )
483+ j[" elicitationSource" ] = *c.elicitation_source ;
484+ if (c.url )
485+ j[" url" ] = *c.url ;
486+ }
487+
488+ // / Result returned from an elicitation dialog
489+ struct ElicitationResult
490+ {
491+ ElicitationAction action = ElicitationAction::Cancel;
492+ std::optional<std::map<std::string, json>> content;
493+ };
494+
495+ inline void to_json (json& j, const ElicitationResult& r)
496+ {
497+ j = json{{" action" , r.action }};
498+ if (r.content )
499+ j[" content" ] = *r.content ;
500+ }
501+
502+ inline void from_json (const json& j, ElicitationResult& r)
503+ {
504+ j.at (" action" ).get_to (r.action );
505+ if (j.contains (" content" ) && !j[" content" ].is_null ())
506+ r.content = j.at (" content" ).get <std::map<std::string, json>>();
507+ }
508+
509+ // / Elicitation handler function type
510+ using ElicitationHandler = std::function<ElicitationResult(const ElicitationContext&)>;
511+
512+ // =============================================================================
513+ // Exit Plan Mode Types
514+ // =============================================================================
515+
516+ // / Request to exit plan mode
517+ struct ExitPlanModeRequest
518+ {
519+ std::string summary;
520+ std::optional<std::string> plan_content;
521+ std::vector<std::string> actions;
522+ std::string recommended_action = " autopilot" ;
523+ };
524+
525+ inline void from_json (const json& j, ExitPlanModeRequest& r)
526+ {
527+ j.at (" summary" ).get_to (r.summary );
528+ if (j.contains (" planContent" ) && !j[" planContent" ].is_null ())
529+ r.plan_content = j.at (" planContent" ).get <std::string>();
530+ if (j.contains (" actions" ))
531+ r.actions = j.at (" actions" ).get <std::vector<std::string>>();
532+ if (j.contains (" recommendedAction" ))
533+ j.at (" recommendedAction" ).get_to (r.recommended_action );
534+ }
535+
536+ inline void to_json (json& j, const ExitPlanModeRequest& r)
537+ {
538+ j = json{{" summary" , r.summary }, {" recommendedAction" , r.recommended_action }};
539+ if (r.plan_content )
540+ j[" planContent" ] = *r.plan_content ;
541+ if (!r.actions .empty ())
542+ j[" actions" ] = r.actions ;
543+ }
544+
545+ // / Response to an exit-plan-mode request
546+ struct ExitPlanModeResult
547+ {
548+ bool approved = true ;
549+ std::optional<std::string> selected_action;
550+ std::optional<std::string> feedback;
551+ };
552+
553+ inline void to_json (json& j, const ExitPlanModeResult& r)
554+ {
555+ j = json{{" approved" , r.approved }};
556+ if (r.selected_action )
557+ j[" selectedAction" ] = *r.selected_action ;
558+ if (r.feedback )
559+ j[" feedback" ] = *r.feedback ;
560+ }
561+
562+ inline void from_json (const json& j, ExitPlanModeResult& r)
563+ {
564+ j.at (" approved" ).get_to (r.approved );
565+ if (j.contains (" selectedAction" ) && !j[" selectedAction" ].is_null ())
566+ r.selected_action = j.at (" selectedAction" ).get <std::string>();
567+ if (j.contains (" feedback" ) && !j[" feedback" ].is_null ())
568+ r.feedback = j.at (" feedback" ).get <std::string>();
569+ }
570+
571+ // / Context for exit-plan-mode invocation
572+ struct ExitPlanModeInvocation
573+ {
574+ std::string session_id;
575+ };
576+
577+ // / Exit plan mode handler function type
578+ using ExitPlanModeHandler =
579+ std::function<ExitPlanModeResult(const ExitPlanModeRequest&, const ExitPlanModeInvocation&)>;
580+
581+ // =============================================================================
582+ // Auto Mode Switch Types
583+ // =============================================================================
584+
585+ // / Request to switch to auto mode after a rate limit
586+ struct AutoModeSwitchRequest
587+ {
588+ std::optional<std::string> error_code;
589+ std::optional<double > retry_after_seconds;
590+ };
591+
592+ inline void from_json (const json& j, AutoModeSwitchRequest& r)
593+ {
594+ if (j.contains (" errorCode" ) && !j[" errorCode" ].is_null ())
595+ r.error_code = j.at (" errorCode" ).get <std::string>();
596+ if (j.contains (" retryAfterSeconds" ) && !j[" retryAfterSeconds" ].is_null ())
597+ r.retry_after_seconds = j.at (" retryAfterSeconds" ).get <double >();
598+ }
599+
600+ inline void to_json (json& j, const AutoModeSwitchRequest& r)
601+ {
602+ j = json::object ();
603+ if (r.error_code )
604+ j[" errorCode" ] = *r.error_code ;
605+ if (r.retry_after_seconds )
606+ j[" retryAfterSeconds" ] = *r.retry_after_seconds ;
607+ }
608+
609+ // / Response to auto-mode-switch request
610+ enum class AutoModeSwitchResponse
611+ {
612+ Yes,
613+ YesAlways,
614+ No
615+ };
616+
617+ NLOHMANN_JSON_SERIALIZE_ENUM (
618+ AutoModeSwitchResponse,
619+ {
620+ {AutoModeSwitchResponse::Yes, " yes" },
621+ {AutoModeSwitchResponse::YesAlways, " yes_always" },
622+ {AutoModeSwitchResponse::No, " no" },
623+ }
624+ )
625+
626+ // / Context for auto-mode-switch invocation
627+ struct AutoModeSwitchInvocation
628+ {
629+ std::string session_id;
630+ };
631+
632+ // / Auto mode switch handler function type
633+ using AutoModeSwitchHandler =
634+ std::function<AutoModeSwitchResponse(const AutoModeSwitchRequest&, const AutoModeSwitchInvocation&)>;
635+
383636// =============================================================================
384637// Hook Handler Types
385638// =============================================================================
@@ -1150,6 +1403,18 @@ struct SessionConfig
11501403 // / Handler for user input requests from the agent (enables ask_user tool).
11511404 std::optional<UserInputHandler> on_user_input_request;
11521405
1406+ // / Handler for elicitation requests from the server.
1407+ std::optional<ElicitationHandler> on_elicitation_request;
1408+
1409+ // / Handler for exit-plan-mode requests from the agent.
1410+ std::optional<ExitPlanModeHandler> on_exit_plan_mode;
1411+
1412+ // / Handler for auto-mode-switch requests.
1413+ std::optional<AutoModeSwitchHandler> on_auto_mode_switch;
1414+
1415+ // / Pre-registered event handler - wired up when session is created.
1416+ std::optional<EventHandler> on_event;
1417+
11531418 // / Hook handlers for session lifecycle events.
11541419 std::optional<SessionHooks> hooks;
11551420
@@ -1237,6 +1502,18 @@ struct ResumeSessionConfig
12371502 // / Handler for user input requests from the agent (enables ask_user tool).
12381503 std::optional<UserInputHandler> on_user_input_request;
12391504
1505+ // / Handler for elicitation requests from the server.
1506+ std::optional<ElicitationHandler> on_elicitation_request;
1507+
1508+ // / Handler for exit-plan-mode requests from the agent.
1509+ std::optional<ExitPlanModeHandler> on_exit_plan_mode;
1510+
1511+ // / Handler for auto-mode-switch requests.
1512+ std::optional<AutoModeSwitchHandler> on_auto_mode_switch;
1513+
1514+ // / Pre-registered event handler - wired up when session is created.
1515+ std::optional<EventHandler> on_event;
1516+
12401517 // / Hook handlers for session lifecycle events.
12411518 std::optional<SessionHooks> hooks;
12421519
0 commit comments