commands to acp+ migration: extensions management (#8733)
This commit is contained in:
@@ -99,11 +99,43 @@ pub struct GetExtensionsRequest {}
|
||||
/// List configured extensions and any warnings.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)]
|
||||
pub struct GetExtensionsResponse {
|
||||
/// Array of ExtensionEntry objects with `enabled` flag and config details.
|
||||
/// Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details.
|
||||
pub extensions: Vec<serde_json::Value>,
|
||||
pub warnings: Vec<String>,
|
||||
}
|
||||
|
||||
/// Persist a new extension to the user's global goose config.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)]
|
||||
#[request(method = "_goose/config/extensions/add", response = EmptyResponse)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AddConfigExtensionRequest {
|
||||
pub name: String,
|
||||
/// Extension configuration. Must be a JSON object matching one of the
|
||||
/// `ExtensionConfig` variants (e.g. `stdio`, `streamable_http`, `builtin`).
|
||||
/// `name` and `enabled` are injected server-side.
|
||||
#[serde(default)]
|
||||
pub extension_config: serde_json::Value,
|
||||
#[serde(default)]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
/// Remove a persisted extension from the user's global goose config.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)]
|
||||
#[request(method = "_goose/config/extensions/remove", response = EmptyResponse)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RemoveConfigExtensionRequest {
|
||||
pub config_key: String,
|
||||
}
|
||||
|
||||
/// Toggle the `enabled` flag for a persisted extension in the user's global goose config.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)]
|
||||
#[request(method = "_goose/config/extensions/toggle", response = EmptyResponse)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ToggleConfigExtensionRequest {
|
||||
pub config_key: String,
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)]
|
||||
#[request(method = "_goose/session/extensions", response = GetSessionExtensionsResponse)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
@@ -35,6 +35,21 @@
|
||||
"requestType": "GetExtensionsRequest",
|
||||
"responseType": "GetExtensionsResponse"
|
||||
},
|
||||
{
|
||||
"method": "_goose/config/extensions/add",
|
||||
"requestType": "AddConfigExtensionRequest",
|
||||
"responseType": "EmptyResponse"
|
||||
},
|
||||
{
|
||||
"method": "_goose/config/extensions/remove",
|
||||
"requestType": "RemoveConfigExtensionRequest",
|
||||
"responseType": "EmptyResponse"
|
||||
},
|
||||
{
|
||||
"method": "_goose/config/extensions/toggle",
|
||||
"requestType": "ToggleConfigExtensionRequest",
|
||||
"responseType": "EmptyResponse"
|
||||
},
|
||||
{
|
||||
"method": "_goose/session/extensions",
|
||||
"requestType": "GetSessionExtensionsRequest",
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"extensions": {
|
||||
"type": "array",
|
||||
"items": {},
|
||||
"description": "Array of ExtensionEntry objects with `enabled` flag and config details."
|
||||
"description": "Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details."
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
@@ -168,6 +168,60 @@
|
||||
"x-side": "agent",
|
||||
"x-method": "_goose/config/extensions"
|
||||
},
|
||||
"AddConfigExtensionRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"extensionConfig": {
|
||||
"description": "Extension configuration. Must be a JSON object matching one of the\n`ExtensionConfig` variants (e.g. `stdio`, `streamable_http`, `builtin`).\n`name` and `enabled` are injected server-side.",
|
||||
"default": null
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"description": "Persist a new extension to the user's global goose config.",
|
||||
"x-side": "agent",
|
||||
"x-method": "_goose/config/extensions/add"
|
||||
},
|
||||
"RemoveConfigExtensionRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"configKey": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"configKey"
|
||||
],
|
||||
"description": "Remove a persisted extension from the user's global goose config.",
|
||||
"x-side": "agent",
|
||||
"x-method": "_goose/config/extensions/remove"
|
||||
},
|
||||
"ToggleConfigExtensionRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"configKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"configKey",
|
||||
"enabled"
|
||||
],
|
||||
"description": "Toggle the `enabled` flag for a persisted extension in the user's global goose config.",
|
||||
"x-side": "agent",
|
||||
"x-method": "_goose/config/extensions/toggle"
|
||||
},
|
||||
"GetSessionExtensionsRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1408,6 +1462,33 @@
|
||||
"description": "Params for _goose/config/extensions",
|
||||
"title": "GetExtensionsRequest"
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/AddConfigExtensionRequest"
|
||||
}
|
||||
],
|
||||
"description": "Params for _goose/config/extensions/add",
|
||||
"title": "AddConfigExtensionRequest"
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/RemoveConfigExtensionRequest"
|
||||
}
|
||||
],
|
||||
"description": "Params for _goose/config/extensions/remove",
|
||||
"title": "RemoveConfigExtensionRequest"
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/ToggleConfigExtensionRequest"
|
||||
}
|
||||
],
|
||||
"description": "Params for _goose/config/extensions/toggle",
|
||||
"title": "ToggleConfigExtensionRequest"
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -2870,7 +2870,17 @@ impl GooseAcpAgent {
|
||||
let warnings = crate::config::extensions::get_warnings();
|
||||
let extensions_json = extensions
|
||||
.into_iter()
|
||||
.map(|e| serde_json::to_value(&e))
|
||||
.map(|e| {
|
||||
let config_key = e.config.key();
|
||||
let mut value = serde_json::to_value(&e)?;
|
||||
if let Some(obj) = value.as_object_mut() {
|
||||
obj.insert(
|
||||
"config_key".to_string(),
|
||||
serde_json::Value::String(config_key),
|
||||
);
|
||||
}
|
||||
Ok::<_, serde_json::Error>(value)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| sacp::Error::internal_error().data(e.to_string()))?;
|
||||
Ok(GetExtensionsResponse {
|
||||
@@ -2879,6 +2889,63 @@ impl GooseAcpAgent {
|
||||
})
|
||||
}
|
||||
|
||||
#[custom_method(AddConfigExtensionRequest)]
|
||||
async fn on_add_config_extension(
|
||||
&self,
|
||||
req: AddConfigExtensionRequest,
|
||||
) -> Result<EmptyResponse, sacp::Error> {
|
||||
let mut obj = match req.extension_config {
|
||||
serde_json::Value::Object(obj) => obj,
|
||||
_ => {
|
||||
return Err(
|
||||
sacp::Error::invalid_params().data("extensionConfig must be a JSON object")
|
||||
);
|
||||
}
|
||||
};
|
||||
obj.insert(
|
||||
"name".to_string(),
|
||||
serde_json::Value::String(req.name.clone()),
|
||||
);
|
||||
|
||||
let config: crate::agents::ExtensionConfig =
|
||||
serde_json::from_value(serde_json::Value::Object(obj))
|
||||
.map_err(|e| sacp::Error::invalid_params().data(format!("bad config: {e}")))?;
|
||||
|
||||
crate::config::extensions::set_extension(crate::config::extensions::ExtensionEntry {
|
||||
enabled: req.enabled,
|
||||
config,
|
||||
});
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
|
||||
#[custom_method(RemoveConfigExtensionRequest)]
|
||||
async fn on_remove_config_extension(
|
||||
&self,
|
||||
req: RemoveConfigExtensionRequest,
|
||||
) -> Result<EmptyResponse, sacp::Error> {
|
||||
let keys = crate::config::extensions::get_all_extension_names();
|
||||
if !keys.iter().any(|k| k == &req.config_key) {
|
||||
return Err(sacp::Error::invalid_params()
|
||||
.data(format!("Extension '{}' not found", req.config_key)));
|
||||
}
|
||||
crate::config::extensions::remove_extension(&req.config_key);
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
|
||||
#[custom_method(ToggleConfigExtensionRequest)]
|
||||
async fn on_toggle_config_extension(
|
||||
&self,
|
||||
req: ToggleConfigExtensionRequest,
|
||||
) -> Result<EmptyResponse, sacp::Error> {
|
||||
let keys = crate::config::extensions::get_all_extension_names();
|
||||
if !keys.iter().any(|k| k == &req.config_key) {
|
||||
return Err(sacp::Error::invalid_params()
|
||||
.data(format!("Extension '{}' not found", req.config_key)));
|
||||
}
|
||||
crate::config::extensions::set_extension_enabled(&req.config_key, req.enabled);
|
||||
Ok(EmptyResponse {})
|
||||
}
|
||||
|
||||
#[custom_method(GetSessionExtensionsRequest)]
|
||||
async fn on_get_session_extensions(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user