feat(acp): add _goose/unstable/session/extensions/apply method (#11081)

Signed-off-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
Matt Toohey
2026-08-12 21:56:04 +10:00
committed by GitHub
parent 752c1fbe33
commit 88709b2c79
17 changed files with 305 additions and 15 deletions
@@ -45,6 +45,25 @@ pub struct RemoveSessionExtensionRequest {
pub name: String,
}
/// Recreate the session's provider, keeping its current provider and model,
/// so that the session's current extension list takes effect.
///
/// Useful after adding or removing session extensions when the provider
/// forwards extensions to a downstream session (ACP harness providers such as
/// claude-acp and codex-acp). Those providers snapshot the extension list when
/// they are built, so extension changes only reach them on rebuild: the
/// provider is replaced with a new instance whose downstream session is
/// created with the updated extension list.
///
/// Providers that don't forward extensions pick up extension changes
/// immediately; for them this call is not required.
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)]
#[request(method = "_goose/unstable/session/extensions/apply", response = EmptyResponse)]
#[serde(rename_all = "camelCase")]
pub struct ApplySessionExtensionsRequest {
pub session_id: String,
}
/// List all tools available in a session.
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)]
#[request(method = "_goose/unstable/tools/list", response = GetToolsResponse)]
+5
View File
@@ -10,6 +10,11 @@
"requestType": "RemoveSessionExtensionRequest_unstable",
"responseType": "EmptyResponse"
},
{
"method": "_goose/unstable/session/extensions/apply",
"requestType": "ApplySessionExtensionsRequest_unstable",
"responseType": "EmptyResponse"
},
{
"method": "_goose/unstable/tools/list",
"requestType": "GetToolsRequest_unstable",
+23
View File
@@ -452,6 +452,20 @@
"x-side": "agent",
"x-method": "_goose/unstable/session/extensions/remove"
},
"ApplySessionExtensionsRequest_unstable": {
"type": "object",
"properties": {
"sessionId": {
"type": "string"
}
},
"required": [
"sessionId"
],
"description": "Recreate the session's provider, keeping its current provider and model,\nso that the session's current extension list takes effect.\n\nUseful after adding or removing session extensions when the provider\nforwards extensions to a downstream session (ACP harness providers such as\nclaude-acp and codex-acp). Those providers snapshot the extension list when\nthey are built, so extension changes only reach them on rebuild: the\nprovider is replaced with a new instance whose downstream session is\ncreated with the updated extension list.\n\nProviders that don't forward extensions pick up extension changes\nimmediately; for them this call is not required.",
"x-side": "agent",
"x-method": "_goose/unstable/session/extensions/apply"
},
"GetToolsRequest_unstable": {
"type": "object",
"properties": {
@@ -6917,6 +6931,15 @@
"description": "Params for _goose/unstable/session/extensions/remove",
"title": "RemoveSessionExtensionRequest_unstable"
},
{
"allOf": [
{
"$ref": "#/$defs/ApplySessionExtensionsRequest_unstable"
}
],
"description": "Params for _goose/unstable/session/extensions/apply",
"title": "ApplySessionExtensionsRequest_unstable"
},
{
"allOf": [
{
+1 -1
View File
@@ -12,5 +12,5 @@ pub mod transport;
pub use common::{map_permission_response, PermissionDecision};
pub use goose_sdk_types::{custom_notifications, custom_requests};
pub use provider::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
resolve_extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
};
+134 -2
View File
@@ -33,7 +33,7 @@ use tokio::sync::{mpsc, oneshot, Mutex as TokioMutex};
use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _};
use crate::acp::{map_permission_response, PermissionDecision};
use crate::config::{ExtensionConfig, GooseMode};
use crate::config::{Config, ExtensionConfig, GooseMode};
use crate::context_mgmt::format_message_for_compacting;
use crate::conversation::message::{Message, MessageContent, TOOL_META_EXTERNAL_DISPATCH_KEY};
use crate::conversation::Conversation;
@@ -1435,7 +1435,33 @@ fn select_mode_id(candidates: &[String], modes: Option<&SessionModeState>) -> Op
}
}
pub fn extension_configs_to_mcp_servers(configs: &[ExtensionConfig]) -> Vec<McpServer> {
/// Extension configs are persisted unresolved: secrets stay in the keyring behind
/// `env_keys`, and uris/headers may still hold `${VAR}` placeholders. Resolve them
/// before handing the servers to the downstream agent, which launches them itself
/// and so needs the real values. An extension that fails to resolve (e.g. a stale
/// `env_keys` entry with no stored secret) is logged and skipped rather than
/// failing the whole provider build, matching how the local extension path
/// contains load errors to the one extension.
pub async fn resolve_extension_configs_to_mcp_servers(
configs: Vec<ExtensionConfig>,
config: &Config,
) -> Vec<McpServer> {
let mut resolved = Vec::with_capacity(configs.len());
for extension in configs {
let name = extension.name();
match extension.resolve(config).await {
Ok(extension) => resolved.push(extension),
Err(error) => tracing::warn!(
extension = %name,
%error,
"skipping extension that failed to resolve; it will not be forwarded to the ACP agent"
),
}
}
extension_configs_to_mcp_servers(&resolved)
}
fn extension_configs_to_mcp_servers(configs: &[ExtensionConfig]) -> Vec<McpServer> {
let mut servers = Vec::new();
for config in configs {
@@ -2597,6 +2623,112 @@ mod tests {
}
}
#[tokio::test]
async fn test_resolve_extension_configs_to_mcp_servers_fills_in_secrets() {
let dir = tempfile::tempdir().unwrap();
let config = Config::new_with_file_secrets(
dir.path().join("config.yaml"),
dir.path().join("secrets.yaml"),
)
.unwrap();
config
.set("GITHUB_TOKEN", &"ghp_xxxxxxxxxxxx", true)
.unwrap();
let servers = resolve_extension_configs_to_mcp_servers(
vec![
ExtensionConfig::Stdio {
name: "github-stdio".into(),
description: String::new(),
cmd: "/path/to/github-mcp-server".into(),
args: vec![],
envs: Envs::default(),
env_keys: vec!["GITHUB_TOKEN".into()],
timeout: None,
cwd: None,
bundled: None,
available_tools: vec![],
},
ExtensionConfig::StreamableHttp {
name: "github-http".into(),
description: String::new(),
uri: "https://api.githubcopilot.com/mcp/".into(),
envs: Envs::default(),
env_keys: vec!["GITHUB_TOKEN".into()],
headers: HashMap::from([(
"Authorization".into(),
"Bearer ${GITHUB_TOKEN}".into(),
)]),
timeout: None,
socket: None,
bundled: None,
available_tools: vec![],
},
],
&config,
)
.await;
let McpServer::Stdio(stdio) = &servers[0] else {
panic!("expected stdio server");
};
assert_eq!(stdio.env.len(), 1);
assert_eq!(stdio.env[0].name, "GITHUB_TOKEN");
assert_eq!(stdio.env[0].value, "ghp_xxxxxxxxxxxx");
let McpServer::Http(http) = &servers[1] else {
panic!("expected http server");
};
assert_eq!(http.headers[0].value, "Bearer ghp_xxxxxxxxxxxx");
}
#[tokio::test]
async fn test_resolve_extension_configs_to_mcp_servers_skips_unresolvable() {
let dir = tempfile::tempdir().unwrap();
let config = Config::new_with_file_secrets(
dir.path().join("config.yaml"),
dir.path().join("secrets.yaml"),
)
.unwrap();
let servers = resolve_extension_configs_to_mcp_servers(
vec![
ExtensionConfig::Stdio {
name: "missing-secret".into(),
description: String::new(),
cmd: "/path/to/server".into(),
args: vec![],
envs: Envs::default(),
env_keys: vec!["NEVER_STORED_KEY".into()],
timeout: None,
cwd: None,
bundled: None,
available_tools: vec![],
},
ExtensionConfig::Stdio {
name: "resolvable".into(),
description: String::new(),
cmd: "/path/to/server".into(),
args: vec![],
envs: Envs::default(),
env_keys: vec![],
timeout: None,
cwd: None,
bundled: None,
available_tools: vec![],
},
],
&config,
)
.await;
assert_eq!(servers.len(), 1);
let McpServer::Stdio(stdio) = &servers[0] else {
panic!("expected stdio server");
};
assert_eq!(stdio.name, "resolvable");
}
#[test]
fn test_sse_skips() {
let config = ExtensionConfig::Sse {
@@ -45,6 +45,14 @@ impl GooseAcpAgent {
self.on_remove_session_extension(req).await
}
#[custom_method(ApplySessionExtensionsRequest)]
async fn dispatch_apply_session_extensions(
&self,
req: ApplySessionExtensionsRequest,
) -> Result<EmptyResponse, agent_client_protocol::Error> {
self.on_apply_session_extensions(req).await
}
#[custom_method(GetToolsRequest)]
async fn dispatch_get_tools(
&self,
+22
View File
@@ -31,6 +31,28 @@ impl GooseAcpAgent {
Ok(EmptyResponse {})
}
pub(super) async fn on_apply_session_extensions(
&self,
req: ApplySessionExtensionsRequest,
) -> Result<EmptyResponse, agent_client_protocol::Error> {
let session_id = &req.session_id;
let agent = self.get_session_agent(session_id).await?;
let provider = agent
.provider()
.await
.internal_err_ctx("Failed to get provider")?;
let provider_name = provider.get_name().to_string();
let model_config = agent
.model_config_for_session(session_id)
.await
.internal_err_ctx("Failed to resolve model config")?;
agent
.recreate_provider_for_session(session_id, &provider_name, model_config)
.await
.internal_err_ctx("Failed to recreate provider")?;
Ok(EmptyResponse {})
}
pub(super) async fn on_get_config_extensions(
&self,
) -> Result<GetConfigExtensionsResponse, agent_client_protocol::Error> {
+2 -2
View File
@@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use crate::acp::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
resolve_extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
};
use crate::config::search_path::SearchPaths;
use crate::config::{Config, GooseMode};
@@ -75,7 +75,7 @@ impl ProviderDef for AmpAcpProvider {
env: vec![],
env_remove: vec![],
work_dir: working_dir,
mcp_servers: extension_configs_to_mcp_servers(&extensions),
mcp_servers: resolve_extension_configs_to_mcp_servers(extensions, config).await,
session_mode_id: mode_mapping[&goose_mode].first().cloned(),
session_config_options: vec![],
model_config_option_id: None,
+2 -2
View File
@@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use crate::acp::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
resolve_extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
};
use crate::config::search_path::SearchPaths;
use crate::config::{Config, GooseMode};
@@ -79,7 +79,7 @@ impl ProviderDef for ClaudeAcpProvider {
// Prevent nested-session detection in claude-agent-acp (wraps Claude Code)
env_remove: vec!["CLAUDECODE".to_string()],
work_dir: working_dir,
mcp_servers: extension_configs_to_mcp_servers(&extensions),
mcp_servers: resolve_extension_configs_to_mcp_servers(extensions, config).await,
session_mode_id: mode_mapping[&goose_mode].first().cloned(),
session_config_options: vec![],
// claude-agent-acp advertises the model as a "model" select
+2 -2
View File
@@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use crate::acp::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
resolve_extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
};
use crate::config::search_path::SearchPaths;
use crate::config::{Config, GooseMode};
@@ -61,7 +61,7 @@ impl ProviderDef for CodexAcpProvider {
.with_npm()
.resolve(CODEX_ACP_PROVIDER_NAME)?;
let goose_mode = config.get_goose_mode().unwrap_or(GooseMode::Auto);
let mcp_servers = extension_configs_to_mcp_servers(&extensions);
let mcp_servers = resolve_extension_configs_to_mcp_servers(extensions, config).await;
let mode_mapping = HashMap::from([
(GooseMode::Auto, vec!["agent-full-access".to_string()]),
+2 -2
View File
@@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use crate::acp::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
resolve_extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
};
use crate::config::search_path::SearchPaths;
use crate::config::{Config, GooseMode};
@@ -89,7 +89,7 @@ impl ProviderDef for CopilotAcpProvider {
env: vec![],
env_remove: vec![],
work_dir: working_dir,
mcp_servers: extension_configs_to_mcp_servers(&extensions),
mcp_servers: resolve_extension_configs_to_mcp_servers(extensions, config).await,
session_mode_id: mode_mapping[&goose_mode].first().cloned(),
session_config_options,
model_config_option_id: Some("model".to_string()),
+2 -2
View File
@@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use crate::acp::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
resolve_extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
};
use crate::config::search_path::SearchPaths;
use crate::config::{Config, GooseMode};
@@ -78,7 +78,7 @@ impl ProviderDef for PiAcpProvider {
env: vec![],
env_remove: vec![],
work_dir: working_dir,
mcp_servers: extension_configs_to_mcp_servers(&extensions),
mcp_servers: resolve_extension_configs_to_mcp_servers(extensions, config).await,
session_mode_id: None,
session_config_options,
model_config_option_id: Some("model".to_string()),
@@ -397,6 +397,35 @@ fn test_custom_session_extensions_add_list_remove() {
});
}
#[test]
#[serial]
fn test_custom_session_extensions_apply_recreates_provider() {
write_acp_global_config(DEFAULT_ACP_TEST_CONFIG);
run_test(async move {
let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await;
let mut conn = AcpServerConnection::new(TestConnectionConfig::default(), openai).await;
let SessionData { session, .. } = conn.new_session().await.unwrap();
let session_id = session.session_id().0.clone();
let result = send_custom(
conn.cx(),
"_goose/unstable/session/extensions/apply",
serde_json::json!({ "sessionId": session_id.clone() }),
)
.await;
assert!(result.is_ok(), "expected ok, got: {:?}", result);
let result = send_custom(
conn.cx(),
"_goose/unstable/session/extensions/apply",
serde_json::json!({ "sessionId": "missing-session" }),
)
.await;
assert!(result.is_err(), "apply for unknown session should fail");
});
}
#[test]
#[serial]
fn test_custom_get_available_extensions() {
+10
View File
@@ -11,6 +11,7 @@ import type { Client } from "@agentclientprotocol/sdk";
import type {
AddConfigExtensionRequest_unstable,
AddSessionExtensionRequest_unstable,
ApplySessionExtensionsRequest_unstable,
AppsDeleteRequest_unstable,
AppsDeleteResponse_unstable,
AppsExportRequest_unstable,
@@ -297,6 +298,15 @@ export class GooseExtClient {
);
}
async sessionExtensionsApply_unstable(
params: ApplySessionExtensionsRequest_unstable,
): Promise<void> {
await this.conn.extMethod(
"_goose/unstable/session/extensions/apply",
params,
);
}
async toolsList_unstable(
params: GetToolsRequest_unstable,
): Promise<GetToolsResponse_unstable> {
File diff suppressed because one or more lines are too long
+19 -1
View File
@@ -254,6 +254,24 @@ export type RemoveSessionExtensionRequest_unstable = {
name: string;
};
/**
* Recreate the session's provider, keeping its current provider and model,
* so that the session's current extension list takes effect.
*
* Useful after adding or removing session extensions when the provider
* forwards extensions to a downstream session (ACP harness providers such as
* claude-acp and codex-acp). Those providers snapshot the extension list when
* they are built, so extension changes only reach them on rebuild: the
* provider is replaced with a new instance whose downstream session is
* created with the updated extension list.
*
* Providers that don't forward extensions pick up extension changes
* immediately; for them this call is not required.
*/
export type ApplySessionExtensionsRequest_unstable = {
sessionId: string;
};
/**
* List all tools available in a session.
*/
@@ -2637,7 +2655,7 @@ export type RecipeParamsAction = 'submit' | 'cancel';
export type ExtRequest = {
id: string;
method: string;
params?: AddSessionExtensionRequest_unstable | RemoveSessionExtensionRequest_unstable | GetToolsRequest_unstable | SetToolPermissionsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | AppsListRequest_unstable | AppsExportRequest_unstable | AppsImportRequest_unstable | AppsDeleteRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | SteerSessionRequest_unstable | DiagnosticsGetRequest_unstable | ListPromptsRequest_unstable | GetPromptRequest_unstable | SavePromptRequest_unstable | ResetPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | ProviderSecretsListRequest_unstable | ProviderSecretDeleteRequest_unstable | CanonicalModelInfoRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | ConfigReadRequest_unstable | ConfigUpsertRequest_unstable | ConfigRemoveRequest_unstable | ConfigReadAllRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | DefaultsClearRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | ShareSessionNostrRequest_unstable | EncodeRecipeRequest_unstable | DecodeRecipeRequest_unstable | ScanRecipeRequest_unstable | ListRecipesRequest_unstable | DeleteRecipeRequest_unstable | ScheduleRecipeRequest_unstable | SetRecipeSlashCommandRequest_unstable | SaveRecipeRequest_unstable | ParseRecipeRequest_unstable | RecipeToYamlRequest_unstable | ListSchedulesRequest_unstable | ListScheduleSessionsRequest_unstable | CreateScheduleRequest_unstable | DeleteScheduleRequest_unstable | PauseScheduleRequest_unstable | UnpauseScheduleRequest_unstable | UpdateScheduleRequest_unstable | RunScheduleNowRequest_unstable | KillRunningJobRequest_unstable | InspectRunningJobRequest_unstable | GetSessionInfoRequest_unstable | TruncateSessionConversationRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | ListAgentMentionsRequest_unstable | ListSlashCommandsRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | LocalInferenceModelsListRequest_unstable | LocalInferenceModelDownloadRequest_unstable | LocalInferenceModelDownloadProgressRequest_unstable | LocalInferenceModelDownloadCancelRequest_unstable | LocalInferenceModelDeleteRequest_unstable | LocalInferenceModelEvictRequest_unstable | LocalInferenceModelSettingsReadRequest_unstable | LocalInferenceModelSettingsUpdateRequest_unstable | LocalInferenceHuggingFaceSearchRequest_unstable | LocalInferenceHuggingFaceRepoVariantsRequest_unstable | LocalInferenceBuiltinChatTemplatesListRequest_unstable | {
params?: AddSessionExtensionRequest_unstable | RemoveSessionExtensionRequest_unstable | ApplySessionExtensionsRequest_unstable | GetToolsRequest_unstable | SetToolPermissionsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | AppsListRequest_unstable | AppsExportRequest_unstable | AppsImportRequest_unstable | AppsDeleteRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | SteerSessionRequest_unstable | DiagnosticsGetRequest_unstable | ListPromptsRequest_unstable | GetPromptRequest_unstable | SavePromptRequest_unstable | ResetPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | ProviderSecretsListRequest_unstable | ProviderSecretDeleteRequest_unstable | CanonicalModelInfoRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | ConfigReadRequest_unstable | ConfigUpsertRequest_unstable | ConfigRemoveRequest_unstable | ConfigReadAllRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | DefaultsClearRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | ShareSessionNostrRequest_unstable | EncodeRecipeRequest_unstable | DecodeRecipeRequest_unstable | ScanRecipeRequest_unstable | ListRecipesRequest_unstable | DeleteRecipeRequest_unstable | ScheduleRecipeRequest_unstable | SetRecipeSlashCommandRequest_unstable | SaveRecipeRequest_unstable | ParseRecipeRequest_unstable | RecipeToYamlRequest_unstable | ListSchedulesRequest_unstable | ListScheduleSessionsRequest_unstable | CreateScheduleRequest_unstable | DeleteScheduleRequest_unstable | PauseScheduleRequest_unstable | UnpauseScheduleRequest_unstable | UpdateScheduleRequest_unstable | RunScheduleNowRequest_unstable | KillRunningJobRequest_unstable | InspectRunningJobRequest_unstable | GetSessionInfoRequest_unstable | TruncateSessionConversationRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | ListAgentMentionsRequest_unstable | ListSlashCommandsRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | LocalInferenceModelsListRequest_unstable | LocalInferenceModelDownloadRequest_unstable | LocalInferenceModelDownloadProgressRequest_unstable | LocalInferenceModelDownloadCancelRequest_unstable | LocalInferenceModelDeleteRequest_unstable | LocalInferenceModelEvictRequest_unstable | LocalInferenceModelSettingsReadRequest_unstable | LocalInferenceModelSettingsUpdateRequest_unstable | LocalInferenceHuggingFaceSearchRequest_unstable | LocalInferenceHuggingFaceRepoVariantsRequest_unstable | LocalInferenceBuiltinChatTemplatesListRequest_unstable | {
[key: string]: unknown;
} | null;
};
+19
View File
@@ -208,6 +208,24 @@ export const zRemoveSessionExtensionRequest_unstable = z.object({
name: z.string()
});
/**
* Recreate the session's provider, keeping its current provider and model,
* so that the session's current extension list takes effect.
*
* Useful after adding or removing session extensions when the provider
* forwards extensions to a downstream session (ACP harness providers such as
* claude-acp and codex-acp). Those providers snapshot the extension list when
* they are built, so extension changes only reach them on rebuild: the
* provider is replaced with a new instance whose downstream session is
* created with the updated extension list.
*
* Providers that don't forward extensions pick up extension changes
* immediately; for them this call is not required.
*/
export const zApplySessionExtensionsRequest_unstable = z.object({
sessionId: z.string()
});
/**
* List all tools available in a session.
*/
@@ -2832,6 +2850,7 @@ export const zExtRequest = z.object({
z.union([
zAddSessionExtensionRequest_unstable,
zRemoveSessionExtensionRequest_unstable,
zApplySessionExtensionsRequest_unstable,
zGetToolsRequest_unstable,
zSetToolPermissionsRequest_unstable,
zGooseToolCallRequest_unstable,