@@ -916,6 +916,42 @@ impl ExtensionInfo {
916916 }
917917}
918918
919+ /// Stable identity for a host/SDK connection that supplies built-in canvases.
920+ ///
921+ /// When set on session create or resume, the runtime uses [`id`] verbatim as
922+ /// the agent-facing canvas extension id, so canvases declared on a control
923+ /// connection survive stdio reconnect and CLI process restart instead of being
924+ /// re-keyed to a per-connection id. The id is opaque to the runtime; a
925+ /// per-window-stable value such as `app:builtin:<windowId>` is recommended. An
926+ /// id beginning with `connection:` is reserved and ignored by the runtime.
927+ ///
928+ /// [`id`]: CanvasProviderIdentity::id
929+ #[ derive( Debug , Clone , Serialize , Deserialize , PartialEq ) ]
930+ #[ serde( rename_all = "camelCase" ) ]
931+ pub struct CanvasProviderIdentity {
932+ /// Opaque, stable provider id used verbatim as the canvas extension id.
933+ pub id : String ,
934+ /// Optional display name surfaced as the canvas extension name.
935+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
936+ pub name : Option < String > ,
937+ }
938+
939+ impl CanvasProviderIdentity {
940+ /// Create a canvas provider identity from a stable opaque id.
941+ pub fn new ( id : impl Into < String > ) -> Self {
942+ Self {
943+ id : id. into ( ) ,
944+ name : None ,
945+ }
946+ }
947+
948+ /// Set the optional display name surfaced as the canvas extension name.
949+ pub fn with_name ( mut self , name : impl Into < String > ) -> Self {
950+ self . name = Some ( name. into ( ) ) ;
951+ self
952+ }
953+ }
954+
919955/// Configuration for a single MCP server.
920956///
921957/// MCP (Model Context Protocol) servers expose external tools to the
@@ -1598,6 +1634,9 @@ pub struct SessionConfig {
15981634 pub extension_sdk_path : Option < String > ,
15991635 /// Stable extension identity for canvas/tool providers on this connection.
16001636 pub extension_info : Option < ExtensionInfo > ,
1637+ /// Stable identity for a host/SDK connection that supplies built-in
1638+ /// canvases, so they survive reconnect and CLI restart.
1639+ pub canvas_provider : Option < CanvasProviderIdentity > ,
16011640 /// Allowlist of built-in tool names the agent may use.
16021641 pub available_tools : Option < Vec < String > > ,
16031642 /// Blocklist of built-in tool names the agent must not use.
@@ -1837,6 +1876,7 @@ impl std::fmt::Debug for SessionConfig {
18371876 . field ( "request_extensions" , & self . request_extensions )
18381877 . field ( "extension_sdk_path" , & self . extension_sdk_path )
18391878 . field ( "extension_info" , & self . extension_info )
1879+ . field ( "canvas_provider" , & self . canvas_provider )
18401880 . field ( "available_tools" , & self . available_tools )
18411881 . field ( "excluded_tools" , & self . excluded_tools )
18421882 . field ( "mcp_servers" , & self . mcp_servers )
@@ -1955,6 +1995,7 @@ impl Default for SessionConfig {
19551995 request_extensions : None ,
19561996 extension_sdk_path : None ,
19571997 extension_info : None ,
1998+ canvas_provider : None ,
19581999 available_tools : None ,
19592000 excluded_tools : None ,
19602001 mcp_servers : None ,
@@ -2100,6 +2141,7 @@ impl SessionConfig {
21002141 request_extensions : self . request_extensions ,
21012142 extension_sdk_path : self . extension_sdk_path ,
21022143 extension_info : self . extension_info ,
2144+ canvas_provider : self . canvas_provider ,
21032145 available_tools : self . available_tools ,
21042146 excluded_tools : self . excluded_tools ,
21052147 tool_filter_precedence : "excluded" ,
@@ -2370,6 +2412,13 @@ impl SessionConfig {
23702412 self
23712413 }
23722414
2415+ /// Set the canvas provider identity for this connection so host-supplied
2416+ /// canvases survive reconnect and CLI restart.
2417+ pub fn with_canvas_provider ( mut self , canvas_provider : CanvasProviderIdentity ) -> Self {
2418+ self . canvas_provider = Some ( canvas_provider) ;
2419+ self
2420+ }
2421+
23732422 /// Set the allowlist of built-in tool names the agent may use.
23742423 pub fn with_available_tools < I , S > ( mut self , tools : I ) -> Self
23752424 where
@@ -2737,6 +2786,9 @@ pub struct ResumeSessionConfig {
27372786 pub extension_sdk_path : Option < String > ,
27382787 /// Stable extension identity for canvas/tool providers on this connection.
27392788 pub extension_info : Option < ExtensionInfo > ,
2789+ /// Stable identity for a host/SDK connection that supplies built-in
2790+ /// canvases, so they rehydrate against a stable extension id on resume.
2791+ pub canvas_provider : Option < CanvasProviderIdentity > ,
27402792 /// Allowlist of tool names the agent may use.
27412793 pub available_tools : Option < Vec < String > > ,
27422794 /// Blocklist of built-in tool names.
@@ -2915,6 +2967,7 @@ impl std::fmt::Debug for ResumeSessionConfig {
29152967 . field ( "request_extensions" , & self . request_extensions )
29162968 . field ( "extension_sdk_path" , & self . extension_sdk_path )
29172969 . field ( "extension_info" , & self . extension_info )
2970+ . field ( "canvas_provider" , & self . canvas_provider )
29182971 . field ( "available_tools" , & self . available_tools )
29192972 . field ( "excluded_tools" , & self . excluded_tools )
29202973 . field ( "mcp_servers" , & self . mcp_servers )
@@ -3068,6 +3121,7 @@ impl ResumeSessionConfig {
30683121 request_extensions : self . request_extensions ,
30693122 extension_sdk_path : self . extension_sdk_path ,
30703123 extension_info : self . extension_info ,
3124+ canvas_provider : self . canvas_provider ,
30713125 available_tools : self . available_tools ,
30723126 excluded_tools : self . excluded_tools ,
30733127 tool_filter_precedence : "excluded" ,
@@ -3158,6 +3212,7 @@ impl ResumeSessionConfig {
31583212 request_extensions : None ,
31593213 extension_sdk_path : None ,
31603214 extension_info : None ,
3215+ canvas_provider : None ,
31613216 available_tools : None ,
31623217 excluded_tools : None ,
31633218 mcp_servers : None ,
@@ -3400,6 +3455,13 @@ impl ResumeSessionConfig {
34003455 self
34013456 }
34023457
3458+ /// Set the canvas provider identity for this connection on resume so
3459+ /// host-supplied canvases rehydrate against a stable extension id.
3460+ pub fn with_canvas_provider ( mut self , canvas_provider : CanvasProviderIdentity ) -> Self {
3461+ self . canvas_provider = Some ( canvas_provider) ;
3462+ self
3463+ }
3464+
34033465 /// Set the allowlist of tool names the agent may use.
34043466 pub fn with_available_tools < I , S > ( mut self , tools : I ) -> Self
34053467 where
0 commit comments