diff --git a/crates/goose-sdk-types/src/custom_requests.rs b/crates/goose-sdk-types/src/custom_requests.rs index d5dc8729b22f..f8e511f490c8 100644 --- a/crates/goose-sdk-types/src/custom_requests.rs +++ b/crates/goose-sdk-types/src/custom_requests.rs @@ -26,18 +26,16 @@ pub struct CustomMethodSchema { #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] #[request(method = "_goose/unstable/session/extensions/add", response = EmptyResponse)] #[serde(rename_all = "camelCase")] -pub struct AddExtensionRequest { +pub struct AddSessionExtensionRequest { pub session_id: String, - /// Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform). - #[serde(default)] - pub config: serde_json::Value, + pub extension: GooseExtension, } /// Remove an extension from an active session. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] #[request(method = "_goose/unstable/session/extensions/remove", response = EmptyResponse)] #[serde(rename_all = "camelCase")] -pub struct RemoveExtensionRequest { +pub struct RemoveSessionExtensionRequest { pub session_id: String, pub name: String, } @@ -303,7 +301,7 @@ pub struct GetSessionExtensionsRequest { #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] pub struct GetSessionExtensionsResponse { - pub extensions: Vec, + pub extensions: Vec, } /// Read allowlisted user preferences. Empty `keys` means all supported preferences. diff --git a/crates/goose-server/src/openapi.rs b/crates/goose-server/src/openapi.rs index 81eadc67dd06..823feb29d5c3 100644 --- a/crates/goose-server/src/openapi.rs +++ b/crates/goose-server/src/openapi.rs @@ -459,7 +459,6 @@ derive_utoipa!(IconTheme as IconThemeSchema); super::routes::schedule::kill_running_job, super::routes::schedule::inspect_running_job, super::routes::schedule::sessions_handler, - super::routes::recipe::create_recipe, super::routes::recipe::encode_recipe, super::routes::recipe::decode_recipe, super::routes::recipe::scan_recipe, @@ -597,9 +596,6 @@ derive_utoipa!(IconTheme as IconThemeSchema); super::routes::schedule::ListSchedulesResponse, super::routes::schedule::SessionsQuery, super::routes::schedule::SessionDisplayInfo, - super::routes::recipe::CreateRecipeRequest, - super::routes::recipe::AuthorRequest, - super::routes::recipe::CreateRecipeResponse, super::routes::recipe::EncodeRecipeRequest, super::routes::recipe::EncodeRecipeResponse, super::routes::recipe::DecodeRecipeRequest, diff --git a/crates/goose-server/src/routes/recipe.rs b/crates/goose-server/src/routes/recipe.rs index a6f516e3b928..a6a140458388 100644 --- a/crates/goose-server/src/routes/recipe.rs +++ b/crates/goose-server/src/routes/recipe.rs @@ -43,27 +43,6 @@ use crate::routes::recipe_utils::{ }; use crate::state::AppState; -#[derive(Debug, Deserialize, ToSchema)] -pub struct CreateRecipeRequest { - session_id: String, - #[serde(default)] - author: Option, -} - -#[derive(Debug, Deserialize, ToSchema)] -pub struct AuthorRequest { - #[serde(default)] - contact: Option, - #[serde(default)] - metadata: Option, -} - -#[derive(Debug, Serialize, ToSchema)] -pub struct CreateRecipeResponse { - recipe: Option, - error: Option, -} - #[derive(Debug, Deserialize, ToSchema)] pub struct EncodeRecipeRequest { recipe: Recipe, @@ -148,82 +127,6 @@ pub struct RecipeToYamlResponse { yaml: String, } -#[utoipa::path( - post, - path = "/recipes/create", - request_body = CreateRecipeRequest, - responses( - (status = 200, description = "Recipe created successfully", body = CreateRecipeResponse), - (status = 400, description = "Bad request"), - (status = 412, description = "Precondition failed - Agent not available"), - (status = 500, description = "Internal server error") - ), - tag = "Recipe Management" -)] -async fn create_recipe( - State(state): State>, - Json(request): Json, -) -> Result, StatusCode> { - tracing::info!( - "Recipe creation request received for session_id: {}", - request.session_id - ); - - let session = match state - .session_manager() - .get_session(&request.session_id, true) - .await - { - Ok(session) => session, - Err(e) => { - tracing::error!("Failed to get session: {}", e); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } - }; - - let conversation = match session.conversation.clone() { - Some(conversation) => conversation, - None => { - let error_message = "Session has no conversation".to_string(); - let error_response = CreateRecipeResponse { - recipe: None, - error: Some(error_message), - }; - return Ok(Json(error_response)); - } - }; - - let agent = state.get_agent_for_route(request.session_id).await?; - - let recipe_result = agent.create_recipe(&session.id, conversation).await; - - match recipe_result { - Ok(mut recipe) => { - if let Some(author_req) = request.author { - recipe.author = Some(goose::recipe::Author { - contact: author_req.contact, - metadata: author_req.metadata, - }); - } - - Ok(Json(CreateRecipeResponse { - recipe: Some(recipe), - error: None, - })) - } - Err(e) => { - tracing::error!("Error details: {:?}", e); - #[cfg(feature = "telemetry")] - goose::posthog::emit_error("recipe_create_failed", &e.to_string()); - let error_response = CreateRecipeResponse { - recipe: None, - error: Some(format!("Failed to create recipe: {}", e)), - }; - Ok(Json(error_response)) - } - } -} - #[utoipa::path( post, path = "/recipes/encode", @@ -571,7 +474,6 @@ async fn recipe_to_yaml( pub fn routes(state: Arc) -> Router { Router::new() - .route("/recipes/create", post(create_recipe)) .route("/recipes/encode", post(encode_recipe)) .route("/recipes/decode", post(decode_recipe)) .route("/recipes/scan", post(scan_recipe)) diff --git a/crates/goose/acp-meta.json b/crates/goose/acp-meta.json index 2c4ed6ecd0e4..7df1167c6d30 100644 --- a/crates/goose/acp-meta.json +++ b/crates/goose/acp-meta.json @@ -2,12 +2,12 @@ "methods": [ { "method": "_goose/unstable/session/extensions/add", - "requestType": "AddExtensionRequest_unstable", + "requestType": "AddSessionExtensionRequest_unstable", "responseType": "EmptyResponse" }, { "method": "_goose/unstable/session/extensions/remove", - "requestType": "RemoveExtensionRequest_unstable", + "requestType": "RemoveSessionExtensionRequest_unstable", "responseType": "EmptyResponse" }, { diff --git a/crates/goose/acp-schema.json b/crates/goose/acp-schema.json index 4fa7028d9fcc..766331fdc4e1 100644 --- a/crates/goose/acp-schema.json +++ b/crates/goose/acp-schema.json @@ -2,30 +2,365 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "GooseExtensions", "$defs": { - "AddExtensionRequest_unstable": { + "AddSessionExtensionRequest_unstable": { "type": "object", "properties": { "sessionId": { "type": "string" }, - "config": { - "description": "Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform).", - "default": null + "extension": { + "$ref": "#/$defs/GooseExtension" + } + }, + "required": [ + "sessionId", + "extension" + ], + "description": "Add an extension to an active session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/extensions/add" + }, + "GooseExtension": { + "oneOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "timeout": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "const": "builtin" + } + }, + "required": [ + "type", + "name" + ] + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "const": "platform" + } + }, + "required": [ + "type", + "name" + ] + }, + { + "type": "object", + "properties": { + "server": { + "$ref": "#/$defs/McpServer" + }, + "envKeys": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "timeout": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "socket": { + "type": [ + "string", + "null" + ] + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "const": "mcp" + } + }, + "required": [ + "type", + "server" + ] + } + ] + }, + "McpServer": { + "anyOf": [ + { + "$ref": "#/$defs/McpServerHttp", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "http" + } + }, + "required": [ + "type" + ], + "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`." + }, + { + "$ref": "#/$defs/McpServerSse", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "sse" + } + }, + "required": [ + "type" + ], + "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`." + }, + { + "$ref": "#/$defs/McpServerStdio", + "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + } + ], + "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" + }, + "HttpHeader": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the HTTP header." + }, + "value": { + "type": "string", + "description": "The value to set for the HTTP header." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "value" + ], + "description": "An HTTP header to set when making requests to the MCP server." + }, + "McpServerHttp": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "url": { + "type": "string", + "description": "URL to the MCP server." + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "description": "HTTP headers to set when making requests to the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + }, + "type": { + "type": "string", + "const": "http" + } + }, + "required": [ + "type", + "name", + "url", + "headers" + ], + "description": "HTTP transport configuration for MCP." + }, + "McpServerSse": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "url": { + "type": "string", + "description": "URL to the MCP server." + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "description": "HTTP headers to set when making requests to the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + }, + "type": { + "type": "string", + "const": "sse" + } + }, + "required": [ + "type", + "name", + "url", + "headers" + ], + "description": "SSE transport configuration for MCP." + }, + "McpServerStdio": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "command": { + "type": "string", + "description": "Path to the MCP server executable." + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Command-line arguments to pass to the MCP server." + }, + "env": { + "type": "array", + "items": { + "$ref": "#/$defs/EnvVariable" + }, + "description": "Environment variables to set when launching the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" } }, "required": [ - "sessionId" + "name", + "command", + "args", + "env" ], - "description": "Add an extension to an active session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/extensions/add" + "description": "Stdio transport configuration for MCP." + }, + "EnvVariable": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable." + }, + "value": { + "type": "string", + "description": "The value to set for the environment variable." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "value" + ], + "description": "An environment variable to set when launching an MCP server." }, "EmptyResponse": { "type": "object", "description": "Empty success response for operations that return no data.", "x-side": "agent" }, - "RemoveExtensionRequest_unstable": { + "RemoveSessionExtensionRequest_unstable": { "type": "object", "properties": { "sessionId": { @@ -370,209 +705,7 @@ } ] }, - "text": { - "type": "string" - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - } - }, - "required": [ - "text" - ], - "description": "Text provided to or from an LLM." - }, - "ImageContent": { - "type": "object", - "properties": { - "annotations": { - "anyOf": [ - { - "$ref": "#/$defs/Annotations" - }, - { - "type": "null" - } - ] - }, - "data": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "uri": { - "type": [ - "string", - "null" - ] - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - } - }, - "required": [ - "data", - "mimeType" - ], - "description": "An image provided to or from an LLM." - }, - "AudioContent": { - "type": "object", - "properties": { - "annotations": { - "anyOf": [ - { - "$ref": "#/$defs/Annotations" - }, - { - "type": "null" - } - ] - }, - "data": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - } - }, - "required": [ - "data", - "mimeType" - ], - "description": "Audio provided to or from an LLM." - }, - "ResourceLink": { - "type": "object", - "properties": { - "annotations": { - "anyOf": [ - { - "$ref": "#/$defs/Annotations" - }, - { - "type": "null" - } - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "mimeType": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "size": { - "type": [ - "integer", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "uri": { - "type": "string" - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - } - }, - "required": [ - "name", - "uri" - ], - "description": "A resource that the server is capable of reading, included in a prompt or tool call result." - }, - "EmbeddedResourceResource": { - "anyOf": [ - { - "$ref": "#/$defs/TextResourceContents" - }, - { - "$ref": "#/$defs/BlobResourceContents" - } - ], - "description": "Resource content that can be embedded in a message." - }, - "TextResourceContents": { - "type": "object", - "properties": { - "mimeType": { - "type": [ - "string", - "null" - ] - }, - "text": { - "type": "string" - }, - "uri": { - "type": "string" - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - } - }, - "required": [ - "text", - "uri" - ], - "description": "Text-based resource contents." - }, - "BlobResourceContents": { - "type": "object", - "properties": { - "blob": { - "type": "string" - }, - "mimeType": { - "type": [ - "string", - "null" - ] - }, - "uri": { + "text": { "type": "string" }, "_meta": { @@ -585,12 +718,11 @@ } }, "required": [ - "blob", - "uri" + "text" ], - "description": "Binary resource contents." + "description": "Text provided to or from an LLM." }, - "EmbeddedResource": { + "ImageContent": { "type": "object", "properties": { "annotations": { @@ -603,8 +735,17 @@ } ] }, - "resource": { - "$ref": "#/$defs/EmbeddedResourceResource" + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "uri": { + "type": [ + "string", + "null" + ] }, "_meta": { "type": [ @@ -616,266 +757,128 @@ } }, "required": [ - "resource" + "data", + "mimeType" ], - "description": "The contents of a resource, embedded into a prompt or tool call result." + "description": "An image provided to or from an LLM." }, - "SteerSessionResponse_unstable": { + "AudioContent": { "type": "object", "properties": { - "runId": { + "annotations": { + "anyOf": [ + { + "$ref": "#/$defs/Annotations" + }, + { + "type": "null" + } + ] + }, + "data": { "type": "string" }, - "messageId": { - "type": "string", - "description": "Stable id of the queued steer message. The same id later appears as\n`messageId` on the streamed `UserMessageChunk` (with `_meta.goose.steer`),\nletting clients correlate a queued steer with its pickup." - } - }, - "required": [ - "runId", - "messageId" - ], - "x-side": "agent", - "x-method": "_goose/unstable/session/steer" - }, - "DeleteSessionRequest": { - "type": "object", - "properties": { - "sessionId": { + "mimeType": { "type": "string" - } - }, - "required": [ - "sessionId" - ], - "description": "Delete a session.", - "x-side": "agent", - "x-method": "session/delete" - }, - "GetConfigExtensionsRequest_unstable": { - "type": "object", - "description": "List configured extensions and any warnings.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/list" - }, - "GetConfigExtensionsResponse_unstable": { - "type": "object", - "properties": { - "extensions": { - "type": "array", - "items": { - "$ref": "#/$defs/GooseExtensionEntry" - } }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" } }, "required": [ - "extensions" + "data", + "mimeType" ], - "description": "List configured extensions and any warnings.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/list" + "description": "Audio provided to or from an LLM." }, - "GooseExtensionEntry": { + "ResourceLink": { "type": "object", "properties": { - "extension": { - "$ref": "#/$defs/GooseExtension" - }, - "enabled": { - "type": "boolean" + "annotations": { + "anyOf": [ + { + "$ref": "#/$defs/Annotations" + }, + { + "type": "null" + } + ] }, - "configKey": { + "description": { "type": [ "string", "null" ] - } - }, - "required": [ - "extension", - "enabled" - ] - }, - "GooseExtension": { - "oneOf": [ - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "timeout": { - "type": [ - "integer", - "null" - ], - "minimum": 0 - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "builtin" - } - }, - "required": [ - "type", - "name" + }, + "mimeType": { + "type": [ + "string", + "null" ] }, - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "platform" - } - }, - "required": [ - "type", - "name" + "name": { + "type": "string" + }, + "size": { + "type": [ + "integer", + "null" ] }, - { - "type": "object", - "properties": { - "server": { - "$ref": "#/$defs/McpServer" - }, - "envKeys": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "timeout": { - "type": [ - "integer", - "null" - ], - "minimum": 0 - }, - "socket": { - "type": [ - "string", - "null" - ] - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "mcp" - } - }, - "required": [ - "type", - "server" + "title": { + "type": [ + "string", + "null" ] + }, + "uri": { + "type": "string" + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" } - ] + }, + "required": [ + "name", + "uri" + ], + "description": "A resource that the server is capable of reading, included in a prompt or tool call result." }, - "McpServer": { + "EmbeddedResourceResource": { "anyOf": [ { - "$ref": "#/$defs/McpServerHttp", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "http" - } - }, - "required": [ - "type" - ], - "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`." - }, - { - "$ref": "#/$defs/McpServerSse", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "sse" - } - }, - "required": [ - "type" - ], - "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`." + "$ref": "#/$defs/TextResourceContents" }, { - "$ref": "#/$defs/McpServerStdio", - "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + "$ref": "#/$defs/BlobResourceContents" } ], - "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" + "description": "Resource content that can be embedded in a message." }, - "HttpHeader": { + "TextResourceContents": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "The name of the HTTP header." + "mimeType": { + "type": [ + "string", + "null" + ] }, - "value": { - "type": "string", - "description": "The value to set for the HTTP header." + "text": { + "type": "string" + }, + "uri": { + "type": "string" }, "_meta": { "type": [ @@ -887,28 +890,25 @@ } }, "required": [ - "name", - "value" + "text", + "uri" ], - "description": "An HTTP header to set when making requests to the MCP server." + "description": "Text-based resource contents." }, - "McpServerHttp": { + "BlobResourceContents": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "Human-readable name identifying this MCP server." + "blob": { + "type": "string" }, - "url": { - "type": "string", - "description": "URL to the MCP server." + "mimeType": { + "type": [ + "string", + "null" + ] }, - "headers": { - "type": "array", - "items": { - "$ref": "#/$defs/HttpHeader" - }, - "description": "HTTP headers to set when making requests to the MCP server." + "uri": { + "type": "string" }, "_meta": { "type": [ @@ -917,37 +917,29 @@ ], "additionalProperties": {}, "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - }, - "type": { - "type": "string", - "const": "http" } }, "required": [ - "type", - "name", - "url", - "headers" + "blob", + "uri" ], - "description": "HTTP transport configuration for MCP." + "description": "Binary resource contents." }, - "McpServerSse": { + "EmbeddedResource": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "Human-readable name identifying this MCP server." - }, - "url": { - "type": "string", - "description": "URL to the MCP server." + "annotations": { + "anyOf": [ + { + "$ref": "#/$defs/Annotations" + }, + { + "type": "null" + } + ] }, - "headers": { - "type": "array", - "items": { - "$ref": "#/$defs/HttpHeader" - }, - "description": "HTTP headers to set when making requests to the MCP server." + "resource": { + "$ref": "#/$defs/EmbeddedResourceResource" }, "_meta": { "type": [ @@ -956,87 +948,95 @@ ], "additionalProperties": {}, "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - }, - "type": { - "type": "string", - "const": "sse" } }, "required": [ - "type", - "name", - "url", - "headers" + "resource" ], - "description": "SSE transport configuration for MCP." + "description": "The contents of a resource, embedded into a prompt or tool call result." }, - "McpServerStdio": { + "SteerSessionResponse_unstable": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "Human-readable name identifying this MCP server." + "runId": { + "type": "string" }, - "command": { + "messageId": { "type": "string", - "description": "Path to the MCP server executable." - }, - "args": { + "description": "Stable id of the queued steer message. The same id later appears as\n`messageId` on the streamed `UserMessageChunk` (with `_meta.goose.steer`),\nletting clients correlate a queued steer with its pickup." + } + }, + "required": [ + "runId", + "messageId" + ], + "x-side": "agent", + "x-method": "_goose/unstable/session/steer" + }, + "DeleteSessionRequest": { + "type": "object", + "properties": { + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId" + ], + "description": "Delete a session.", + "x-side": "agent", + "x-method": "session/delete" + }, + "GetConfigExtensionsRequest_unstable": { + "type": "object", + "description": "List configured extensions and any warnings.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/list" + }, + "GetConfigExtensionsResponse_unstable": { + "type": "object", + "properties": { + "extensions": { "type": "array", "items": { - "type": "string" - }, - "description": "Command-line arguments to pass to the MCP server." + "$ref": "#/$defs/GooseExtensionEntry" + } }, - "env": { + "warnings": { "type": "array", "items": { - "$ref": "#/$defs/EnvVariable" + "type": "string" }, - "description": "Environment variables to set when launching the MCP server." - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "default": [] } }, "required": [ - "name", - "command", - "args", - "env" + "extensions" ], - "description": "Stdio transport configuration for MCP." + "description": "List configured extensions and any warnings.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/list" }, - "EnvVariable": { + "GooseExtensionEntry": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "The name of the environment variable." + "extension": { + "$ref": "#/$defs/GooseExtension" }, - "value": { - "type": "string", - "description": "The value to set for the environment variable." + "enabled": { + "type": "boolean" }, - "_meta": { + "configKey": { "type": [ - "object", + "string", "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + ] } }, "required": [ - "name", - "value" - ], - "description": "An environment variable to set when launching an MCP server." + "extension", + "enabled" + ] }, "GetAvailableExtensionsRequest_unstable": { "type": "object", @@ -1128,7 +1128,9 @@ "properties": { "extensions": { "type": "array", - "items": {} + "items": { + "$ref": "#/$defs/GooseExtension" + } } }, "required": [ @@ -3704,20 +3706,20 @@ { "allOf": [ { - "$ref": "#/$defs/AddExtensionRequest_unstable" + "$ref": "#/$defs/AddSessionExtensionRequest_unstable" } ], "description": "Params for _goose/unstable/session/extensions/add", - "title": "AddExtensionRequest_unstable" + "title": "AddSessionExtensionRequest_unstable" }, { "allOf": [ { - "$ref": "#/$defs/RemoveExtensionRequest_unstable" + "$ref": "#/$defs/RemoveSessionExtensionRequest_unstable" } ], "description": "Params for _goose/unstable/session/extensions/remove", - "title": "RemoveExtensionRequest_unstable" + "title": "RemoveSessionExtensionRequest_unstable" }, { "allOf": [ diff --git a/crates/goose/src/acp/server.rs b/crates/goose/src/acp/server.rs index eb0d185a32ca..2459b8132b1e 100644 --- a/crates/goose/src/acp/server.rs +++ b/crates/goose/src/acp/server.rs @@ -985,13 +985,18 @@ impl GooseAcpAgent { &self, config: &Config, mcp_servers: Vec, + goose_extensions: Option>, ) -> Result, agent_client_protocol::Error> { let mut extensions = Vec::new(); for builtin in &self.builtins { push_or_replace_extension(&mut extensions, builtin_to_extension_config(builtin)); } - if mcp_servers.is_empty() { + if let Some(goose_extensions) = goose_extensions { + for extension in extensions::goose_extensions_to_configs(goose_extensions)? { + push_or_replace_extension(&mut extensions, extension); + } + } else if mcp_servers.is_empty() { for extension in get_enabled_extensions_with_config(config) { push_or_replace_extension(&mut extensions, extension); } @@ -1113,7 +1118,7 @@ impl GooseAcpAgent { || EnabledExtensionsState::from_extension_data(&session.extension_data).is_none() { let extension_data = - self.build_enabled_extensions_data(config, &session, mcp_servers)?; + self.build_enabled_extensions_data(config, &session, mcp_servers, None)?; builder = builder.extension_data(extension_data); session_needs_update = true; } @@ -1142,8 +1147,9 @@ impl GooseAcpAgent { config: &Config, session: &Session, mcp_servers: Vec, + goose_extensions: Option>, ) -> Result { - let extensions = self.initial_session_extensions(config, mcp_servers)?; + let extensions = self.initial_session_extensions(config, mcp_servers, goose_extensions)?; let mut extension_data = session.extension_data.clone(); EnabledExtensionsState::new(extensions) .to_extension_data(&mut extension_data) @@ -2310,43 +2316,6 @@ impl GooseAcpAgent { )) } - #[allow(dead_code)] - async fn add_mcp_extensions( - agent: &Arc, - mcp_servers: Vec, - session_id: &str, - ) -> Result<(), agent_client_protocol::Error> { - let mut configs = Vec::with_capacity(mcp_servers.len()); - for mcp_server in mcp_servers { - let config = match mcp_server_to_extension_config(mcp_server) { - Ok(c) => c, - Err(msg) => { - return Err(agent_client_protocol::Error::invalid_params().data(msg)); - } - }; - configs.push(config); - } - - if configs.is_empty() { - return Ok(()); - } - - let results = agent - .add_extensions_bulk(configs, session_id) - .await - .internal_err()?; - for result in &results { - if !result.success { - let error_msg = result.error.as_deref().unwrap_or("unknown error"); - return Err(agent_client_protocol::Error::internal_error().data(format!( - "Failed to add MCP server '{}': {}", - result.name, error_msg - ))); - } - } - Ok(()) - } - async fn on_load_session( &self, cx: &ConnectionTo, diff --git a/crates/goose/src/acp/server/custom_dispatch.rs b/crates/goose/src/acp/server/custom_dispatch.rs index ed45793b9e92..a6a747b6e1c6 100644 --- a/crates/goose/src/acp/server/custom_dispatch.rs +++ b/crates/goose/src/acp/server/custom_dispatch.rs @@ -11,20 +11,20 @@ impl GooseAcpAgent { self.handle_custom_request(method, params).await } - #[custom_method(AddExtensionRequest)] - async fn dispatch_add_extension( + #[custom_method(AddSessionExtensionRequest)] + async fn dispatch_add_session_extension( &self, - req: AddExtensionRequest, + req: AddSessionExtensionRequest, ) -> Result { - self.on_add_extension(req).await + self.on_add_session_extension(req).await } - #[custom_method(RemoveExtensionRequest)] - async fn dispatch_remove_extension( + #[custom_method(RemoveSessionExtensionRequest)] + async fn dispatch_remove_session_extension( &self, - req: RemoveExtensionRequest, + req: RemoveSessionExtensionRequest, ) -> Result { - self.on_remove_extension(req).await + self.on_remove_session_extension(req).await } #[custom_method(GetToolsRequest)] diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index fae9bdadba6d..347a4fba7da9 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -4,14 +4,12 @@ use crate::config::extensions::ExtensionEntry; use agent_client_protocol::schema::{HttpHeader, McpServer, McpServerHttp, McpServerStdio}; impl GooseAcpAgent { - pub(super) async fn on_add_extension( + pub(super) async fn on_add_session_extension( &self, - req: AddExtensionRequest, + req: AddSessionExtensionRequest, ) -> Result { let session_id = &req.session_id; - let config: ExtensionConfig = serde_json::from_value(req.config).map_err(|e| { - agent_client_protocol::Error::invalid_params().data(format!("bad config: {e}")) - })?; + let config = goose_extension_to_config_without_secrets(req.extension)?; let agent = self.get_session_agent(&req.session_id).await?; agent .add_extension(config, session_id) @@ -20,9 +18,9 @@ impl GooseAcpAgent { Ok(EmptyResponse {}) } - pub(super) async fn on_remove_extension( + pub(super) async fn on_remove_session_extension( &self, - req: RemoveExtensionRequest, + req: RemoveSessionExtensionRequest, ) -> Result { let session_id = &req.session_id; let agent = self.get_session_agent(&req.session_id).await?; @@ -125,15 +123,15 @@ impl GooseAcpAgent { crate::config::Config::global(), ); - let extensions_json = extensions + let extensions = extensions .into_iter() - .map(|e| serde_json::to_value(&e)) - .collect::, _>>() - .internal_err()?; + .map(|config| config_to_goose_extension(&config)) + .collect::, _>>()? + .into_iter() + .flatten() + .collect::>(); - Ok(GetSessionExtensionsResponse { - extensions: extensions_json, - }) + Ok(GetSessionExtensionsResponse { extensions }) } } @@ -317,6 +315,27 @@ fn goose_extension_to_config( }) } +fn goose_extension_to_config_without_secrets( + extension: GooseExtension, +) -> Result { + let conversion = goose_extension_to_config(extension)?; + if !conversion.secret_updates.is_empty() { + return Err(agent_client_protocol::Error::invalid_params().data( + "extension env values must be passed via envKeys referencing stored secrets, not inline env", + )); + } + Ok(conversion.config) +} + +pub(super) fn goose_extensions_to_configs( + extensions: Vec, +) -> Result, agent_client_protocol::Error> { + extensions + .into_iter() + .map(goose_extension_to_config_without_secrets) + .collect() +} + fn config_entry_to_goose_entry( entry: ExtensionEntry, ) -> Result, agent_client_protocol::Error> { diff --git a/crates/goose/src/acp/server/new_session.rs b/crates/goose/src/acp/server/new_session.rs index a17d568de30c..0cb556351436 100644 --- a/crates/goose/src/acp/server/new_session.rs +++ b/crates/goose/src/acp/server/new_session.rs @@ -1,22 +1,19 @@ -use crate::acp::server::{meta_string, sid_short, validate_absolute_cwd, ResultExt}; +use crate::acp::custom_requests::GooseExtension; +use crate::acp::server::{meta_string, validate_absolute_cwd, ResultExt}; use crate::config::{Config, GooseMode}; use crate::session::SessionType; use super::GooseAcpAgent; -use agent_client_protocol::schema::{NewSessionRequest, NewSessionResponse, SessionId}; +use agent_client_protocol::schema::{Meta, NewSessionRequest, NewSessionResponse, SessionId}; use agent_client_protocol::{Client, ConnectionTo}; use std::collections::HashMap; -use tracing::debug; impl GooseAcpAgent { - #[allow(dead_code)] pub(super) async fn handle_new_session( &self, cx: &ConnectionTo, args: NewSessionRequest, ) -> Result { - debug!(?args, "new session request"); - let t_start = std::time::Instant::now(); validate_absolute_cwd(&args.cwd)?; let project_id = meta_string(args.meta.as_ref(), "projectId")?; let session_type = match meta_string(args.meta.as_ref(), "client")? { @@ -33,8 +30,8 @@ impl GooseAcpAgent { } None => super::resolve_default_provider_model_config(config)?, }; + let goose_extensions = meta_goose_extensions(args.meta.as_ref())?; let current_mode: GooseMode = config.get_goose_mode().unwrap_or_default(); - let t0 = std::time::Instant::now(); let mut goose_session = self .session_manager .create_session( @@ -46,8 +43,12 @@ impl GooseAcpAgent { .await .internal_err_ctx("Failed to create session")?; let mut builder = self.session_manager.update(&goose_session.id); - let extension_data = - self.build_enabled_extensions_data(config, &goose_session, args.mcp_servers)?; + let extension_data = self.build_enabled_extensions_data( + config, + &goose_session, + args.mcp_servers, + goose_extensions, + )?; builder = builder .provider_name(resolved_provider) .model_config(resolved_model_config) @@ -66,8 +67,6 @@ impl GooseAcpAgent { .await .internal_err_ctx("Failed to reload session")?; let session_id_str = goose_session.id.clone(); - let sid = sid_short(&session_id_str); - debug!(target: "perf", sid = %sid, ms = t0.elapsed().as_millis() as u64, "perf: new_session create_session"); let (_agent, extension_results) = self .activate_acp_session(cx, &goose_session, HashMap::new()) @@ -101,12 +100,22 @@ impl GooseAcpAgent { &goose_session, self.supports_goose_custom_notifications(), )?; - debug!( - target: "perf", - sid = %sid, - ms = t_start.elapsed().as_millis() as u64, - "perf: new_session done" - ); Ok(response) } } + +fn meta_goose_extensions( + meta: Option<&Meta>, +) -> Result>, agent_client_protocol::Error> { + let Some(value) = meta.and_then(|m| m.get("enabledExtensions")) else { + return Ok(None); + }; + if value.is_null() { + return Ok(None); + } + serde_json::from_value(value.clone()) + .map(Some) + .map_err(|e| { + agent_client_protocol::Error::invalid_params().data(format!("enabledExtensions: {e}")) + }) +} diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index 0453a3c163ac..3c9c87c859a9 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -315,6 +315,90 @@ fn test_custom_get_extensions() { }); } +#[test] +#[serial] +fn test_custom_session_extensions_add_list_remove() { + let extension_name = "summarize"; + let _guard = env_lock::lock_env([("EXTENSIONS", None::<&str>)]); + 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 list_extension = || async { + let result = send_custom( + conn.cx(), + "_goose/unstable/session/extensions/list", + serde_json::json!({ "sessionId": session_id.clone() }), + ) + .await; + assert!(result.is_ok(), "expected ok, got: {:?}", result); + + let response = result.unwrap(); + let extensions = response + .get("extensions") + .and_then(|extensions| extensions.as_array()) + .expect("extensions should be an array"); + extensions + .iter() + .find(|extension| extension["name"] == extension_name) + .cloned() + }; + + assert!( + list_extension().await.is_none(), + "{extension_name} should not be enabled before add" + ); + + let add_result = send_custom( + conn.cx(), + "_goose/unstable/session/extensions/add", + serde_json::json!({ + "sessionId": session_id.clone(), + "extension": { + "type": "platform", + "name": extension_name, + "description": "Load files/directories and get an LLM summary in a single call", + "displayName": "Summarize", + "bundled": true + } + }), + ) + .await; + assert!(add_result.is_ok(), "expected ok, got: {:?}", add_result); + + let extension = list_extension() + .await + .unwrap_or_else(|| panic!("missing added session extension")); + assert_eq!(extension["type"], "platform"); + assert_eq!(extension["name"], extension_name); + + let remove_result = send_custom( + conn.cx(), + "_goose/unstable/session/extensions/remove", + serde_json::json!({ + "sessionId": session_id.clone(), + "name": extension_name, + }), + ) + .await; + assert!( + remove_result.is_ok(), + "expected ok, got: {:?}", + remove_result + ); + + assert!( + list_extension().await.is_none(), + "removed session extension should not be listed" + ); + }); +} + #[test] #[serial] fn test_custom_get_available_extensions() { diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index ec5898090a9f..9c21ebc92bcd 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -2418,45 +2418,6 @@ } } }, - "/recipes/create": { - "post": { - "tags": [ - "Recipe Management" - ], - "operationId": "create_recipe", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateRecipeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Recipe created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateRecipeResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "412": { - "description": "Precondition failed - Agent not available" - }, - "500": { - "description": "Internal server error" - } - } - } - }, "/recipes/decode": { "post": { "tags": [ @@ -3984,19 +3945,6 @@ } } }, - "AuthorRequest": { - "type": "object", - "properties": { - "contact": { - "type": "string", - "nullable": true - }, - "metadata": { - "type": "string", - "nullable": true - } - } - }, "CallToolRequest": { "type": "object", "required": [ @@ -4482,42 +4430,6 @@ } } }, - "CreateRecipeRequest": { - "type": "object", - "required": [ - "session_id" - ], - "properties": { - "author": { - "allOf": [ - { - "$ref": "#/components/schemas/AuthorRequest" - } - ], - "nullable": true - }, - "session_id": { - "type": "string" - } - } - }, - "CreateRecipeResponse": { - "type": "object", - "properties": { - "error": { - "type": "string", - "nullable": true - }, - "recipe": { - "allOf": [ - { - "$ref": "#/components/schemas/Recipe" - } - ], - "nullable": true - } - } - }, "CreateScheduleRequest": { "type": "object", "required": [ diff --git a/ui/desktop/src/acp/__tests__/chatSessionStore.test.ts b/ui/desktop/src/acp/__tests__/chatSessionStore.test.ts index e9bca9eb6da3..feb750fdc983 100644 --- a/ui/desktop/src/acp/__tests__/chatSessionStore.test.ts +++ b/ui/desktop/src/acp/__tests__/chatSessionStore.test.ts @@ -156,14 +156,6 @@ describe('acpChatSessionStore', () => { expect(snapshot.session?.id).toBe(currentSessionId); expect(snapshot.messages).toEqual([initialMessage]); - expect(snapshot.tokenState).toMatchObject({ - inputTokens: 1, - outputTokens: 2, - totalTokens: 3, - accumulatedInputTokens: 4, - accumulatedOutputTokens: 5, - accumulatedTotalTokens: 9, - }); expect(snapshot.chatState).toBe(ChatState.Idle); expect(snapshot.sessionLoadError).toBeUndefined(); }); diff --git a/ui/desktop/src/acp/chatSessionController.ts b/ui/desktop/src/acp/chatSessionController.ts index 2bf0c182a50f..cf05dc200e31 100644 --- a/ui/desktop/src/acp/chatSessionController.ts +++ b/ui/desktop/src/acp/chatSessionController.ts @@ -1,5 +1,6 @@ import { v7 as uuidv7 } from 'uuid'; -import { updateSessionUserRecipeValues, type Message } from '../api'; +import { updateSessionUserRecipeValues, type Message, type Session } from '../api'; +import type { GooseExtension } from '@aaif/goose-sdk'; import { AppEvents } from '../constants/events'; import { ChatState } from '../types/chatState'; import { errorMessage } from '../utils/conversionUtils'; @@ -17,6 +18,7 @@ import { acpCancelPrompt, acpPromptSession } from './prompt'; import { acpForkSession, acpLoadSession, + acpNewSession, acpTruncateSessionConversation, isAcpSessionLoadInFlight, sessionInfoToSession, @@ -35,6 +37,7 @@ export interface AcpSubmitMessageOptions extends AcpSnapshotOptions { } export interface AcpChatSessionController { + createSession(cwd: string, gooseExtensions: GooseExtension[]): Promise; loadSession(sessionId: string, options?: AcpLoadSessionOptions): Promise; submitMessage( sessionId: string, @@ -73,6 +76,19 @@ function createAcpCreditsExhaustedMessage(error: AcpCreditsExhaustedError): Mess }; } +async function createSession(cwd: string, gooseExtensions: GooseExtension[]): Promise { + const { sessionId, sessionInfo, meta } = await acpNewSession(cwd, gooseExtensions); + const session = sessionInfoToSession(sessionInfo, meta); + + showExtensionLoadResults(meta.extensionResults); + window.dispatchEvent( + new CustomEvent(AppEvents.SESSION_EXTENSIONS_LOADED, { detail: { sessionId } }) + ); + acpChatSessionActions.finishSessionLoad(sessionId, session); + + return session; +} + async function loadSession(sessionId: string, options: AcpLoadSessionOptions = {}): Promise { const cached = acpChatSessionStore.getSnapshot(sessionId); if (cached?.session) { @@ -106,6 +122,10 @@ async function submitMessage( userMessage: Message, options: AcpSubmitMessageOptions ): Promise { + if (acpChatSessionStore.getSnapshot(sessionId)?.activePromptAttemptId) { + return; + } + const promptAttemptId = uuidv7(); acpChatSessionActions.startPromptAttempt(sessionId, promptAttemptId); @@ -247,6 +267,7 @@ async function setRecipeUserParams( } export const acpChatSessionController: AcpChatSessionController = { + createSession, loadSession, submitMessage, stop, diff --git a/ui/desktop/src/acp/chatSessionStore.ts b/ui/desktop/src/acp/chatSessionStore.ts index 70cee7f13dfa..7dfc62608b88 100644 --- a/ui/desktop/src/acp/chatSessionStore.ts +++ b/ui/desktop/src/acp/chatSessionStore.ts @@ -38,22 +38,6 @@ const initialTokenState: TokenState = { accumulatedTotalTokens: 0, }; -function tokenStateFromSession(session: Session | undefined): Partial { - return { - inputTokens: session?.usage?.input_tokens ?? 0, - outputTokens: session?.usage?.output_tokens ?? 0, - totalTokens: session?.usage?.total_tokens ?? 0, - cacheReadTokens: session?.usage?.cache_read_input_tokens ?? 0, - cacheWriteTokens: session?.usage?.cache_write_input_tokens ?? 0, - accumulatedInputTokens: session?.accumulated_usage?.input_tokens ?? 0, - accumulatedOutputTokens: session?.accumulated_usage?.output_tokens ?? 0, - accumulatedTotalTokens: session?.accumulated_usage?.total_tokens ?? 0, - accumulatedCacheReadTokens: session?.accumulated_usage?.cache_read_input_tokens ?? 0, - accumulatedCacheWriteTokens: session?.accumulated_usage?.cache_write_input_tokens ?? 0, - ...(session?.accumulated_cost != null ? { accumulatedCost: session.accumulated_cost } : {}), - }; -} - export interface AcpChatSessionStore { getSnapshot(sessionId: string): AcpChatSessionSnapshot | undefined; } @@ -180,7 +164,6 @@ function createAcpChatSessionStoreInternal(): AcpChatSessionStoreInternal { const finishSessionLoad: AcpChatSessionActions['finishSessionLoad'] = (sessionId, session) => { const entry = getOrCreateEntry(sessionId); entry.session = session; - entry.tokenState = { ...entry.tokenState, ...tokenStateFromSession(session) }; entry.sessionLoadError = undefined; entry.chatState = entry.activePromptAttemptId ? ChatState.Streaming : ChatState.Idle; return notify(sessionId, entry); diff --git a/ui/desktop/src/acp/extensions.ts b/ui/desktop/src/acp/extensions.ts index 7964210b8538..2fad4536a706 100644 --- a/ui/desktop/src/acp/extensions.ts +++ b/ui/desktop/src/acp/extensions.ts @@ -1,7 +1,11 @@ import type { ExtensionResponse, ExtensionEntry } from '../api'; -import type { GooseExtensionEntry, McpServer } from '@aaif/goose-sdk'; +import type { GooseExtension, GooseExtensionEntry, McpServer } from '@aaif/goose-sdk'; import { getAcpClient } from './acpConnection'; +export function gooseExtensionName(extension: GooseExtension): string { + return extension.type === 'mcp' ? extension.server.name : extension.name; +} + function headersToRecord(headers: { name: string; value: string }[] = []) { return Object.fromEntries(headers.map(({ name, value }) => [name, value])); } @@ -65,6 +69,12 @@ function gooseExtensionEntryToExtensionEntry(entry: GooseExtensionEntry): Extens return null; } +export async function getConfiguredGooseExtensions(): Promise { + const client = await getAcpClient(); + const response = await client.goose.configExtensionsList_unstable({}); + return response.extensions; +} + export async function getConfiguredExtensions(): Promise { const client = await getAcpClient(); const response = await client.goose.configExtensionsList_unstable({}); diff --git a/ui/desktop/src/acp/sessions.ts b/ui/desktop/src/acp/sessions.ts index d6db5a3704a9..fb99b060f616 100644 --- a/ui/desktop/src/acp/sessions.ts +++ b/ui/desktop/src/acp/sessions.ts @@ -2,8 +2,10 @@ import type { ForkSessionRequest, ListSessionsRequest, LoadSessionResponse, + NewSessionRequest, SessionInfo, } from '@agentclientprotocol/sdk'; +import type { GooseExtension } from '@aaif/goose-sdk'; import { getAcpClient } from './acpConnection'; import { DEFAULT_CHAT_TITLE } from '../contexts/ChatContext'; import type { ExtensionLoadResult, Recipe, Session } from '../api'; @@ -56,8 +58,8 @@ export interface AcpLoadSessionResult { const inFlightSessionLoads = new Map>(); -export function parseLoadMeta(response: LoadSessionResponse): LoadSessionMeta { - const meta = (response._meta ?? {}) as LoadSessionMeta; +function parseSessionResponseMeta(rawMeta: unknown): LoadSessionMeta { + const meta = (rawMeta ?? {}) as LoadSessionMeta; return { recipe: meta.recipe, userRecipeValues: meta.userRecipeValues, @@ -66,6 +68,10 @@ export function parseLoadMeta(response: LoadSessionResponse): LoadSessionMeta { }; } +export function parseLoadMeta(response: LoadSessionResponse): LoadSessionMeta { + return parseSessionResponseMeta(response._meta); +} + function sessionInfoMeta(s: SessionInfo): GooseSessionInfoMeta { return (s._meta ?? {}) as GooseSessionInfoMeta; } @@ -197,6 +203,33 @@ async function loadAcpSession(sessionId: string): Promise }; } +export interface AcpNewSessionResult { + sessionId: string; + sessionInfo: SessionInfo; + meta: LoadSessionMeta; +} + +export async function acpNewSession( + cwd: string, + gooseExtensions: GooseExtension[] +): Promise { + const client = await getAcpClient(); + const meta: Record = { client: 'goose-desktop' }; + if (gooseExtensions.length > 0) { + meta.enabledExtensions = gooseExtensions; + } + const request: NewSessionRequest = { cwd, mcpServers: [], _meta: meta }; + const response = await client.newSession(request); + const sessionId = String(response.sessionId); + const sessionInfoResponse = await client.goose.sessionInfo_unstable({ sessionId }); + + return { + sessionId, + sessionInfo: sessionInfoResponse.session, + meta: parseSessionResponseMeta(response._meta), + }; +} + export async function acpDeleteSession(sessionId: string): Promise { const client = await getAcpClient(); await client.goose.sessionDelete({ sessionId }); diff --git a/ui/desktop/src/api/index.ts b/ui/desktop/src/api/index.ts index f1de1c86ab2b..17ed66891d55 100644 --- a/ui/desktop/src/api/index.ts +++ b/ui/desktop/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { addExtension, agentAddExtension, agentRemoveExtension, callTool, cancelDownload, cancelLocalModelDownload, checkProvider, cleanupProviderCache, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteLocalModel, deleteModel, deleteProviderSecret, deleteRecipe, deleteSchedule, diagnostics, downloadHfModel, downloadModel, encodeRecipe, exportApp, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getFeatures, getLocalModelDownloadProgress, getModelSettings, getPrompt, getPrompts, getProviderCatalog, getProviderCatalogTemplate, getProviderModelInfo, getProviderModels, getRepoFiles, getSession, getSessionExtensions, getSlashCommands, getTools, getTunnelStatus, importApp, importSessionNostr, inspectRunningJob, killRunningJob, listApps, listBuiltinChatTemplates, listLocalModels, listModels, listProviderSecrets, listRecipes, listSchedules, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchHfModels, sendTelemetryEvent, sessionCancel, sessionEvents, sessionReply, sessionsHandler, setConfigProvider, setRecipeSlashCommand, shareSessionNostr, startAgent, startNanogptSetup, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, syncFeaturedModels, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateModelSettings, updateSchedule, updateSession, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; -export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, CallToolData, CallToolError, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CancelRequest, ChatRequest, ChatTemplate, CheckProviderData, CheckProviderRequest, CleanupProviderCacheData, CleanupProviderCacheErrors, CleanupProviderCacheResponse, CleanupProviderCacheResponses, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, ContentBlock, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteProviderSecretData, DeleteProviderSecretErrors, DeleteProviderSecretResponse, DeleteProviderSecretResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponse, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelRequest, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, EnvVarConfig, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, FeaturesResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetFeaturesData, GetFeaturesResponse, GetFeaturesResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponse, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponse, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponse, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponse, GetProviderCatalogTemplateResponses, GetProviderModelInfoData, GetProviderModelInfoErrors, GetProviderModelInfoResponse, GetProviderModelInfoResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponse, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, GooseMode, HfGgufFile, HfModelInfo, HfModelVariant, HfQuantVariant, Icon, IconTheme, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionNostrData, ImportSessionNostrErrors, ImportSessionNostrRequest, ImportSessionNostrResponse, ImportSessionNostrResponses, InferenceMetadata, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListBuiltinChatTemplatesData, ListBuiltinChatTemplatesResponse, ListBuiltinChatTemplatesResponses, ListLocalModelsData, ListLocalModelsResponse, ListLocalModelsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListProviderSecretsData, ListProviderSecretsErrors, ListProviderSecretsResponse, ListProviderSecretsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, LoadedProvider, LocalModelResponse, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelCapabilities, ModelConfig, ModelDownloadStatus, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ModelSettings, ModelTemplate, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderCatalogEntry, ProviderDetails, ProviderEngine, ProviderMetadata, ProviderModelInfoQuery, ProvidersData, ProviderSecret, ProviderSecretsResponse, ProviderSecretStatus, ProviderSecretStorage, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderTemplate, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, RepoVariantsResponse, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SamplingConfig, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponse, SearchHfModelsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionCancelData, SessionCancelResponses, SessionDisplayInfo, SessionEventsData, SessionEventsErrors, SessionEventsResponse, SessionEventsResponses, SessionExtensionsResponse, SessionReplyData, SessionReplyErrors, SessionReplyRequest, SessionReplyResponse, SessionReplyResponse2, SessionReplyResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, ShareSessionNostrData, ShareSessionNostrErrors, ShareSessionNostrRequest, ShareSessionNostrResponse, ShareSessionNostrResponse2, ShareSessionNostrResponses, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponse, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SyncFeaturedModelsData, SyncFeaturedModelsResponses, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, ThinkingEffort, TokenState, Tool, ToolAnnotations, ToolCallingMode, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponse, UpdateModelSettingsResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionData, UpdateSessionErrors, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionRequest, UpdateSessionResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, Usage, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; +export { addExtension, agentAddExtension, agentRemoveExtension, callTool, cancelDownload, cancelLocalModelDownload, checkProvider, cleanupProviderCache, configureProviderOauth, confirmToolAction, createCustomProvider, createSchedule, decodeRecipe, deleteLocalModel, deleteModel, deleteProviderSecret, deleteRecipe, deleteSchedule, diagnostics, downloadHfModel, downloadModel, encodeRecipe, exportApp, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getFeatures, getLocalModelDownloadProgress, getModelSettings, getPrompt, getPrompts, getProviderCatalog, getProviderCatalogTemplate, getProviderModelInfo, getProviderModels, getRepoFiles, getSession, getSessionExtensions, getSlashCommands, getTools, getTunnelStatus, importApp, importSessionNostr, inspectRunningJob, killRunningJob, listApps, listBuiltinChatTemplates, listLocalModels, listModels, listProviderSecrets, listRecipes, listSchedules, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchHfModels, sendTelemetryEvent, sessionCancel, sessionEvents, sessionReply, sessionsHandler, setConfigProvider, setRecipeSlashCommand, shareSessionNostr, startAgent, startNanogptSetup, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, syncFeaturedModels, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateModelSettings, updateSchedule, updateSession, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; +export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, CallToolData, CallToolError, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CancelRequest, ChatRequest, ChatTemplate, CheckProviderData, CheckProviderRequest, CleanupProviderCacheData, CleanupProviderCacheErrors, CleanupProviderCacheResponse, CleanupProviderCacheResponses, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, ContentBlock, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteProviderSecretData, DeleteProviderSecretErrors, DeleteProviderSecretResponse, DeleteProviderSecretResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponse, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelRequest, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, EnvVarConfig, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, FeaturesResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetFeaturesData, GetFeaturesResponse, GetFeaturesResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponse, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponse, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponse, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponse, GetProviderCatalogTemplateResponses, GetProviderModelInfoData, GetProviderModelInfoErrors, GetProviderModelInfoResponse, GetProviderModelInfoResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponse, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, GooseMode, HfGgufFile, HfModelInfo, HfModelVariant, HfQuantVariant, Icon, IconTheme, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionNostrData, ImportSessionNostrErrors, ImportSessionNostrRequest, ImportSessionNostrResponse, ImportSessionNostrResponses, InferenceMetadata, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListBuiltinChatTemplatesData, ListBuiltinChatTemplatesResponse, ListBuiltinChatTemplatesResponses, ListLocalModelsData, ListLocalModelsResponse, ListLocalModelsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListProviderSecretsData, ListProviderSecretsErrors, ListProviderSecretsResponse, ListProviderSecretsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, LoadedProvider, LocalModelResponse, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelCapabilities, ModelConfig, ModelDownloadStatus, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ModelSettings, ModelTemplate, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderCatalogEntry, ProviderDetails, ProviderEngine, ProviderMetadata, ProviderModelInfoQuery, ProvidersData, ProviderSecret, ProviderSecretsResponse, ProviderSecretStatus, ProviderSecretStorage, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderTemplate, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, RepoVariantsResponse, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SamplingConfig, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponse, SearchHfModelsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionCancelData, SessionCancelResponses, SessionDisplayInfo, SessionEventsData, SessionEventsErrors, SessionEventsResponse, SessionEventsResponses, SessionExtensionsResponse, SessionReplyData, SessionReplyErrors, SessionReplyRequest, SessionReplyResponse, SessionReplyResponse2, SessionReplyResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, ShareSessionNostrData, ShareSessionNostrErrors, ShareSessionNostrRequest, ShareSessionNostrResponse, ShareSessionNostrResponse2, ShareSessionNostrResponses, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponse, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SyncFeaturedModelsData, SyncFeaturedModelsResponses, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, ThinkingEffort, TokenState, Tool, ToolAnnotations, ToolCallingMode, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponse, UpdateModelSettingsResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionData, UpdateSessionErrors, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionRequest, UpdateSessionResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, Usage, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; diff --git a/ui/desktop/src/api/sdk.gen.ts b/ui/desktop/src/api/sdk.gen.ts index dcfc8070c4fc..989646f10eef 100644 --- a/ui/desktop/src/api/sdk.gen.ts +++ b/ui/desktop/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import type { Client, Options as Options2, TDataShape } from './client'; import { client } from './client.gen'; -import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CheckProviderData, CleanupProviderCacheData, CleanupProviderCacheErrors, CleanupProviderCacheResponses, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteProviderSecretData, DeleteProviderSecretErrors, DeleteProviderSecretResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetFeaturesData, GetFeaturesResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponses, GetProviderModelInfoData, GetProviderModelInfoErrors, GetProviderModelInfoResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionNostrData, ImportSessionNostrErrors, ImportSessionNostrResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListBuiltinChatTemplatesData, ListBuiltinChatTemplatesResponses, ListLocalModelsData, ListLocalModelsResponses, ListModelsData, ListModelsResponses, ListProviderSecretsData, ListProviderSecretsErrors, ListProviderSecretsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionCancelData, SessionCancelResponses, SessionEventsData, SessionEventsErrors, SessionEventsResponses, SessionReplyData, SessionReplyErrors, SessionReplyResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, ShareSessionNostrData, ShareSessionNostrErrors, ShareSessionNostrResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SyncFeaturedModelsData, SyncFeaturedModelsResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionData, UpdateSessionErrors, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; +import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CheckProviderData, CleanupProviderCacheData, CleanupProviderCacheErrors, CleanupProviderCacheResponses, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteProviderSecretData, DeleteProviderSecretErrors, DeleteProviderSecretResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetFeaturesData, GetFeaturesResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponses, GetProviderModelInfoData, GetProviderModelInfoErrors, GetProviderModelInfoResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionNostrData, ImportSessionNostrErrors, ImportSessionNostrResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListBuiltinChatTemplatesData, ListBuiltinChatTemplatesResponses, ListLocalModelsData, ListLocalModelsResponses, ListModelsData, ListModelsResponses, ListProviderSecretsData, ListProviderSecretsErrors, ListProviderSecretsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionCancelData, SessionCancelResponses, SessionEventsData, SessionEventsErrors, SessionEventsResponses, SessionReplyData, SessionReplyErrors, SessionReplyResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, ShareSessionNostrData, ShareSessionNostrErrors, ShareSessionNostrResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SyncFeaturedModelsData, SyncFeaturedModelsResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionData, UpdateSessionErrors, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; export type Options = Options2 & { /** @@ -363,15 +363,6 @@ export const syncFeaturedModels = (options export const mcpUiProxy = (options: Options) => (options.client ?? client).get({ url: '/mcp-ui-proxy', ...options }); -export const createRecipe = (options: Options) => (options.client ?? client).post({ - url: '/recipes/create', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } -}); - export const decodeRecipe = (options: Options) => (options.client ?? client).post({ url: '/recipes/decode', ...options, diff --git a/ui/desktop/src/api/types.gen.ts b/ui/desktop/src/api/types.gen.ts index 2bc1a817c789..26cb604a756f 100644 --- a/ui/desktop/src/api/types.gen.ts +++ b/ui/desktop/src/api/types.gen.ts @@ -42,11 +42,6 @@ export type Author = { metadata?: string | null; }; -export type AuthorRequest = { - contact?: string | null; - metadata?: string | null; -}; - export type CallToolRequest = { arguments: unknown; name: string; @@ -178,16 +173,6 @@ export type CreateCustomProviderResponse = { provider_name: string; }; -export type CreateRecipeRequest = { - author?: AuthorRequest | null; - session_id: string; -}; - -export type CreateRecipeResponse = { - error?: string | null; - recipe?: Recipe | null; -}; - export type CreateScheduleRequest = { cron: string; id: string; @@ -3645,37 +3630,6 @@ export type McpUiProxyResponses = { 200: unknown; }; -export type CreateRecipeData = { - body: CreateRecipeRequest; - path?: never; - query?: never; - url: '/recipes/create'; -}; - -export type CreateRecipeErrors = { - /** - * Bad request - */ - 400: unknown; - /** - * Precondition failed - Agent not available - */ - 412: unknown; - /** - * Internal server error - */ - 500: unknown; -}; - -export type CreateRecipeResponses = { - /** - * Recipe created successfully - */ - 200: CreateRecipeResponse; -}; - -export type CreateRecipeResponse2 = CreateRecipeResponses[keyof CreateRecipeResponses]; - export type DecodeRecipeData = { body: DecodeRecipeRequest; path?: never; diff --git a/ui/desktop/src/components/BaseChat.tsx b/ui/desktop/src/components/BaseChat.tsx index 42adee4ba0f0..f87af6ceeb91 100644 --- a/ui/desktop/src/components/BaseChat.tsx +++ b/ui/desktop/src/components/BaseChat.tsx @@ -29,9 +29,6 @@ import { useToolCount } from './alerts/useToolCount'; import { getThinkingMessage, getTextAndImageContent } from '../types/message'; import ParameterInputModal from './ParameterInputModal'; import { substituteParameters } from '../utils/parameterSubstitution'; -import CreateRecipeFromSessionModal from './recipes/CreateRecipeFromSessionModal'; -import { toastSuccess } from '../toasts'; -import { Recipe } from '../recipe'; import { useAutoSubmit } from '../hooks/useAutoSubmit'; import EnvironmentBadge from './GooseSidebar/EnvironmentBadge'; import apeCloudLogo from '../images/logo.png'; @@ -48,18 +45,6 @@ const i18n = defineMessages({ id: 'baseChat.goHome', defaultMessage: 'Go home', }, - noSession: { - id: 'baseChat.noSession', - defaultMessage: 'No Session', - }, - recipeCreatedTitle: { - id: 'baseChat.recipeCreatedTitle', - defaultMessage: 'Workflow created successfully!', - }, - recipeCreatedMessage: { - id: 'baseChat.recipeCreatedMessage', - defaultMessage: '"{title}" has been saved and is ready to use.', - }, }); interface BaseChatProps { @@ -103,7 +88,6 @@ export default function BaseChat({ const contentClassName = cn('pr-1 pb-10 pt-12', (isMobile || isNavCollapsed) && 'pt-16'); const { droppedFiles, setDroppedFiles, handleDrop, handleDragOver } = useFileDrop(); const onStreamFinish = useCallback(() => {}, []); - const [isCreateRecipeModalOpen, setIsCreateRecipeModalOpen] = useState(false); const { session, @@ -323,15 +307,6 @@ export default function BaseChat({ return undefined; }, [isActiveSession, sessionId, chatState]); - useEffect(() => { - const handleMakeAgent = () => { - setIsCreateRecipeModalOpen(true); - }; - - window.addEventListener('make-agent-from-chat', handleMakeAgent); - return () => window.removeEventListener('make-agent-from-chat', handleMakeAgent); - }, []); - useEffect(() => { const handleSessionForked = (event: Event) => { const customEvent = event as CustomEvent<{ @@ -363,20 +338,6 @@ export default function BaseChat({ }; }, [location.pathname, navigate]); - const handleRecipeCreated = (recipe: Recipe) => { - toastSuccess({ - title: intl.formatMessage(i18n.recipeCreatedTitle), - msg: intl.formatMessage(i18n.recipeCreatedMessage, { title: recipe.title }), - }); - }; - - const chat: ChatType = { - messages, - recipe, - sessionId, - name: session?.name || intl.formatMessage(i18n.noSession), - }; - const lastSetNameRef = useRef(''); useEffect(() => { @@ -606,13 +567,6 @@ export default function BaseChat({ } /> )} - - setIsCreateRecipeModalOpen(false)} - sessionId={chat.sessionId} - onRecipeCreated={handleRecipeCreated} - /> ); } diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index f7a848331e02..d04099b196e3 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -162,10 +162,6 @@ const i18n = defineMessages({ id: 'chatInput.viewEditRecipe', defaultMessage: 'View/Edit Workflow', }, - createRecipeFromSession: { - id: 'chatInput.createRecipeFromSession', - defaultMessage: 'Create Workflow from Session', - }, }); interface ChatInputProps { diff --git a/ui/desktop/src/components/recipes/CreateRecipeFromSessionModal.tsx b/ui/desktop/src/components/recipes/CreateRecipeFromSessionModal.tsx deleted file mode 100644 index 054b6db2665a..000000000000 --- a/ui/desktop/src/components/recipes/CreateRecipeFromSessionModal.tsx +++ /dev/null @@ -1,412 +0,0 @@ -import { useState, useEffect } from 'react'; -import { useForm } from '@tanstack/react-form'; -import { Recipe } from '../../recipe'; -import { Geese } from '../icons/Geese'; -import { X, Save, Play, Loader2 } from 'lucide-react'; -import { Button } from '../ui/button'; -import { RecipeFormFields } from './shared/RecipeFormFields'; -import { RecipeFormData } from './shared/recipeFormSchema'; -import { createRecipe } from '../../api/sdk.gen'; -import { RecipeParameter } from './shared/recipeFormSchema'; -import { toastError } from '../../toasts'; -import { saveRecipe } from '../../recipe/recipe_management'; -import { errorMessage } from '../../utils/conversionUtils'; -import { defineMessages, useIntl } from '../../i18n'; - -const i18n = defineMessages({ - title: { - id: 'createRecipeFromSession.title', - defaultMessage: 'Create Workflow from Session', - }, - subtitle: { - id: 'createRecipeFromSession.subtitle', - defaultMessage: 'Create a reusable workflow based on your current conversation.', - }, - analyzingTitle: { - id: 'createRecipeFromSession.analyzingTitle', - defaultMessage: 'Analyzing your conversation', - }, - stageReading: { - id: 'createRecipeFromSession.stageReading', - defaultMessage: 'Reading your conversation...', - }, - stageIdentifying: { - id: 'createRecipeFromSession.stageIdentifying', - defaultMessage: 'Identifying key patterns...', - }, - stageExtracting: { - id: 'createRecipeFromSession.stageExtracting', - defaultMessage: 'Extracting main topics...', - }, - stageGenerating: { - id: 'createRecipeFromSession.stageGenerating', - defaultMessage: 'Generating workflow structure...', - }, - stageFinalizing: { - id: 'createRecipeFromSession.stageFinalizing', - defaultMessage: 'Finalizing details...', - }, - stageComplete: { - id: 'createRecipeFromSession.stageComplete', - defaultMessage: 'Complete!', - }, - extractingInsights: { - id: 'createRecipeFromSession.extractingInsights', - defaultMessage: 'Extracting insights from your chat', - }, - cancel: { - id: 'createRecipeFromSession.cancel', - defaultMessage: 'Cancel', - }, - creating: { - id: 'createRecipeFromSession.creating', - defaultMessage: 'Creating...', - }, - createRecipe: { - id: 'createRecipeFromSession.createRecipe', - defaultMessage: 'Create Workflow', - }, - createAndRunRecipe: { - id: 'createRecipeFromSession.createAndRunRecipe', - defaultMessage: 'Create & Run Workflow', - }, - failedToCreateTitle: { - id: 'createRecipeFromSession.failedToCreateTitle', - defaultMessage: 'Failed to create workflow', - }, - failedToCreateDefaultMsg: { - id: 'createRecipeFromSession.failedToCreateDefaultMsg', - defaultMessage: 'An unexpected error occurred while creating the workflow. Please try again.', - }, -}); - -interface CreateRecipeFromSessionModalProps { - isOpen: boolean; - onClose: () => void; - sessionId: string; - onRecipeCreated?: (recipe: Recipe) => void; -} - -export default function CreateRecipeFromSessionModal({ - isOpen, - onClose, - sessionId, - onRecipeCreated, -}: CreateRecipeFromSessionModalProps) { - const intl = useIntl(); - const [isCreating, setIsCreating] = useState(false); - const [isAnalyzing, setIsAnalyzing] = useState(false); - const [analysisStage, setAnalysisStage] = useState(''); - const [hasAnalyzed, setHasAnalyzed] = useState(false); - - // Initialize form with empty values for new recipe - const form = useForm({ - defaultValues: { - title: '', - description: '', - instructions: '', - prompt: '', - activities: [] as string[], - parameters: [] as RecipeParameter[], - jsonSchema: '', - subRecipes: [], - recipeName: '', - global: true, - } as RecipeFormData, - onSubmit: async ({ value }) => { - await handleCreateRecipe(value); - }, - }); - - // Track form validity with state to make it reactive - const [isFormValid, setIsFormValid] = useState(false); - - // Analyze messages and prefill form when modal opens - useEffect(() => { - if (isOpen && sessionId && !hasAnalyzed) { - setIsAnalyzing(true); - - // Create a sequence of analysis stages for better UX - const stages = [ - intl.formatMessage(i18n.stageReading), - intl.formatMessage(i18n.stageIdentifying), - intl.formatMessage(i18n.stageExtracting), - intl.formatMessage(i18n.stageGenerating), - intl.formatMessage(i18n.stageFinalizing), - ]; - - let currentStageIndex = 0; - setAnalysisStage(stages[0]); - - // Update stage every 800ms - const stageInterval = setInterval(() => { - currentStageIndex = (currentStageIndex + 1) % stages.length; - setAnalysisStage(stages[currentStageIndex]); - }, 800); - - // Call the backend to analyze messages and create a recipe - createRecipe({ - body: { session_id: sessionId }, - throwOnError: true, - }) - .then((response) => { - clearInterval(stageInterval); - setAnalysisStage(intl.formatMessage(i18n.stageComplete)); - - if (response.data?.recipe) { - const recipe = response.data.recipe; - - // Prefill the form with the analyzed recipe information - form.setFieldValue('title', recipe.title || ''); - form.setFieldValue('description', recipe.description || ''); - form.setFieldValue('instructions', recipe.instructions || ''); - form.setFieldValue('activities', recipe.activities || []); - form.setFieldValue('parameters', recipe.parameters || []); - - if (recipe.response?.json_schema) { - form.setFieldValue( - 'jsonSchema', - JSON.stringify(recipe.response.json_schema, null, 2) - ); - } - } else { - console.error('No recipe in response:', response); - } - setHasAnalyzed(true); - }) - .catch((error) => { - console.error('Failed to analyze messages:', error); - setAnalysisStage('Analysis failed'); - }) - .finally(() => { - clearInterval(stageInterval); - setHasAnalyzed(true); - setTimeout(() => { - setIsAnalyzing(false); - setAnalysisStage(''); - }, 500); // Brief delay to show completion - }); - } - }, [isOpen, sessionId, hasAnalyzed, form, intl]); - - // Reset analysis state when modal closes - useEffect(() => { - if (!isOpen) { - setHasAnalyzed(false); - setIsAnalyzing(false); - setAnalysisStage(''); - } - }, [isOpen]); - - // Subscribe to form changes using the form's subscribe method - useEffect(() => { - const unsubscribe = form.store.subscribe(() => { - const hasTitle = form.state.values.title?.trim(); - const hasDescription = form.state.values.description?.trim(); - const hasInstructions = form.state.values.instructions?.trim(); - const valid = !!(hasTitle && hasDescription && hasInstructions); - - setIsFormValid(valid); - }); - - // Initial validation check - const hasTitle = form.state.values.title?.trim(); - const hasDescription = form.state.values.description?.trim(); - const hasInstructions = form.state.values.instructions?.trim(); - const valid = !!(hasTitle && hasDescription && hasInstructions); - setIsFormValid(valid); - - return unsubscribe; - }, [form]); - - const handleCreateRecipe = async (formData: RecipeFormData, runAfterSave = false) => { - if (!isFormValid) { - return; - } - - setIsCreating(true); - try { - const formattedSubRecipes = - formData.subRecipes.length > 0 - ? formData.subRecipes.map((subRecipe) => ({ - name: subRecipe.name, - path: subRecipe.path, - description: subRecipe.description || undefined, - values: - subRecipe.values && Object.keys(subRecipe.values).length > 0 - ? subRecipe.values - : undefined, - sequential_when_repeated: subRecipe.sequential_when_repeated, - })) - : undefined; - - const recipe: Recipe = { - title: formData.title, - description: formData.description, - instructions: formData.instructions, - prompt: formData.prompt || undefined, - activities: formData.activities.filter((activity) => activity.trim() !== ''), - parameters: formData.parameters.map((param) => ({ - key: param.key, - input_type: param.input_type || 'string', - requirement: param.requirement, - description: param.description, - ...(param.requirement === 'optional' && param.default ? { default: param.default } : {}), - ...(param.input_type === 'select' && param.options - ? { - options: param.options.filter((opt: string) => opt.trim() !== ''), - } - : {}), - })), - response: - formData.jsonSchema && formData.jsonSchema.trim() - ? { - json_schema: JSON.parse(formData.jsonSchema), - } - : undefined, - sub_recipes: formattedSubRecipes, - }; - - const { id: recipeId } = await saveRecipe(recipe, null); - - onRecipeCreated?.(recipe); - onClose(); - - if (runAfterSave) { - window.electron.createChatWindow({ recipeId }); - } - } catch (error) { - console.error('Failed to create recipe:', error); - toastError({ - title: intl.formatMessage(i18n.failedToCreateTitle), - msg: errorMessage(error, intl.formatMessage(i18n.failedToCreateDefaultMsg)), - }); - } finally { - setIsCreating(false); - } - }; - - if (!isOpen) return null; - - return ( -
-
- {/* Header */} -
-
-
- -
-
-

- {intl.formatMessage(i18n.title)} -

-

{intl.formatMessage(i18n.subtitle)}

-
-
- -
- - {/* Content */} -
- {isAnalyzing ? ( -
-
- -
- {intl.formatMessage(i18n.analyzingTitle)} -
-
-
- {analysisStage} -
-
- - {intl.formatMessage(i18n.extractingInsights)} -
-
- ) : ( -
- -
- )} -
- - {/* Footer */} -
- - -
- {!isAnalyzing && ( - <> - - - - )} -
-
-
-
- ); -} diff --git a/ui/desktop/src/components/recipes/__tests__/CreateRecipeFromSessionModal.test.tsx b/ui/desktop/src/components/recipes/__tests__/CreateRecipeFromSessionModal.test.tsx deleted file mode 100644 index 00e998f69db3..000000000000 --- a/ui/desktop/src/components/recipes/__tests__/CreateRecipeFromSessionModal.test.tsx +++ /dev/null @@ -1,318 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, type RenderOptions, screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import CreateRecipeFromSessionModal from '../CreateRecipeFromSessionModal'; -import { createRecipe } from '../../../api/sdk.gen'; -import type { CreateRecipeResponse } from '../../../api/types.gen'; -import { IntlTestWrapper } from '../../../i18n/test-utils'; - -const renderWithIntl = (ui: React.ReactElement, options?: RenderOptions) => - render(ui, { wrapper: IntlTestWrapper, ...options }); - -vi.mock('../../../api/sdk.gen', () => ({ - createRecipe: vi.fn(), -})); - -vi.mock('../../../toasts', () => ({ - toastError: vi.fn(), -})); - -vi.mock('../../../recipe/recipe_management', () => ({ - saveRecipe: vi.fn().mockResolvedValue({ id: 'mock-recipe-id', fileName: 'mock-recipe.yaml' }), -})); - -vi.mock('../../ConfigContext', () => ({ - useConfig: () => ({ - extensionsList: [], - getExtensions: vi.fn().mockResolvedValue([]), - getProviders: vi.fn().mockResolvedValue([]), - }), -})); - -const mockCreateRecipe = vi.mocked(createRecipe); - -describe('CreateRecipeFromSessionModal', () => { - const defaultProps = { - isOpen: true, - onClose: vi.fn(), - sessionId: 'test-session-id', - onRecipeCreated: vi.fn(), - }; - - beforeEach(() => { - vi.clearAllMocks(); - const mockResponse: CreateRecipeResponse = { - recipe: { - title: 'Analyzed Recipe Title', - description: 'Analyzed description', - instructions: 'Analyzed instructions with {{param1}}', - prompt: 'Analyzed prompt', - activities: ['activity1', 'activity2'], - parameters: [ - { - key: 'param1', - description: 'Auto-detected parameter', - input_type: 'string', - requirement: 'required', - }, - ], - response: { - json_schema: { type: 'object' }, - }, - }, - error: undefined, - }; - - mockCreateRecipe.mockResolvedValue({ - data: mockResponse, - error: undefined, - request: new globalThis.Request('http://localhost/test'), - response: new globalThis.Response(), - }); - }); - - describe('Modal Rendering', () => { - it('renders modal when open', () => { - renderWithIntl(); - - expect(screen.getByTestId('create-recipe-modal')).toBeInTheDocument(); - }); - - it('does not render when closed', () => { - renderWithIntl(); - - expect(screen.queryByTestId('create-recipe-modal')).not.toBeInTheDocument(); - }); - - it('renders modal header with close button', () => { - renderWithIntl(); - - expect(screen.getByTestId('modal-header')).toBeInTheDocument(); - expect(screen.getByTestId('close-button')).toBeInTheDocument(); - }); - - it('calls onClose when close button is clicked', async () => { - const user = userEvent.setup(); - renderWithIntl(); - - await user.click(screen.getByTestId('close-button')); - expect(defaultProps.onClose).toHaveBeenCalled(); - }); - }); - - describe('Analysis Workflow', () => { - it('shows analyzing state initially', () => { - renderWithIntl(); - - expect(screen.getByTestId('analyzing-state')).toBeInTheDocument(); - expect(screen.getByTestId('analyzing-title')).toBeInTheDocument(); - }); - - it('displays analysis progress indicator', async () => { - renderWithIntl(); - - expect(screen.getByTestId('analysis-stage')).toBeInTheDocument(); - - await waitFor( - () => { - const stageElement = screen.getByTestId('analysis-stage'); - expect(stageElement).toBeInTheDocument(); - }, - { timeout: 1000 } - ); - }); - - it('shows loading indicator during analysis', () => { - renderWithIntl(); - - expect(screen.getByTestId('analysis-spinner')).toBeInTheDocument(); - }); - - it('transitions to form state after analysis completes', async () => { - renderWithIntl(); - - await waitFor( - () => { - expect(screen.getByTestId('form-state')).toBeInTheDocument(); - }, - { timeout: 3000 } - ); - - expect(screen.queryByTestId('analyzing-state')).not.toBeInTheDocument(); - }); - }); - - describe('Form Pre-filling', () => { - it('pre-fills form with analyzed data', async () => { - renderWithIntl(); - - // Wait for analysis to complete and form to be pre-filled - await waitFor( - () => { - expect(screen.getByDisplayValue('Analyzed Recipe Title')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - expect(screen.getByDisplayValue('Analyzed description')).toBeInTheDocument(); - expect(screen.getByDisplayValue('Analyzed instructions with {{param1}}')).toBeInTheDocument(); - const promptInput = screen.getByTestId('prompt-input'); - expect(promptInput).toBeInTheDocument(); - }); - - it('shows recipe form fields after analysis', async () => { - renderWithIntl(); - - await waitFor( - () => { - expect(screen.getByTestId('recipe-form')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - expect(screen.getByTestId('title-input')).toBeInTheDocument(); - expect(screen.getByTestId('description-input')).toBeInTheDocument(); - expect(screen.getByTestId('instructions-input')).toBeInTheDocument(); - expect(screen.getByTestId('prompt-input')).toBeInTheDocument(); - }); - }); - - describe('Form Interactions', () => { - it('allows editing form fields', async () => { - const user = userEvent.setup(); - renderWithIntl(); - - await waitFor( - () => { - expect(screen.getByTestId('title-input')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - const titleInput = screen.getByTestId('title-input'); - await user.clear(titleInput); - await user.type(titleInput, 'Modified Title'); - - expect(screen.getByDisplayValue('Modified Title')).toBeInTheDocument(); - }); - - it('validates required fields', async () => { - const user = userEvent.setup(); - renderWithIntl(); - - await waitFor( - () => { - expect(screen.getByTestId('create-recipe-button')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - const titleInput = screen.getByTestId('title-input'); - await user.clear(titleInput); - - const createButton = screen.getByTestId('create-recipe-button'); - expect(createButton).toBeDisabled(); - }); - }); - - describe('Recipe Creation', () => { - it('enables create button when form is valid', async () => { - renderWithIntl(); - - await waitFor( - () => { - const createButton = screen.getByTestId('create-recipe-button'); - expect(createButton).toBeEnabled(); - }, - { timeout: 2000 } - ); - }); - - it('creates recipe and closes modal when form is submitted', async () => { - const user = userEvent.setup(); - renderWithIntl(); - - await waitFor( - () => { - expect(screen.getByTestId('create-recipe-button')).toBeEnabled(); - }, - { timeout: 2000 } - ); - - await user.click(screen.getByTestId('create-recipe-button')); - - await waitFor(() => { - expect(defaultProps.onRecipeCreated).toHaveBeenCalled(); - expect(defaultProps.onClose).toHaveBeenCalled(); - }); - }); - }); - - describe('Modal Footer', () => { - it('shows cancel button in all states', async () => { - renderWithIntl(); - - expect(screen.getByTestId('cancel-button')).toBeInTheDocument(); - - await waitFor( - () => { - expect(screen.getByTestId('create-recipe-button')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - expect(screen.getByTestId('cancel-button')).toBeInTheDocument(); - }); - - it('calls onClose when cancel button is clicked', async () => { - const user = userEvent.setup(); - renderWithIntl(); - - await user.click(screen.getByTestId('cancel-button')); - expect(defaultProps.onClose).toHaveBeenCalled(); - }); - - it('shows different button states based on workflow stage', async () => { - renderWithIntl(); - - expect(screen.getByTestId('cancel-button')).toBeInTheDocument(); - expect(screen.queryByTestId('create-recipe-button')).not.toBeInTheDocument(); - - await waitFor( - () => { - expect(screen.getByTestId('create-recipe-button')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - expect(screen.getByTestId('create-and-run-recipe-button')).toBeInTheDocument(); - }); - }); - - describe('Error Handling', () => { - it('handles analysis errors gracefully', async () => { - renderWithIntl(); - - expect(screen.getByTestId('create-recipe-modal')).toBeInTheDocument(); - }); - - it('handles form validation errors', async () => { - const user = userEvent.setup(); - renderWithIntl(); - - await waitFor( - () => { - expect(screen.getByTestId('title-input')).toBeInTheDocument(); - }, - { timeout: 2000 } - ); - - await user.clear(screen.getByTestId('title-input')); - await user.clear(screen.getByTestId('description-input')); - await user.clear(screen.getByTestId('instructions-input')); - - const createButton = screen.getByTestId('create-recipe-button'); - expect(createButton).toBeDisabled(); - }); - }); -}); diff --git a/ui/desktop/src/i18n/messages/en.json b/ui/desktop/src/i18n/messages/en.json index 3286402983e8..7e635a17a48e 100644 --- a/ui/desktop/src/i18n/messages/en.json +++ b/ui/desktop/src/i18n/messages/en.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "Go home" }, - "baseChat.noSession": { - "defaultMessage": "No Session" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "\"{title}\" has been saved and is ready to use." - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "Workflow created successfully!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "Extension Updated" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "Context window" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "Create Workflow from Session" - }, "chatInput.dictationError": { "defaultMessage": "Dictation Error" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "View/edit workflow" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "Analyzing your conversation" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "Cancel" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "Create & Run Workflow" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "Create Workflow" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "Creating..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "Extracting insights from your chat" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "An unexpected error occurred while creating the workflow. Please try again." - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "Failed to create workflow" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "Complete!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "Extracting main topics..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "Finalizing details..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "Generating workflow structure..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "Identifying key patterns..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "Reading your conversation..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "Create a reusable workflow based on your current conversation." - }, - "createRecipeFromSession.title": { - "defaultMessage": "Create Workflow from Session" - }, "createSubRecipeInline.cancel": { "defaultMessage": "Cancel" }, diff --git a/ui/desktop/src/i18n/messages/es.json b/ui/desktop/src/i18n/messages/es.json index c8e0b7f5d3d3..6a98ee2b0b01 100644 --- a/ui/desktop/src/i18n/messages/es.json +++ b/ui/desktop/src/i18n/messages/es.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "Ir al inicio" }, - "baseChat.noSession": { - "defaultMessage": "Sin sesión" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "\"{title}\" se guardó y está lista para usar." - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "¡Receta creada con éxito!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "Extensión actualizada" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "Ventana de contexto" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "Crear Receta desde la sesión" - }, "chatInput.dictationError": { "defaultMessage": "Error de dictado" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "Ver/editar receta" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "Analizando tu conversación" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "Cancelar" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "Crear y ejecutar Receta" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "Crear Receta" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "Creando..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "Extrayendo ideas de tu chat" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "Ocurrió un error inesperado al crear la receta. Inténtalo de nuevo." - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "No se pudo crear la receta" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "¡Completado!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "Extrayendo los temas principales..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "Finalizando los detalles..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "Generando la estructura de la receta..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "Identificando patrones clave..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "Leyendo tu conversación..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "Crea una receta reutilizable a partir de tu conversación actual." - }, - "createRecipeFromSession.title": { - "defaultMessage": "Crear Receta desde la sesión" - }, "createSubRecipeInline.cancel": { "defaultMessage": "Cancelar" }, diff --git a/ui/desktop/src/i18n/messages/hi.json b/ui/desktop/src/i18n/messages/hi.json index 55f52378099d..1bdf0ee611fe 100644 --- a/ui/desktop/src/i18n/messages/hi.json +++ b/ui/desktop/src/i18n/messages/hi.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "घर जाओ" }, - "baseChat.noSession": { - "defaultMessage": "कोई सत्र नहीं" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "\"{title}\" सहेजा गया है और उपयोग के लिए तैयार है।" - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "रेसिपी सफलतापूर्वक बनाई गई!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "एक्सटेंशन अपडेट किया गया" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "प्रसंग विंडो" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "सत्र से रेसिपी बनाएं" - }, "chatInput.dictationError": { "defaultMessage": "श्रुतलेख त्रुटि" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "रेसिपी देखें/संपादित करें" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "आपकी बातचीत का विश्लेषण" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "रद्द करें" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "रेसिपी बनाएं और चलाएं" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "रेसिपी बनाएं" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "बनाया जा रहा है..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "आपकी चैट से अंतर्दृष्टि निकालना" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "रेसिपी बनाते समय एक अप्रत्याशित त्रुटि उत्पन्न हुई. कृपया पुन: प्रयास करें।" - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "रेसिपी बनाने में विफल" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "पूरा!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "मुख्य विषय निकाले जा रहे हैं..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "विवरण को अंतिम रूप दिया जा रहा है..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "रेसिपी संरचना तैयार की जा रही है..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "प्रमुख पैटर्न की पहचान..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "आपकी बातचीत पढ़ रहा हूँ..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "अपनी मौजूदा बातचीत के आधार पर दोबारा इस्तेमाल होने वाली रेसिपी बनाएं।" - }, - "createRecipeFromSession.title": { - "defaultMessage": "सत्र से रेसिपी बनाएं" - }, "createSubRecipeInline.cancel": { "defaultMessage": "रद्द करें" }, diff --git a/ui/desktop/src/i18n/messages/ja.json b/ui/desktop/src/i18n/messages/ja.json index 2be6e2f0df2c..0bdd0a36acab 100644 --- a/ui/desktop/src/i18n/messages/ja.json +++ b/ui/desktop/src/i18n/messages/ja.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "ホームへ" }, - "baseChat.noSession": { - "defaultMessage": "セッションなし" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "\"{title}\" を保存しました。使用できます。" - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "レシピを作成しました!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "拡張機能を更新しました" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "コンテキストウィンドウ" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "セッションからレシピを作成" - }, "chatInput.dictationError": { "defaultMessage": "音声入力エラー" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "レシピを表示/編集" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "会話を分析中" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "キャンセル" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "レシピを作成して実行" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "レシピを作成" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "作成中..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "チャットからインサイトを抽出中" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "レシピの作成中に予期しないエラーが発生しました。もう一度お試しください。" - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "レシピの作成に失敗しました" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "完了!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "主要トピックを抽出中..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "詳細を仕上げ中..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "レシピ構造を生成中..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "主要なパターンを特定中..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "会話を読み込み中..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "現在の会話に基づいて、再利用可能なレシピを作成します。" - }, - "createRecipeFromSession.title": { - "defaultMessage": "セッションからレシピを作成" - }, "createSubRecipeInline.cancel": { "defaultMessage": "キャンセル" }, diff --git a/ui/desktop/src/i18n/messages/ko.json b/ui/desktop/src/i18n/messages/ko.json index da3066bcaf2d..885cec1082e4 100644 --- a/ui/desktop/src/i18n/messages/ko.json +++ b/ui/desktop/src/i18n/messages/ko.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "홈으로 이동" }, - "baseChat.noSession": { - "defaultMessage": "세션 없음" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "\"{title}\"이 저장되어 사용할 수 있습니다." - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "레시피가 성공적으로 생성되었습니다!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "익스텐션이 업데이트되었습니다." }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "컨텍스트 창" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "세션에서 레시피 생성" - }, "chatInput.dictationError": { "defaultMessage": "받아쓰기 오류" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "레시피 보기/수정" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "대화 분석 중" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "취소" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "레시피 생성 및 실행" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "레시피 생성" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "생성 중..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "채팅에서 통찰력 추출" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "레시피를 생성하는 중에 예상치 못한 오류가 발생했습니다. 다시 시도해 주세요." - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "레시피를 생성하지 못했습니다." - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "완료!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "주요 주제 추출 중..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "세부정보를 마무리하는 중..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "레시피 구조 생성 중..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "주요 패턴 식별 중..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "대화를 읽는 중..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "현재 대화를 기반으로 재사용 가능한 레시피를 만드세요." - }, - "createRecipeFromSession.title": { - "defaultMessage": "세션에서 레시피 생성" - }, "createSubRecipeInline.cancel": { "defaultMessage": "취소" }, diff --git a/ui/desktop/src/i18n/messages/ru.json b/ui/desktop/src/i18n/messages/ru.json index 0ff6783d8f6b..9ea92c6f79ed 100644 --- a/ui/desktop/src/i18n/messages/ru.json +++ b/ui/desktop/src/i18n/messages/ru.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "На главную" }, - "baseChat.noSession": { - "defaultMessage": "Нет сеанса" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "«{title}» сохранено и готово к использованию." - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "Рецепт успешно создан!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "Расширение обновлено" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "Контекстное окно" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "Создать рецепт из сеанса" - }, "chatInput.dictationError": { "defaultMessage": "Ошибка диктовки" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "Просмотреть/изменить рецепт" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "Анализ вашего разговора" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "Отмена" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "Создать и запустить рецепт" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "Создать рецепт" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "Создание..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "Извлечение сведений из вашего чата" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "При создании рецепта произошла непредвиденная ошибка. Повторите попытку." - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "Не удалось создать рецепт" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "Готово!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "Извлечение основных тем..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "Завершение деталей..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "Создание структуры рецепта..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "Определение ключевых шаблонов..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "Чтение вашего разговора..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "Создайте повторно используемый рецепт на основе текущего разговора." - }, - "createRecipeFromSession.title": { - "defaultMessage": "Создать рецепт из сеанса" - }, "createSubRecipeInline.cancel": { "defaultMessage": "Отмена" }, diff --git a/ui/desktop/src/i18n/messages/tr.json b/ui/desktop/src/i18n/messages/tr.json index d1d23aea7b96..c1757b0e2dda 100644 --- a/ui/desktop/src/i18n/messages/tr.json +++ b/ui/desktop/src/i18n/messages/tr.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "Ana sayfaya git" }, - "baseChat.noSession": { - "defaultMessage": "Oturum Yok" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "\"{title}\" kaydedildi ve kullanıma hazır." - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "Tarif başarıyla oluşturuldu!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "Uzantı Güncellendi" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "Bağlam penceresi" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "Oturumdan Tarif Oluştur" - }, "chatInput.dictationError": { "defaultMessage": "Dikte Hatası" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "Tarifi görüntüle/düzenle" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "Konuşmanızı analiz etme" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "İptal" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "Tarif Oluştur ve Çalıştır" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "Tarif Oluştur" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "Oluşturuluyor..." - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "Sohbetinizden içgörüler çıkarma" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "Tarif oluşturulurken beklenmeyen bir hata oluştu. Lütfen tekrar deneyin." - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "Tarif oluşturulamadı" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "Tamamla!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "Ana konular çıkarılıyor..." - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "Ayrıntılar tamamlanıyor..." - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "Tarif yapısı oluşturuluyor..." - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "Anahtar kalıpları belirlemek..." - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "Konuşmanızı okuyorum..." - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "Mevcut konuşmanıza göre yeniden kullanılabilir bir tarif oluşturun." - }, - "createRecipeFromSession.title": { - "defaultMessage": "Oturumdan Tarif Oluştur" - }, "createSubRecipeInline.cancel": { "defaultMessage": "İptal" }, diff --git a/ui/desktop/src/i18n/messages/zh-CN.json b/ui/desktop/src/i18n/messages/zh-CN.json index 597523fec068..efed7c5c65ed 100644 --- a/ui/desktop/src/i18n/messages/zh-CN.json +++ b/ui/desktop/src/i18n/messages/zh-CN.json @@ -116,15 +116,6 @@ "baseChat.goHome": { "defaultMessage": "回到首页" }, - "baseChat.noSession": { - "defaultMessage": "无会话" - }, - "baseChat.recipeCreatedMessage": { - "defaultMessage": "“{title}”已保存,可以使用了。" - }, - "baseChat.recipeCreatedTitle": { - "defaultMessage": "工作流创建成功!" - }, "bottomMenuExtensionSelection.extensionUpdated": { "defaultMessage": "扩展已更新" }, @@ -167,9 +158,6 @@ "chatInput.contextWindow": { "defaultMessage": "上下文窗口" }, - "chatInput.createRecipeFromSession": { - "defaultMessage": "从会话创建工作流" - }, "chatInput.dictationError": { "defaultMessage": "语音输入错误" }, @@ -401,54 +389,6 @@ "createEditRecipe.viewEditRecipeTitle": { "defaultMessage": "查看/编辑工作流" }, - "createRecipeFromSession.analyzingTitle": { - "defaultMessage": "正在分析你的对话" - }, - "createRecipeFromSession.cancel": { - "defaultMessage": "取消" - }, - "createRecipeFromSession.createAndRunRecipe": { - "defaultMessage": "创建并运行工作流" - }, - "createRecipeFromSession.createRecipe": { - "defaultMessage": "创建工作流" - }, - "createRecipeFromSession.creating": { - "defaultMessage": "创建中…" - }, - "createRecipeFromSession.extractingInsights": { - "defaultMessage": "正在从你的聊天中提取要点" - }, - "createRecipeFromSession.failedToCreateDefaultMsg": { - "defaultMessage": "创建工作流时发生意外错误,请重试。" - }, - "createRecipeFromSession.failedToCreateTitle": { - "defaultMessage": "创建工作流失败" - }, - "createRecipeFromSession.stageComplete": { - "defaultMessage": "完成!" - }, - "createRecipeFromSession.stageExtracting": { - "defaultMessage": "正在提取主要话题…" - }, - "createRecipeFromSession.stageFinalizing": { - "defaultMessage": "正在敲定细节…" - }, - "createRecipeFromSession.stageGenerating": { - "defaultMessage": "正在生成工作流结构…" - }, - "createRecipeFromSession.stageIdentifying": { - "defaultMessage": "正在识别关键模式…" - }, - "createRecipeFromSession.stageReading": { - "defaultMessage": "正在阅读你的对话…" - }, - "createRecipeFromSession.subtitle": { - "defaultMessage": "基于当前对话创建一份可复用的工作流。" - }, - "createRecipeFromSession.title": { - "defaultMessage": "从会话创建工作流" - }, "createSubRecipeInline.cancel": { "defaultMessage": "取消" }, diff --git a/ui/desktop/src/sessions.ts b/ui/desktop/src/sessions.ts index 2fa8082949db..41e51aec2b87 100644 --- a/ui/desktop/src/sessions.ts +++ b/ui/desktop/src/sessions.ts @@ -4,6 +4,9 @@ import type { setViewType } from './hooks/useNavigation'; import type { FixedExtensionEntry } from './components/ConfigContext'; import { AppEvents } from './constants/events'; import { decodeRecipe, Recipe } from './recipe'; +import { USE_ACP_CHAT } from './acpChatFeatureFlag'; +import { acpChatSessionController } from './acp/chatSessionController'; +import { getConfiguredGooseExtensions, gooseExtensionName } from './acp/extensions'; export function getSessionDisplayName(session: Session): string { if (session.user_set_name) { @@ -40,15 +43,51 @@ export function resumeSession(session: Session, setView: setViewType) { }); } +interface CreateSessionOptions { + recipeDeeplink?: string; + recipeId?: string; + extensionConfigs?: ExtensionConfig[]; + allExtensions?: FixedExtensionEntry[]; +} + +function selectedExtensionConfigs(options?: CreateSessionOptions): ExtensionConfig[] { + if (options?.extensionConfigs && options.extensionConfigs.length > 0) { + return options.extensionConfigs; + } + if (options?.allExtensions) { + return options.allExtensions + .filter((extension) => extension.enabled) + .map((extension) => { + const { enabled: _enabled, ...config } = extension; + return config as ExtensionConfig; + }); + } + return []; +} + +async function createAcpSession( + workingDir: string, + options?: CreateSessionOptions +): Promise { + const selectedNames = new Set(selectedExtensionConfigs(options).map((config) => config.name)); + const gooseExtensions = + selectedNames.size > 0 + ? (await getConfiguredGooseExtensions()) + .filter((entry) => selectedNames.has(gooseExtensionName(entry.extension))) + .map((entry) => entry.extension) + : []; + return acpChatSessionController.createSession(workingDir, gooseExtensions); +} + export async function createSession( workingDir: string, - options?: { - recipeDeeplink?: string; - recipeId?: string; - extensionConfigs?: ExtensionConfig[]; - allExtensions?: FixedExtensionEntry[]; - } + options?: CreateSessionOptions ): Promise { + const hasRecipe = Boolean(options?.recipeId || options?.recipeDeeplink); + if (USE_ACP_CHAT && !hasRecipe) { + return createAcpSession(workingDir, options); + } + const body: { working_dir: string; recipe?: Recipe; @@ -64,19 +103,9 @@ export async function createSession( body.recipe = await decodeRecipe(options.recipeDeeplink); } - if (options?.extensionConfigs && options.extensionConfigs.length > 0) { - body.extension_overrides = options.extensionConfigs; - } else if (options?.allExtensions) { - const extensionConfigs = options.allExtensions - .filter((extension) => extension.enabled) - .map((extension) => { - const { enabled: _enabled, ...config } = extension; - return config as ExtensionConfig; - }); - - if (extensionConfigs.length > 0) { - body.extension_overrides = extensionConfigs; - } + const extensionConfigs = selectedExtensionConfigs(options); + if (extensionConfigs.length > 0) { + body.extension_overrides = extensionConfigs; } const newAgent = await startAgent({ diff --git a/ui/sdk/src/generated/client.gen.ts b/ui/sdk/src/generated/client.gen.ts index c9a117b207fd..f4303b6ae566 100644 --- a/ui/sdk/src/generated/client.gen.ts +++ b/ui/sdk/src/generated/client.gen.ts @@ -10,7 +10,7 @@ export interface ExtMethodProvider { import type { Client } from "@agentclientprotocol/sdk"; import type { AddConfigExtensionRequest_unstable, - AddExtensionRequest_unstable, + AddSessionExtensionRequest_unstable, ArchiveSessionRequest_unstable, CreateSourceRequest_unstable, CreateSourceResponse_unstable, @@ -95,7 +95,7 @@ import type { RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RemoveConfigExtensionRequest_unstable, - RemoveExtensionRequest_unstable, + RemoveSessionExtensionRequest_unstable, RenameSessionRequest_unstable, SetConfigExtensionEnabledRequest_unstable, SetSessionSystemPromptRequest_unstable, @@ -152,13 +152,13 @@ export class GooseExtClient { constructor(private conn: ExtMethodProvider) {} async sessionExtensionsAdd_unstable( - params: AddExtensionRequest_unstable, + params: AddSessionExtensionRequest_unstable, ): Promise { await this.conn.extMethod("_goose/unstable/session/extensions/add", params); } async sessionExtensionsRemove_unstable( - params: RemoveExtensionRequest_unstable, + params: RemoveSessionExtensionRequest_unstable, ): Promise { await this.conn.extMethod( "_goose/unstable/session/extensions/remove", diff --git a/ui/sdk/src/generated/index.ts b/ui/sdk/src/generated/index.ts index 555182187ece..bc1346f4c8af 100644 --- a/ui/sdk/src/generated/index.ts +++ b/ui/sdk/src/generated/index.ts @@ -1,16 +1,16 @@ // This file is auto-generated by @hey-api/openapi-ts -export type { AddConfigExtensionRequest_unstable, AddExtensionRequest_unstable, Annotations, ArchiveSessionRequest_unstable, AudioContent, BlobResourceContents, ContentBlock, CreateSourceRequest_unstable, CreateSourceResponse_unstable, CustomProviderConfigDto, CustomProviderCreateRequest_unstable, CustomProviderCreateResponse_unstable, CustomProviderDeleteRequest_unstable, CustomProviderDeleteResponse_unstable, CustomProviderReadRequest_unstable, CustomProviderReadResponse_unstable, CustomProviderUpdateRequest_unstable, CustomProviderUpdateResponse_unstable, DefaultsReadRequest_unstable, DefaultsReadResponse_unstable, DefaultsSaveRequest_unstable, DeleteSessionRequest, DeleteSourceRequest_unstable, DictationConfigRequest_unstable, DictationConfigResponse_unstable, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest_unstable, DictationModelDeleteRequest_unstable, DictationModelDownloadProgressRequest_unstable, DictationModelDownloadProgressResponse_unstable, DictationModelDownloadRequest_unstable, DictationModelOption, DictationModelSelectRequest_unstable, DictationModelsListRequest_unstable, DictationModelsListResponse_unstable, DictationProviderStatusEntry, DictationSecretDeleteRequest_unstable, DictationSecretSaveRequest_unstable, DictationTranscribeRequest_unstable, DictationTranscribeResponse_unstable, EmbeddedResource, EmbeddedResourceResource, EmptyResponse, EnvVariable, ExportSessionRequest_unstable, ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, ExtNotification, ExtRequest, ExtResponse, GetAvailableExtensionsRequest_unstable, GetAvailableExtensionsResponse_unstable, GetConfigExtensionsRequest_unstable, GetConfigExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetSessionInfoRequest_unstable, GetSessionInfoResponse_unstable, GetToolsRequest_unstable, GetToolsResponse_unstable, GooseExtension, GooseExtensionEntry, GooseSessionNotification_unstable, GooseSessionUpdate, GooseToolCallRequest_unstable, GooseToolCallResponse_unstable, HttpHeader, ImageContent, ImportSessionRequest_unstable, ImportSessionResponse_unstable, ImportSourcesRequest_unstable, ImportSourcesResponse_unstable, ListProvidersRequest_unstable, ListProvidersResponse_unstable, ListSourcesRequest_unstable, ListSourcesResponse_unstable, McpServer, McpServerHttp, McpServerSse, McpServerStdio, OnboardingImportApplyRequest_unstable, OnboardingImportApplyResponse_unstable, OnboardingImportCandidate, OnboardingImportCounts, OnboardingImportScanRequest_unstable, OnboardingImportScanResponse_unstable, OnboardingImportSourceKind, PreferenceKey, PreferencesReadRequest_unstable, PreferencesReadResponse_unstable, PreferencesRemoveRequest_unstable, PreferencesSaveRequest_unstable, PreferenceValue, ProviderCatalogListRequest_unstable, ProviderCatalogListResponse_unstable, ProviderCatalogTemplateRequest_unstable, ProviderCatalogTemplateResponse_unstable, ProviderConfigAuthenticateRequest_unstable, ProviderConfigChangeResponse_unstable, ProviderConfigDeleteRequest_unstable, ProviderConfigFieldUpdate, ProviderConfigFieldValueDto, ProviderConfigKey, ProviderConfigReadRequest_unstable, ProviderConfigReadResponse_unstable, ProviderConfigSaveRequest_unstable, ProviderConfigStatusDto, ProviderConfigStatusRequest_unstable, ProviderConfigStatusResponse_unstable, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderSetupCatalogEntryDto, ProviderSetupCatalogListRequest_unstable, ProviderSetupCatalogListResponse_unstable, ProviderSetupCategoryDto, ProviderSetupFieldDto, ProviderSetupGroupDto, ProviderSetupMethodDto, ProviderSupportedModelsListRequest_unstable, ProviderSupportedModelsListResponse_unstable, ProviderTemplateCapabilitiesDto, ProviderTemplateCatalogEntryDto, ProviderTemplateDto, ProviderTemplateModelDto, ReadResourceRequest_unstable, ReadResourceResponse_unstable, RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigExtensionRequest_unstable, RemoveExtensionRequest_unstable, RenameSessionRequest_unstable, ResourceLink, Role, SessionId, SessionInfo, SessionSystemPromptMode, SessionUsageUpdate, SetConfigExtensionEnabledRequest_unstable, SetSessionSystemPromptRequest_unstable, SourceEntry, SourceScope, SourceType, StatusMessage, StatusMessageUpdate, SteerSessionRequest_unstable, SteerSessionResponse_unstable, TextContent, TextResourceContents, TruncateSessionConversationRequest_unstable, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, UpdateSourceResponse_unstable, UpdateWorkingDirRequest_unstable } from './types.gen.js'; +export type { AddConfigExtensionRequest_unstable, AddSessionExtensionRequest_unstable, Annotations, ArchiveSessionRequest_unstable, AudioContent, BlobResourceContents, ContentBlock, CreateSourceRequest_unstable, CreateSourceResponse_unstable, CustomProviderConfigDto, CustomProviderCreateRequest_unstable, CustomProviderCreateResponse_unstable, CustomProviderDeleteRequest_unstable, CustomProviderDeleteResponse_unstable, CustomProviderReadRequest_unstable, CustomProviderReadResponse_unstable, CustomProviderUpdateRequest_unstable, CustomProviderUpdateResponse_unstable, DefaultsReadRequest_unstable, DefaultsReadResponse_unstable, DefaultsSaveRequest_unstable, DeleteSessionRequest, DeleteSourceRequest_unstable, DictationConfigRequest_unstable, DictationConfigResponse_unstable, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest_unstable, DictationModelDeleteRequest_unstable, DictationModelDownloadProgressRequest_unstable, DictationModelDownloadProgressResponse_unstable, DictationModelDownloadRequest_unstable, DictationModelOption, DictationModelSelectRequest_unstable, DictationModelsListRequest_unstable, DictationModelsListResponse_unstable, DictationProviderStatusEntry, DictationSecretDeleteRequest_unstable, DictationSecretSaveRequest_unstable, DictationTranscribeRequest_unstable, DictationTranscribeResponse_unstable, EmbeddedResource, EmbeddedResourceResource, EmptyResponse, EnvVariable, ExportSessionRequest_unstable, ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, ExtNotification, ExtRequest, ExtResponse, GetAvailableExtensionsRequest_unstable, GetAvailableExtensionsResponse_unstable, GetConfigExtensionsRequest_unstable, GetConfigExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetSessionInfoRequest_unstable, GetSessionInfoResponse_unstable, GetToolsRequest_unstable, GetToolsResponse_unstable, GooseExtension, GooseExtensionEntry, GooseSessionNotification_unstable, GooseSessionUpdate, GooseToolCallRequest_unstable, GooseToolCallResponse_unstable, HttpHeader, ImageContent, ImportSessionRequest_unstable, ImportSessionResponse_unstable, ImportSourcesRequest_unstable, ImportSourcesResponse_unstable, ListProvidersRequest_unstable, ListProvidersResponse_unstable, ListSourcesRequest_unstable, ListSourcesResponse_unstable, McpServer, McpServerHttp, McpServerSse, McpServerStdio, OnboardingImportApplyRequest_unstable, OnboardingImportApplyResponse_unstable, OnboardingImportCandidate, OnboardingImportCounts, OnboardingImportScanRequest_unstable, OnboardingImportScanResponse_unstable, OnboardingImportSourceKind, PreferenceKey, PreferencesReadRequest_unstable, PreferencesReadResponse_unstable, PreferencesRemoveRequest_unstable, PreferencesSaveRequest_unstable, PreferenceValue, ProviderCatalogListRequest_unstable, ProviderCatalogListResponse_unstable, ProviderCatalogTemplateRequest_unstable, ProviderCatalogTemplateResponse_unstable, ProviderConfigAuthenticateRequest_unstable, ProviderConfigChangeResponse_unstable, ProviderConfigDeleteRequest_unstable, ProviderConfigFieldUpdate, ProviderConfigFieldValueDto, ProviderConfigKey, ProviderConfigReadRequest_unstable, ProviderConfigReadResponse_unstable, ProviderConfigSaveRequest_unstable, ProviderConfigStatusDto, ProviderConfigStatusRequest_unstable, ProviderConfigStatusResponse_unstable, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderSetupCatalogEntryDto, ProviderSetupCatalogListRequest_unstable, ProviderSetupCatalogListResponse_unstable, ProviderSetupCategoryDto, ProviderSetupFieldDto, ProviderSetupGroupDto, ProviderSetupMethodDto, ProviderSupportedModelsListRequest_unstable, ProviderSupportedModelsListResponse_unstable, ProviderTemplateCapabilitiesDto, ProviderTemplateCatalogEntryDto, ProviderTemplateDto, ProviderTemplateModelDto, ReadResourceRequest_unstable, ReadResourceResponse_unstable, RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigExtensionRequest_unstable, RemoveSessionExtensionRequest_unstable, RenameSessionRequest_unstable, ResourceLink, Role, SessionId, SessionInfo, SessionSystemPromptMode, SessionUsageUpdate, SetConfigExtensionEnabledRequest_unstable, SetSessionSystemPromptRequest_unstable, SourceEntry, SourceScope, SourceType, StatusMessage, StatusMessageUpdate, SteerSessionRequest_unstable, SteerSessionResponse_unstable, TextContent, TextResourceContents, TruncateSessionConversationRequest_unstable, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, UpdateSourceResponse_unstable, UpdateWorkingDirRequest_unstable } from './types.gen.js'; export const GOOSE_EXT_METHODS = [ { method: "_goose/unstable/session/extensions/add", - requestType: "AddExtensionRequest_unstable", + requestType: "AddSessionExtensionRequest_unstable", responseType: "EmptyResponse", }, { method: "_goose/unstable/session/extensions/remove", - requestType: "RemoveExtensionRequest_unstable", + requestType: "RemoveSessionExtensionRequest_unstable", responseType: "EmptyResponse", }, { diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index 7a97352d37b1..1eb028c6a731 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -4,12 +4,180 @@ /** * Add an extension to an active session. */ -export type AddExtensionRequest_unstable = { +export type AddSessionExtensionRequest_unstable = { sessionId: string; + extension: GooseExtension; +}; + +export type GooseExtension = { + name: string; + description?: string | null; + display_name?: string | null; + timeout?: number | null; + bundled?: boolean | null; + type: 'builtin'; +} | { + name: string; + description?: string | null; + display_name?: string | null; + bundled?: boolean | null; + type: 'platform'; +} | { + server: McpServer; + envKeys?: Array; + description?: string | null; + timeout?: number | null; + socket?: string | null; + bundled?: boolean | null; + type: 'mcp'; +}; + +/** + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + */ +export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; + +/** + * An HTTP header to set when making requests to the MCP server. + */ +export type HttpHeader = { + /** + * The name of the HTTP header. + */ + name: string; /** - * Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform). + * The value to set for the HTTP header. */ - config?: unknown; + value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * HTTP transport configuration for MCP. + */ +export type McpServerHttp = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + type: 'http'; +}; + +/** + * SSE transport configuration for MCP. + */ +export type McpServerSse = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + type: 'sse'; +}; + +/** + * Stdio transport configuration for MCP. + */ +export type McpServerStdio = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * Path to the MCP server executable. + */ + command: string; + /** + * Command-line arguments to pass to the MCP server. + */ + args: Array; + /** + * Environment variables to set when launching the MCP server. + */ + env: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * An environment variable to set when launching an MCP server. + */ +export type EnvVariable = { + /** + * The name of the environment variable. + */ + name: string; + /** + * The value to set for the environment variable. + */ + value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; }; /** @@ -22,7 +190,7 @@ export type EmptyResponse = { /** * Remove an extension from an active session. */ -export type RemoveExtensionRequest_unstable = { +export type RemoveSessionExtensionRequest_unstable = { sessionId: string; name: string; }; @@ -349,177 +517,6 @@ export type GooseExtensionEntry = { configKey?: string | null; }; -export type GooseExtension = { - name: string; - description?: string | null; - display_name?: string | null; - timeout?: number | null; - bundled?: boolean | null; - type: 'builtin'; -} | { - name: string; - description?: string | null; - display_name?: string | null; - bundled?: boolean | null; - type: 'platform'; -} | { - server: McpServer; - envKeys?: Array; - description?: string | null; - timeout?: number | null; - socket?: string | null; - bundled?: boolean | null; - type: 'mcp'; -}; - -/** - * Configuration for connecting to an MCP (Model Context Protocol) server. - * - * MCP servers provide tools and context that the agent can use when - * processing prompts. - * - * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) - */ -export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; - -/** - * An HTTP header to set when making requests to the MCP server. - */ -export type HttpHeader = { - /** - * The name of the HTTP header. - */ - name: string; - /** - * The value to set for the HTTP header. - */ - value: string; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; -}; - -/** - * HTTP transport configuration for MCP. - */ -export type McpServerHttp = { - /** - * Human-readable name identifying this MCP server. - */ - name: string; - /** - * URL to the MCP server. - */ - url: string; - /** - * HTTP headers to set when making requests to the MCP server. - */ - headers: Array; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; - type: 'http'; -}; - -/** - * SSE transport configuration for MCP. - */ -export type McpServerSse = { - /** - * Human-readable name identifying this MCP server. - */ - name: string; - /** - * URL to the MCP server. - */ - url: string; - /** - * HTTP headers to set when making requests to the MCP server. - */ - headers: Array; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; - type: 'sse'; -}; - -/** - * Stdio transport configuration for MCP. - */ -export type McpServerStdio = { - /** - * Human-readable name identifying this MCP server. - */ - name: string; - /** - * Path to the MCP server executable. - */ - command: string; - /** - * Command-line arguments to pass to the MCP server. - */ - args: Array; - /** - * Environment variables to set when launching the MCP server. - */ - env: Array; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; -}; - -/** - * An environment variable to set when launching an MCP server. - */ -export type EnvVariable = { - /** - * The name of the environment variable. - */ - name: string; - /** - * The value to set for the environment variable. - */ - value: string; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; -}; - /** * List Goose-owned extension definitions available to configure or enable. */ @@ -559,7 +556,7 @@ export type GetSessionExtensionsRequest_unstable = { }; export type GetSessionExtensionsResponse_unstable = { - extensions: Array; + extensions: Array; }; /** @@ -1602,7 +1599,7 @@ export type StatusMessageUpdate = { export type ExtRequest = { id: string; method: string; - params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | SteerSessionRequest_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 | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | GetSessionInfoRequest_unstable | TruncateSessionConversationRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_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 | { + params?: AddSessionExtensionRequest_unstable | RemoveSessionExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | SteerSessionRequest_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 | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | GetSessionInfoRequest_unstable | TruncateSessionConversationRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_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 | { [key: string]: unknown; } | null; }; diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index 54b87f001acb..3345667f08bc 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -2,12 +2,152 @@ import { z } from 'zod'; +/** + * An HTTP header to set when making requests to the MCP server. + */ +export const zHttpHeader = z.object({ + name: z.string(), + value: z.string(), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * HTTP transport configuration for MCP. + */ +export const zMcpServerHttp = z.object({ + name: z.string(), + url: z.string(), + headers: z.array(zHttpHeader), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + type: z.literal('http') +}); + +/** + * SSE transport configuration for MCP. + */ +export const zMcpServerSse = z.object({ + name: z.string(), + url: z.string(), + headers: z.array(zHttpHeader), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + type: z.literal('sse') +}); + +/** + * An environment variable to set when launching an MCP server. + */ +export const zEnvVariable = z.object({ + name: z.string(), + value: z.string(), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * Stdio transport configuration for MCP. + */ +export const zMcpServerStdio = z.object({ + name: z.string(), + command: z.string(), + args: z.array(z.string()), + env: z.array(zEnvVariable), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + */ +export const zMcpServer = z.union([ + zMcpServerHttp, + zMcpServerSse, + zMcpServerStdio +]); + +export const zGooseExtension = z.union([ + z.object({ + name: z.string(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + display_name: z.union([ + z.string(), + z.null() + ]).optional(), + timeout: z.union([ + z.number().int().gte(0), + z.null() + ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + type: z.literal('builtin') + }), + z.object({ + name: z.string(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + display_name: z.union([ + z.string(), + z.null() + ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + type: z.literal('platform') + }), + z.object({ + server: zMcpServer, + envKeys: z.array(z.string()).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + timeout: z.union([ + z.number().int().gte(0), + z.null() + ]).optional(), + socket: z.union([ + z.string(), + z.null() + ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + type: z.literal('mcp') + }) +]); + /** * Add an extension to an active session. */ -export const zAddExtensionRequest_unstable = z.object({ +export const zAddSessionExtensionRequest_unstable = z.object({ sessionId: z.string(), - config: z.unknown().optional().default(null) + extension: zGooseExtension }); /** @@ -18,7 +158,7 @@ export const zEmptyResponse = z.record(z.unknown()); /** * Remove an extension from an active session. */ -export const zRemoveExtensionRequest_unstable = z.object({ +export const zRemoveSessionExtensionRequest_unstable = z.object({ sessionId: z.string(), name: z.string() }); @@ -330,146 +470,6 @@ export const zDeleteSessionRequest = z.object({ */ export const zGetConfigExtensionsRequest_unstable = z.record(z.unknown()); -/** - * An HTTP header to set when making requests to the MCP server. - */ -export const zHttpHeader = z.object({ - name: z.string(), - value: z.string(), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() -}); - -/** - * HTTP transport configuration for MCP. - */ -export const zMcpServerHttp = z.object({ - name: z.string(), - url: z.string(), - headers: z.array(zHttpHeader), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - type: z.literal('http') -}); - -/** - * SSE transport configuration for MCP. - */ -export const zMcpServerSse = z.object({ - name: z.string(), - url: z.string(), - headers: z.array(zHttpHeader), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - type: z.literal('sse') -}); - -/** - * An environment variable to set when launching an MCP server. - */ -export const zEnvVariable = z.object({ - name: z.string(), - value: z.string(), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() -}); - -/** - * Stdio transport configuration for MCP. - */ -export const zMcpServerStdio = z.object({ - name: z.string(), - command: z.string(), - args: z.array(z.string()), - env: z.array(zEnvVariable), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() -}); - -/** - * Configuration for connecting to an MCP (Model Context Protocol) server. - * - * MCP servers provide tools and context that the agent can use when - * processing prompts. - * - * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) - */ -export const zMcpServer = z.union([ - zMcpServerHttp, - zMcpServerSse, - zMcpServerStdio -]); - -export const zGooseExtension = z.union([ - z.object({ - name: z.string(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - display_name: z.union([ - z.string(), - z.null() - ]).optional(), - timeout: z.union([ - z.number().int().gte(0), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('builtin') - }), - z.object({ - name: z.string(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - display_name: z.union([ - z.string(), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('platform') - }), - z.object({ - server: zMcpServer, - envKeys: z.array(z.string()).optional(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - timeout: z.union([ - z.number().int().gte(0), - z.null() - ]).optional(), - socket: z.union([ - z.string(), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('mcp') - }) -]); - export const zGooseExtensionEntry = z.object({ extension: zGooseExtension, enabled: z.boolean(), @@ -524,7 +524,7 @@ export const zGetSessionExtensionsRequest_unstable = z.object({ }); export const zGetSessionExtensionsResponse_unstable = z.object({ - extensions: z.array(z.unknown()) + extensions: z.array(zGooseExtension) }); /** @@ -1573,8 +1573,8 @@ export const zExtRequest = z.object({ method: z.string(), params: z.union([ z.union([ - zAddExtensionRequest_unstable, - zRemoveExtensionRequest_unstable, + zAddSessionExtensionRequest_unstable, + zRemoveSessionExtensionRequest_unstable, zGetToolsRequest_unstable, zGooseToolCallRequest_unstable, zReadResourceRequest_unstable,