@@ -402,162 +402,6 @@ impl OtelExporterType {
402402 }
403403}
404404
405- /// A named session capability sent in the `session.create` and
406- /// `session.resume` wire payloads.
407- ///
408- /// Capabilities gate optional CLI features (extra tools, system-prompt
409- /// sections, host-rendered surfaces). The runtime starts from a
410- /// hard-coded `SDK_CAPABILITIES` set; use
411- /// [`SessionConfig::with_enable_capability`] /
412- /// [`SessionConfig::with_disable_capability`] (and their plural
413- /// counterparts) to opt individual sessions in or out.
414- ///
415- /// > **Not** the same as [`SessionCapabilities`] — that struct is the
416- /// > *runtime-negotiated* capability descriptor reported by the CLI on
417- /// > `session.create`. [`SessionCapability`] is the *opt-in / opt-out
418- /// > toggle name* sent with each `session.create` / `session.resume`.
419- /// >
420- /// > This public type is also separate from the generated protocol enum:
421- /// > unknown generated enum values collapse to `Unknown`, while callers
422- /// > need [`Other`](Self::Other) to preserve and send capability names
423- /// > introduced by newer runtimes.
424- ///
425- /// The runtime's overlap semantics are **disable-wins**: if a capability
426- /// appears in both the enabled and disabled lists, the disable wins.
427- /// The SDK preserves the order callers add capabilities in so the
428- /// resulting wire payload is deterministic.
429- ///
430- /// The enum is `#[non_exhaustive]` and carries an [`Other`](Self::Other)
431- /// variant so forward-compat capabilities the runtime grows ahead of an
432- /// SDK release can still be opted into without waiting for a new
433- /// enum variant.
434- ///
435- /// Requires runtime support for per-session capability controls.
436- #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
437- #[ non_exhaustive]
438- pub enum SessionCapability {
439- /// TUI-only prompt hints (keyboard shortcuts).
440- TuiHints ,
441- /// `[[PLAN]]` handling and plan-mode instructions.
442- PlanMode ,
443- /// `store_memory` tool and the `<memories>` system-prompt section.
444- Memory ,
445- /// `fetch_copilot_cli_documentation` tool plus the
446- /// `<self_documentation>` system-prompt section.
447- CliDocumentation ,
448- /// `ask_user` tool for interactive clarification.
449- AskUser ,
450- /// Interactive-CLI identity (vs non-interactive / headless).
451- InteractiveMode ,
452- /// Automatic system notifications to the agent (batched, hidden
453- /// from the user timeline).
454- SystemNotifications ,
455- /// Elicitation support (confirm / select / input prompts).
456- Elicitation ,
457- /// Cross-session history tools and session-store prompt/tool metadata.
458- SessionStore ,
459- /// MCP-Apps (SEP-1865) `ui://` resource passthrough.
460- McpApps ,
461- /// Extension-provided canvases rendered by the host.
462- CanvasRenderer ,
463- /// A capability name the SDK doesn't have a typed variant for yet.
464- ///
465- /// Pass any kebab-case capability string here to forward it
466- /// verbatim to the runtime.
467- Other ( String ) ,
468- }
469-
470- impl SessionCapability {
471- /// The kebab-case wire string sent in `enabledCapabilities` /
472- /// `disabledCapabilities` on `session.create` and `session.resume`.
473- pub fn as_str ( & self ) -> & str {
474- match self {
475- Self :: TuiHints => "tui-hints" ,
476- Self :: PlanMode => "plan-mode" ,
477- Self :: Memory => "memory" ,
478- Self :: CliDocumentation => "cli-documentation" ,
479- Self :: AskUser => "ask-user" ,
480- Self :: InteractiveMode => "interactive-mode" ,
481- Self :: SystemNotifications => "system-notifications" ,
482- Self :: Elicitation => "elicitation" ,
483- Self :: SessionStore => "session-store" ,
484- Self :: McpApps => "mcp-apps" ,
485- Self :: CanvasRenderer => "canvas-renderer" ,
486- Self :: Other ( name) => name. as_str ( ) ,
487- }
488- }
489-
490- fn from_known_name ( name : & str ) -> Option < Self > {
491- Some ( match name {
492- "tui-hints" => Self :: TuiHints ,
493- "plan-mode" => Self :: PlanMode ,
494- "memory" => Self :: Memory ,
495- "cli-documentation" => Self :: CliDocumentation ,
496- "ask-user" => Self :: AskUser ,
497- "interactive-mode" => Self :: InteractiveMode ,
498- "system-notifications" => Self :: SystemNotifications ,
499- "elicitation" => Self :: Elicitation ,
500- "session-store" => Self :: SessionStore ,
501- "mcp-apps" => Self :: McpApps ,
502- "canvas-renderer" => Self :: CanvasRenderer ,
503- _ => return None ,
504- } )
505- }
506- }
507-
508- impl std:: fmt:: Display for SessionCapability {
509- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
510- f. write_str ( self . as_str ( ) )
511- }
512- }
513-
514- impl std:: str:: FromStr for SessionCapability {
515- type Err = std:: convert:: Infallible ;
516-
517- /// Parse a kebab-case capability name. Unknown names round-trip
518- /// through [`SessionCapability::Other`] so old SDK builds stay
519- /// useful against CLIs that add new capabilities. Always returns
520- /// `Ok` — the error type is [`Infallible`](std::convert::Infallible).
521- fn from_str ( s : & str ) -> std:: result:: Result < Self , std:: convert:: Infallible > {
522- Ok ( Self :: from ( s) )
523- }
524- }
525-
526- impl From < & str > for SessionCapability {
527- fn from ( s : & str ) -> Self {
528- Self :: from_known_name ( s) . unwrap_or_else ( || Self :: Other ( s. to_owned ( ) ) )
529- }
530- }
531-
532- impl From < String > for SessionCapability {
533- fn from ( s : String ) -> Self {
534- if let Some ( capability) = Self :: from_known_name ( & s) {
535- capability
536- } else {
537- Self :: Other ( s)
538- }
539- }
540- }
541-
542- impl Serialize for SessionCapability {
543- fn serialize < S > ( & self , serializer : S ) -> std:: result:: Result < S :: Ok , S :: Error >
544- where
545- S : serde:: Serializer ,
546- {
547- serializer. serialize_str ( self . as_str ( ) )
548- }
549- }
550-
551- impl < ' de > Deserialize < ' de > for SessionCapability {
552- fn deserialize < D > ( deserializer : D ) -> std:: result:: Result < Self , D :: Error >
553- where
554- D : serde:: Deserializer < ' de > ,
555- {
556- let capability = String :: deserialize ( deserializer) ?;
557- Ok ( Self :: from ( capability) )
558- }
559- }
560-
561405/// OpenTelemetry configuration forwarded to the spawned GitHub Copilot CLI
562406/// process.
563407///
@@ -2535,106 +2379,6 @@ mod tests {
25352379 assert_eq ! ( Client :: remote_args( & opts) , vec![ "--remote" . to_string( ) ] ) ;
25362380 }
25372381
2538- #[ test]
2539- fn session_capability_round_trips_via_str ( ) {
2540- for cap in [
2541- SessionCapability :: TuiHints ,
2542- SessionCapability :: PlanMode ,
2543- SessionCapability :: Memory ,
2544- SessionCapability :: CliDocumentation ,
2545- SessionCapability :: AskUser ,
2546- SessionCapability :: InteractiveMode ,
2547- SessionCapability :: SystemNotifications ,
2548- SessionCapability :: Elicitation ,
2549- SessionCapability :: SessionStore ,
2550- SessionCapability :: McpApps ,
2551- SessionCapability :: CanvasRenderer ,
2552- ] {
2553- let s = cap. to_string ( ) ;
2554- let parsed: SessionCapability = s. parse ( ) . unwrap ( ) ;
2555- assert_eq ! ( parsed, cap, "round-trip failed for {s}" ) ;
2556- }
2557- }
2558-
2559- #[ test]
2560- fn session_capability_from_str_falls_back_to_other_for_unknown_names ( ) {
2561- let parsed: SessionCapability = "brand-new-cap" . parse ( ) . unwrap ( ) ;
2562- assert_eq ! (
2563- parsed,
2564- SessionCapability :: Other ( "brand-new-cap" . to_string( ) )
2565- ) ;
2566- assert_eq ! ( parsed. as_str( ) , "brand-new-cap" ) ;
2567- }
2568-
2569- #[ test]
2570- fn session_capability_into_from_str_and_string ( ) {
2571- let from_str: SessionCapability = "memory" . into ( ) ;
2572- let from_string: SessionCapability = "memory" . to_string ( ) . into ( ) ;
2573- assert_eq ! ( from_str, SessionCapability :: Memory ) ;
2574- assert_eq ! ( from_string, SessionCapability :: Memory ) ;
2575- // Unknown names go to Other
2576- let other: SessionCapability = "future-cap" . into ( ) ;
2577- assert_eq ! ( other, SessionCapability :: Other ( "future-cap" . to_string( ) ) ) ;
2578- }
2579-
2580- #[ test]
2581- fn session_capability_serializes_as_wire_string ( ) {
2582- assert_eq ! (
2583- serde_json:: to_value( SessionCapability :: Memory ) . unwrap( ) ,
2584- serde_json:: json!( "memory" )
2585- ) ;
2586- assert_eq ! (
2587- serde_json:: to_value( SessionCapability :: Other ( "future-cap" . to_string( ) ) ) . unwrap( ) ,
2588- serde_json:: json!( "future-cap" )
2589- ) ;
2590- }
2591-
2592- #[ test]
2593- fn session_capability_deserializes_unknown_as_other ( ) {
2594- let parsed: SessionCapability =
2595- serde_json:: from_value ( serde_json:: json!( "future-cap" ) ) . unwrap ( ) ;
2596- assert_eq ! ( parsed, SessionCapability :: Other ( "future-cap" . to_string( ) ) ) ;
2597- }
2598-
2599- #[ test]
2600- fn generated_session_capabilities_have_public_variants ( ) {
2601- use crate :: generated:: api_types:: SessionCapability as GeneratedSessionCapability ;
2602-
2603- fn expected_wire_name ( capability : GeneratedSessionCapability ) -> Option < & ' static str > {
2604- match capability {
2605- GeneratedSessionCapability :: TuiHints => Some ( "tui-hints" ) ,
2606- GeneratedSessionCapability :: PlanMode => Some ( "plan-mode" ) ,
2607- GeneratedSessionCapability :: Memory => Some ( "memory" ) ,
2608- GeneratedSessionCapability :: CliDocumentation => Some ( "cli-documentation" ) ,
2609- GeneratedSessionCapability :: AskUser => Some ( "ask-user" ) ,
2610- GeneratedSessionCapability :: InteractiveMode => Some ( "interactive-mode" ) ,
2611- GeneratedSessionCapability :: SystemNotifications => Some ( "system-notifications" ) ,
2612- GeneratedSessionCapability :: Elicitation => Some ( "elicitation" ) ,
2613- GeneratedSessionCapability :: SessionStore => Some ( "session-store" ) ,
2614- GeneratedSessionCapability :: McpApps => Some ( "mcp-apps" ) ,
2615- GeneratedSessionCapability :: CanvasRenderer => Some ( "canvas-renderer" ) ,
2616- GeneratedSessionCapability :: Unknown => None ,
2617- }
2618- }
2619-
2620- for generated in [
2621- GeneratedSessionCapability :: TuiHints ,
2622- GeneratedSessionCapability :: PlanMode ,
2623- GeneratedSessionCapability :: Memory ,
2624- GeneratedSessionCapability :: CliDocumentation ,
2625- GeneratedSessionCapability :: AskUser ,
2626- GeneratedSessionCapability :: InteractiveMode ,
2627- GeneratedSessionCapability :: SystemNotifications ,
2628- GeneratedSessionCapability :: Elicitation ,
2629- GeneratedSessionCapability :: SessionStore ,
2630- GeneratedSessionCapability :: McpApps ,
2631- GeneratedSessionCapability :: CanvasRenderer ,
2632- ] {
2633- let wire_name = expected_wire_name ( generated) . unwrap ( ) ;
2634- assert_eq ! ( SessionCapability :: from( wire_name) . as_str( ) , wire_name) ;
2635- }
2636- }
2637-
26382382 #[ test]
26392383 fn log_level_args_omitted_when_unset ( ) {
26402384 let opts = ClientOptions :: default ( ) ;
0 commit comments