merge goose-acp crate into goose (#8726)

This commit is contained in:
Jack Amadeo 2026-04-21 16:26:49 -04:00 committed by GitHub
parent 05af51f18f
commit 38941b1d26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 196 additions and 286 deletions

View file

@ -47,7 +47,6 @@ git commit -s # required for DCO sign-off
``` ```
crates/ crates/
├── goose # core logic ├── goose # core logic
├── goose-acp # Agent Client Protocol
├── goose-acp-macros # ACP proc macros ├── goose-acp-macros # ACP proc macros
├── goose-cli # CLI entry ├── goose-cli # CLI entry
├── goose-server # backend (binary: goosed) ├── goose-server # backend (binary: goosed)

View file

@ -416,7 +416,7 @@ For the full ACP specification, see the [Agent Client Protocol documentation](ht
- API client example: `ui/desktop/src/api/` (generated TypeScript client) - API client example: `ui/desktop/src/api/` (generated TypeScript client)
**ACP**: **ACP**:
- ACP server implementation: `crates/goose-acp/src/server.rs` - ACP server implementation: `crates/goose/src/acp/server.rs`
- CLI integration: `crates/goose-cli/src/cli.rs` (Command::Acp) - CLI integration: `crates/goose-cli/src/cli.rs` (Command::Acp)
- Protocol library: `sacp` crate (Rust implementation of ACP) - Protocol library: `sacp` crate (Rust implementation of ACP)
- Test client example: `test_acp_client.py` - Test client example: `test_acp_client.py`

42
Cargo.lock generated
View file

@ -4358,9 +4358,12 @@ dependencies = [
"fs-err", "fs-err",
"fs2", "fs2",
"futures", "futures",
"goose-acp-macros",
"goose-mcp",
"goose-sdk", "goose-sdk",
"goose-test-support", "goose-test-support",
"http 1.4.0", "http 1.4.0",
"http-body-util",
"ignore", "ignore",
"include_dir", "include_dir",
"indexmap 2.13.0", "indexmap 2.13.0",
@ -4419,6 +4422,7 @@ dependencies = [
"tokio-cron-scheduler", "tokio-cron-scheduler",
"tokio-stream", "tokio-stream",
"tokio-util", "tokio-util",
"tower-http",
"tracing", "tracing",
"tracing-futures", "tracing-futures",
"tracing-opentelemetry", "tracing-opentelemetry",
@ -4446,43 +4450,6 @@ dependencies = [
"zip 8.4.0", "zip 8.4.0",
] ]
[[package]]
name = "goose-acp"
version = "1.31.0"
dependencies = [
"agent-client-protocol-schema",
"anyhow",
"async-stream",
"async-trait",
"axum",
"base64 0.22.1",
"fs-err",
"futures",
"goose",
"goose-acp-macros",
"goose-mcp",
"goose-sdk",
"goose-test-support",
"http-body-util",
"regex",
"rmcp",
"sacp",
"schemars 1.2.1",
"serde",
"serde_json",
"sqlx",
"strum 0.27.2",
"tempfile",
"test-case",
"tokio",
"tokio-util",
"tower-http",
"tracing",
"url",
"uuid",
"wiremock",
]
[[package]] [[package]]
name = "goose-acp-macros" name = "goose-acp-macros"
version = "1.31.0" version = "1.31.0"
@ -4513,7 +4480,6 @@ dependencies = [
"etcetera 0.11.0", "etcetera 0.11.0",
"futures", "futures",
"goose", "goose",
"goose-acp",
"goose-mcp", "goose-mcp",
"indicatif", "indicatif",
"open", "open",

View file

@ -205,7 +205,7 @@ check-acp-schema: generate-acp-types
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
echo "🔍 Checking ACP schema and generated types are up-to-date..." echo "🔍 Checking ACP schema and generated types are up-to-date..."
if ! git diff --exit-code crates/goose-acp/acp-schema.json crates/goose-acp/acp-meta.json ui/sdk/src/generated/; then if ! git diff --exit-code crates/goose/acp-schema.json crates/goose/acp-meta.json ui/sdk/src/generated/; then
echo "" echo ""
echo "❌ ACP generated files are out of date!" echo "❌ ACP generated files are out of date!"
echo "" echo ""
@ -217,8 +217,8 @@ check-acp-schema: generate-acp-types
# Generate ACP JSON schema from Rust types # Generate ACP JSON schema from Rust types
generate-acp-schema: generate-acp-schema:
@echo "Generating ACP schema..." @echo "Generating ACP schema..."
cd crates/goose-acp && cargo run --bin generate-acp-schema cd crates/goose && cargo run --bin generate-acp-schema
@echo "ACP schema generated: crates/goose-acp/acp-schema.json, crates/goose-acp/acp-meta.json" @echo "ACP schema generated: crates/goose/acp-schema.json, crates/goose/acp-meta.json"
# Generate ACP TypeScript types from JSON schema (requires generate-acp-schema first) # Generate ACP TypeScript types from JSON schema (requires generate-acp-schema first)
generate-acp-types: generate-acp-schema generate-acp-types: generate-acp-schema

View file

@ -1,67 +0,0 @@
[package]
name = "goose-acp"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
description.workspace = true
[[bin]]
name = "generate-acp-schema"
path = "src/bin/generate_acp_schema.rs"
[features]
default = ["code-mode", "rustls-tls"]
code-mode = ["goose/code-mode"]
local-inference = ["goose/local-inference"]
rustls-tls = ["goose/rustls-tls", "goose-mcp/rustls-tls"]
native-tls = ["goose/native-tls", "goose-mcp/native-tls"]
[lints]
workspace = true
[dependencies]
goose = { path = "../goose", default-features = false }
goose-mcp = { path = "../goose-mcp", default-features = false }
rmcp = { workspace = true }
sacp = { workspace = true, features = ["unstable"] }
agent-client-protocol-schema = { workspace = true }
async-trait = { workspace = true }
anyhow = { workspace = true }
tokio = { workspace = true }
tokio-util = { workspace = true, features = ["compat", "rt"] }
tracing = { workspace = true }
serde_json = { workspace = true }
futures = { workspace = true }
regex = { workspace = true }
fs-err = "3"
strum = { workspace = true }
url = { workspace = true }
# HTTP server dependencies
axum = { workspace = true, features = ["ws"] }
serde = { workspace = true, features = ["derive"] }
tower-http = { workspace = true, features = ["cors"] }
async-stream = { workspace = true }
http-body-util = "0.1.3"
uuid = { workspace = true, features = ["v7"] }
schemars = { workspace = true, features = ["derive"] }
goose-acp-macros = { path = "../goose-acp-macros" }
goose-sdk = { path = "../goose-sdk" }
base64 = { workspace = true }
[dev-dependencies]
async-trait = { workspace = true }
goose-test-support = { path = "../goose-test-support" }
wiremock = { workspace = true }
tempfile = { workspace = true }
test-case = { workspace = true }
axum = { workspace = true }
rmcp = { workspace = true, features = ["transport-streamable-http-server"] }
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio-rustls", "sqlite"] }
[package.metadata.cargo-machete]
# Used to provide extras imports for sacp
ignored = ["agent-client-protocol-schema"]

View file

@ -1,9 +0,0 @@
#![recursion_limit = "256"]
mod adapters;
pub use goose_sdk::custom_requests;
mod fs;
pub mod server;
pub mod server_factory;
pub(crate) mod tools;
pub mod transport;

View file

@ -22,7 +22,6 @@ path = "src/bin/generate_manpages.rs"
[dependencies] [dependencies]
clap_mangen = "0.2.31" clap_mangen = "0.2.31"
goose = { path = "../goose", default-features = false } goose = { path = "../goose", default-features = false }
goose-acp = { path = "../goose-acp", default-features = false }
goose-mcp = { path = "../goose-mcp" } goose-mcp = { path = "../goose-mcp" }
rmcp = { workspace = true } rmcp = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
@ -71,8 +70,8 @@ winapi = { workspace = true }
[features] [features]
default = ["code-mode", "local-inference", "aws-providers", "telemetry", "otel", "rustls-tls"] default = ["code-mode", "local-inference", "aws-providers", "telemetry", "otel", "rustls-tls"]
code-mode = ["goose/code-mode", "goose-acp/code-mode"] code-mode = ["goose/code-mode"]
local-inference = ["goose/local-inference", "goose-acp/local-inference"] local-inference = ["goose/local-inference"]
aws-providers = ["goose/aws-providers"] aws-providers = ["goose/aws-providers"]
cuda = ["goose/cuda", "local-inference"] cuda = ["goose/cuda", "local-inference"]
telemetry = ["goose/telemetry"] telemetry = ["goose/telemetry"]

View file

@ -1064,8 +1064,9 @@ async fn handle_mcp_command(server: McpCommand) -> Result<()> {
} }
async fn handle_serve_command(host: String, port: u16, builtins: Vec<String>) -> Result<()> { async fn handle_serve_command(host: String, port: u16, builtins: Vec<String>) -> Result<()> {
use goose::acp::server_factory::{AcpServer, AcpServerFactoryConfig};
use goose::acp::transport::create_router;
use goose::config::paths::Paths; use goose::config::paths::Paths;
use goose_acp::server_factory::{AcpServer, AcpServerFactoryConfig};
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::Arc; use std::sync::Arc;
use tracing::info; use tracing::info;
@ -1081,7 +1082,7 @@ async fn handle_serve_command(host: String, port: u16, builtins: Vec<String>) ->
data_dir: Paths::data_dir(), data_dir: Paths::data_dir(),
config_dir: Paths::config_dir(), config_dir: Paths::config_dir(),
})); }));
let router = goose_acp::transport::create_router(server); let router = create_router(server);
let addr: SocketAddr = format!("{}:{}", host, port).parse()?; let addr: SocketAddr = format!("{}:{}", host, port).parse()?;
info!("Starting ACP server on {}", addr); info!("Starting ACP server on {}", addr);
@ -1766,7 +1767,7 @@ pub async fn cli() -> anyhow::Result<()> {
Some(Command::Doctor {}) => crate::commands::doctor::handle_doctor().await, Some(Command::Doctor {}) => crate::commands::doctor::handle_doctor().await,
Some(Command::Info { verbose }) => handle_info(verbose), Some(Command::Info { verbose }) => handle_info(verbose),
Some(Command::Mcp { server }) => handle_mcp_command(server).await, Some(Command::Mcp { server }) => handle_mcp_command(server).await,
Some(Command::Acp { builtins }) => goose_acp::server::run(builtins).await, Some(Command::Acp { builtins }) => goose::acp::server::run(builtins).await,
Some(Command::Serve { Some(Command::Serve {
host, host,
port, port,

View file

@ -82,7 +82,7 @@ serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
serde_urlencoded = "0.7" serde_urlencoded = "0.7"
jsonschema = "0.30.0" jsonschema = "0.30.0"
uuid = { workspace = true } uuid = { workspace = true, features = ["v7"] }
regex = { workspace = true } regex = { workspace = true }
async-trait = { workspace = true } async-trait = { workspace = true }
async-stream = { workspace = true } async-stream = { workspace = true }
@ -96,7 +96,7 @@ nanoid = "0.4"
sha2 = { workspace = true } sha2 = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
url = { workspace = true } url = { workspace = true }
axum = { workspace = true } axum = { workspace = true, features = ["ws"] }
webbrowser = { workspace = true } webbrowser = { workspace = true }
lazy_static = "1.5.0" lazy_static = "1.5.0"
tracing = { workspace = true } tracing = { workspace = true }
@ -190,6 +190,9 @@ pem = { version = "3", optional = true }
pkcs1 = { version = "0.7", default-features = false, features = ["pkcs8"], optional = true } pkcs1 = { version = "0.7", default-features = false, features = ["pkcs8"], optional = true }
pkcs8 = { version = "0.10", default-features = false, features = ["alloc"], optional = true } pkcs8 = { version = "0.10", default-features = false, features = ["alloc"], optional = true }
sec1 = { version = "0.7", default-features = false, features = ["der", "pkcs8"], optional = true } sec1 = { version = "0.7", default-features = false, features = ["der", "pkcs8"], optional = true }
goose-acp-macros = { version = "1.31.0", path = "../goose-acp-macros" }
tower-http = { workspace = true, features = ["cors"] }
http-body-util = "0.1.3"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
@ -222,6 +225,7 @@ opentelemetry_sdk = { workspace = true, features = ["testing"] }
goose-test-support = { path = "../goose-test-support" } goose-test-support = { path = "../goose-test-support" }
bytes.workspace = true bytes.workspace = true
http.workspace = true http.workspace = true
goose-mcp = { path = "../goose-mcp" }
[[example]] [[example]]
name = "agent" name = "agent"
@ -244,6 +248,10 @@ path = "src/bin/analyze_cli.rs"
name = "build_canonical_models" name = "build_canonical_models"
path = "src/providers/canonical/build_canonical_models.rs" path = "src/providers/canonical/build_canonical_models.rs"
[[bin]]
name = "generate-acp-schema"
path = "src/bin/generate_acp_schema.rs"
[package.metadata.cargo-machete] [package.metadata.cargo-machete]
ignored = [ ignored = [
@ -251,4 +259,6 @@ ignored = [
"winapi", "winapi",
# Used to provide extras imports for sacp # Used to provide extras imports for sacp
"agent-client-protocol-schema", "agent-client-protocol-schema",
# Used via http transport
"http-body-util",
] ]

View file

@ -1,13 +1,13 @@
use crate::tools::AcpAwareToolMeta; use crate::acp::tools::AcpAwareToolMeta;
use crate::agents::mcp_client::{Error as McpError, McpClientTrait};
use crate::agents::platform_extensions::developer::edit::{
resolve_path, string_replace, FileEditParams, FileReadParams, FileWriteParams,
};
use crate::agents::platform_extensions::developer::shell::{ShellParams, OUTPUT_LIMIT_BYTES};
use crate::agents::platform_extensions::developer::DeveloperClient;
use agent_client_protocol_schema::TerminalId; use agent_client_protocol_schema::TerminalId;
use async_trait::async_trait; use async_trait::async_trait;
use fs_err as fs; use fs_err as fs;
use goose::agents::mcp_client::{Error as McpError, McpClientTrait};
use goose::agents::platform_extensions::developer::edit::{
resolve_path, string_replace, FileEditParams, FileReadParams, FileWriteParams,
};
use goose::agents::platform_extensions::developer::shell::{ShellParams, OUTPUT_LIMIT_BYTES};
use goose::agents::platform_extensions::developer::DeveloperClient;
use rmcp::model::{CallToolResult, Content as RmcpContent, Tool, ToolAnnotations}; use rmcp::model::{CallToolResult, Content as RmcpContent, Tool, ToolAnnotations};
use sacp::schema::{ use sacp::schema::{
CreateTerminalRequest, Diff, KillTerminalRequest, ReadTextFileRequest, ReleaseTerminalRequest, CreateTerminalRequest, Diff, KillTerminalRequest, ReadTextFileRequest, ReleaseTerminalRequest,
@ -93,7 +93,7 @@ fn read_tool() -> Tool {
} }
impl AcpTools { impl AcpTools {
fn update_tool_call(&self, ctx: &goose::agents::ToolCallContext, fields: ToolCallUpdateFields) { fn update_tool_call(&self, ctx: &crate::agents::ToolCallContext, fields: ToolCallUpdateFields) {
if let Some(ref req_id) = ctx.tool_call_request_id { if let Some(ref req_id) = ctx.tool_call_request_id {
let _ = self let _ = self
.cx .cx
@ -125,7 +125,7 @@ impl AcpTools {
async fn acp_read( async fn acp_read(
&self, &self,
arguments: Option<rmcp::model::JsonObject>, arguments: Option<rmcp::model::JsonObject>,
ctx: &goose::agents::ToolCallContext, ctx: &crate::agents::ToolCallContext,
) -> Result<CallToolResult, McpError> { ) -> Result<CallToolResult, McpError> {
let params: FileReadParams = match Self::parse_args(arguments) { let params: FileReadParams = match Self::parse_args(arguments) {
Ok(p) => p, Ok(p) => p,
@ -150,7 +150,7 @@ impl AcpTools {
async fn acp_write( async fn acp_write(
&self, &self,
arguments: Option<rmcp::model::JsonObject>, arguments: Option<rmcp::model::JsonObject>,
ctx: &goose::agents::ToolCallContext, ctx: &crate::agents::ToolCallContext,
) -> Result<CallToolResult, McpError> { ) -> Result<CallToolResult, McpError> {
let params: FileWriteParams = match Self::parse_args(arguments) { let params: FileWriteParams = match Self::parse_args(arguments) {
Ok(p) => p, Ok(p) => p,
@ -187,7 +187,7 @@ impl AcpTools {
async fn acp_edit( async fn acp_edit(
&self, &self,
arguments: Option<rmcp::model::JsonObject>, arguments: Option<rmcp::model::JsonObject>,
ctx: &goose::agents::ToolCallContext, ctx: &crate::agents::ToolCallContext,
) -> Result<CallToolResult, McpError> { ) -> Result<CallToolResult, McpError> {
let params: FileEditParams = match Self::parse_args(arguments) { let params: FileEditParams = match Self::parse_args(arguments) {
Ok(p) => p, Ok(p) => p,
@ -240,7 +240,7 @@ impl AcpTools {
async fn acp_shell( async fn acp_shell(
&self, &self,
arguments: Option<rmcp::model::JsonObject>, arguments: Option<rmcp::model::JsonObject>,
ctx: &goose::agents::ToolCallContext, ctx: &crate::agents::ToolCallContext,
) -> Result<CallToolResult, McpError> { ) -> Result<CallToolResult, McpError> {
let params: ShellParams = match Self::parse_args(arguments) { let params: ShellParams = match Self::parse_args(arguments) {
Ok(p) => p, Ok(p) => p,
@ -404,7 +404,7 @@ impl McpClientTrait for AcpTools {
async fn call_tool( async fn call_tool(
&self, &self,
ctx: &goose::agents::ToolCallContext, ctx: &crate::agents::ToolCallContext,
name: &str, name: &str,
arguments: Option<rmcp::model::JsonObject>, arguments: Option<rmcp::model::JsonObject>,
cancellation_token: CancellationToken, cancellation_token: CancellationToken,

View file

@ -1,7 +1,14 @@
mod adapters;
mod common; mod common;
pub(crate) mod fs;
mod provider; mod provider;
pub mod server;
pub mod server_factory;
pub(crate) mod tools;
pub mod transport;
pub use common::{map_permission_response, PermissionDecision}; pub use common::{map_permission_response, PermissionDecision};
pub use goose_sdk::custom_requests;
pub use provider::{ pub use provider::{
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL, extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
}; };

View file

@ -1,37 +1,36 @@
use crate::custom_requests::*; use crate::acp::custom_requests::*;
use crate::fs::AcpTools; use crate::acp::fs::AcpTools;
use crate::tools::AcpAwareToolMeta; use crate::acp::tools::AcpAwareToolMeta;
use anyhow::Result; use crate::acp::{PermissionDecision, ACP_CURRENT_MODEL};
use fs_err as fs; use crate::agents::extension::{Envs, PLATFORM_EXTENSIONS};
use futures::future::BoxFuture; use crate::agents::mcp_client::McpClientTrait;
use goose::acp::{PermissionDecision, ACP_CURRENT_MODEL}; use crate::agents::platform_extensions::developer::DeveloperClient;
use goose::agents::extension::{Envs, PLATFORM_EXTENSIONS}; use crate::agents::{Agent, AgentConfig, ExtensionConfig, GoosePlatform, SessionConfig};
use goose::agents::mcp_client::McpClientTrait; use crate::config::base::CONFIG_YAML_NAME;
use goose::agents::platform_extensions::developer::DeveloperClient; use crate::config::extensions::get_enabled_extensions_with_config;
use goose::agents::{Agent, AgentConfig, ExtensionConfig, GoosePlatform, SessionConfig}; use crate::config::paths::Paths;
use goose::builtin_extension::register_builtin_extensions; use crate::config::permission::PermissionManager;
use goose::config::base::CONFIG_YAML_NAME; use crate::config::{Config, GooseMode};
use goose::config::extensions::get_enabled_extensions_with_config; use crate::conversation::message::{ActionRequiredData, Message, MessageContent};
use goose::config::paths::Paths;
use goose::config::permission::PermissionManager;
use goose::config::{Config, GooseMode};
use goose::conversation::message::{ActionRequiredData, Message, MessageContent};
#[cfg(feature = "local-inference")] #[cfg(feature = "local-inference")]
use goose::dictation::providers::transcribe_local; use crate::dictation::providers::transcribe_local;
use goose::dictation::providers::{ use crate::dictation::providers::{
all_providers, is_configured, transcribe_with_provider, DictationProvider, all_providers, is_configured, transcribe_with_provider, DictationProvider,
}; };
#[cfg(feature = "local-inference")] #[cfg(feature = "local-inference")]
use goose::dictation::whisper; use crate::dictation::whisper;
use goose::mcp_utils::ToolResult; use crate::mcp_utils::ToolResult;
use goose::permission::permission_confirmation::PrincipalType; use crate::permission::permission_confirmation::PrincipalType;
use goose::permission::{Permission, PermissionConfirmation}; use crate::permission::{Permission, PermissionConfirmation};
use goose::providers::base::Provider; use crate::providers::base::Provider;
use goose::providers::inventory::{ use crate::providers::inventory::{
ProviderInventoryEntry, ProviderInventoryService, RefreshSkipReason, ProviderInventoryEntry, ProviderInventoryService, RefreshSkipReason,
}; };
use goose::session::session_manager::SessionType; use crate::session::session_manager::SessionType;
use goose::session::{EnabledExtensionsState, Session, SessionManager}; use crate::session::{EnabledExtensionsState, Session, SessionManager};
use anyhow::Result;
use fs_err as fs;
use futures::future::BoxFuture;
use goose_acp_macros::custom_methods; use goose_acp_macros::custom_methods;
use rmcp::model::{CallToolResult, RawContent, ResourceContents, Role}; use rmcp::model::{CallToolResult, RawContent, ResourceContents, Role};
use sacp::schema::{ use sacp::schema::{
@ -69,7 +68,7 @@ use url::Url;
pub type AcpProviderFactory = Arc< pub type AcpProviderFactory = Arc<
dyn Fn( dyn Fn(
String, String,
goose::model::ModelConfig, crate::model::ModelConfig,
Vec<ExtensionConfig>, Vec<ExtensionConfig>,
) -> BoxFuture<'static, Result<Arc<dyn Provider>>> ) -> BoxFuture<'static, Result<Arc<dyn Provider>>>
+ Send + Send
@ -106,7 +105,7 @@ const ELEVENLABS_TRANSCRIPTION_MODEL: &str = "scribe_v1";
struct GooseAcpSession { struct GooseAcpSession {
agent: AgentHandle, agent: AgentHandle,
internal_session_id: String, internal_session_id: String,
tool_requests: HashMap<String, goose::conversation::message::ToolRequest>, tool_requests: HashMap<String, crate::conversation::message::ToolRequest>,
cancel_token: Option<CancellationToken>, cancel_token: Option<CancellationToken>,
/// Working directory set while the agent was still loading. /// Working directory set while the agent was still loading.
/// Applied once the agent becomes ready. /// Applied once the agent becomes ready.
@ -127,7 +126,7 @@ struct AgentSetupRequest {
mcp_servers: Vec<McpServer>, mcp_servers: Vec<McpServer>,
/// Pre-resolved provider name + model config (from config, no network). /// Pre-resolved provider name + model config (from config, no network).
/// When present the spawn skips re-deriving these from config. /// When present the spawn skips re-deriving these from config.
resolved_provider: Option<(String, goose::model::ModelConfig)>, resolved_provider: Option<(String, crate::model::ModelConfig)>,
/// Pre-instantiated provider reused from synchronous session initialization. /// Pre-instantiated provider reused from synchronous session initialization.
prebuilt_provider: Option<Arc<dyn Provider>>, prebuilt_provider: Option<Arc<dyn Provider>>,
} }
@ -140,7 +139,7 @@ pub struct GooseAcpAgent {
client_terminal: OnceCell<bool>, client_terminal: OnceCell<bool>,
config_dir: std::path::PathBuf, config_dir: std::path::PathBuf,
session_manager: Arc<SessionManager>, session_manager: Arc<SessionManager>,
thread_manager: Arc<goose::session::ThreadManager>, thread_manager: Arc<crate::session::ThreadManager>,
permission_manager: Arc<PermissionManager>, permission_manager: Arc<PermissionManager>,
goose_mode: GooseMode, goose_mode: GooseMode,
disable_session_naming: bool, disable_session_naming: bool,
@ -220,7 +219,7 @@ fn is_developer_file_tool(tool_name: &str) -> bool {
} }
fn extract_locations_from_meta( fn extract_locations_from_meta(
tool_response: &goose::conversation::message::ToolResponse, tool_response: &crate::conversation::message::ToolResponse,
) -> Option<Vec<ToolCallLocation>> { ) -> Option<Vec<ToolCallLocation>> {
let result = tool_response.tool_result.as_ref().ok()?; let result = tool_response.tool_result.as_ref().ok()?;
let meta = result.meta.as_ref()?; let meta = result.meta.as_ref()?;
@ -242,8 +241,8 @@ fn extract_locations_from_meta(
} }
fn extract_tool_locations( fn extract_tool_locations(
tool_request: &goose::conversation::message::ToolRequest, tool_request: &crate::conversation::message::ToolRequest,
tool_response: &goose::conversation::message::ToolResponse, tool_response: &crate::conversation::message::ToolResponse,
) -> Vec<ToolCallLocation> { ) -> Vec<ToolCallLocation> {
let mut locations = Vec::new(); let mut locations = Vec::new();
@ -385,7 +384,7 @@ fn summarize_tool_call(tool_name: &str, arguments: Option<&serde_json::Value>) -
if !s.is_empty() { if !s.is_empty() {
let first_line = s.lines().next().unwrap_or(&s); let first_line = s.lines().next().unwrap_or(&s);
if first_line.len() > 60 { if first_line.len() > 60 {
return Some(format!("{}", goose::utils::safe_truncate(first_line, 57))); return Some(format!("{}", crate::utils::safe_truncate(first_line, 57)));
} }
return Some(first_line.to_string()); return Some(first_line.to_string());
} }
@ -458,7 +457,7 @@ fn inventory_entry_to_dto(entry: ProviderInventoryEntry) -> ProviderInventoryEnt
} }
} }
fn provider_config_key_to_dto(key: goose::providers::base::ConfigKey) -> ProviderConfigKey { fn provider_config_key_to_dto(key: crate::providers::base::ConfigKey) -> ProviderConfigKey {
ProviderConfigKey { ProviderConfigKey {
name: key.name, name: key.name,
required: key.required, required: key.required,
@ -494,7 +493,7 @@ struct ProviderOptionEntry {
} }
async fn list_provider_entries(current_provider: Option<&str>) -> Vec<ProviderOptionEntry> { async fn list_provider_entries(current_provider: Option<&str>) -> Vec<ProviderOptionEntry> {
let mut providers = goose::providers::providers() let mut providers = crate::providers::providers()
.await .await
.into_iter() .into_iter()
.map(|(metadata, _)| ProviderOptionEntry { .map(|(metadata, _)| ProviderOptionEntry {
@ -548,7 +547,7 @@ fn session_provider_selection(session: &Session) -> &str {
async fn resolve_provider_and_model_from_config( async fn resolve_provider_and_model_from_config(
config: &Config, config: &Config,
goose_session: &Session, goose_session: &Session,
) -> Result<(String, goose::model::ModelConfig), String> { ) -> Result<(String, crate::model::ModelConfig), String> {
let global_provider = config.get_goose_provider().ok(); let global_provider = config.get_goose_provider().ok();
let provider_override = goose_session let provider_override = goose_session
.provider_name .provider_name
@ -563,17 +562,17 @@ async fn resolve_provider_and_model_from_config(
let model_config = match &goose_session.model_config { let model_config = match &goose_session.model_config {
Some(mc) => mc.clone(), Some(mc) => mc.clone(),
None if explicitly_switched => { None if explicitly_switched => {
let entry = goose::providers::get_from_registry(&provider_name) let entry = crate::providers::get_from_registry(&provider_name)
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
let default_model = &entry.metadata().default_model; let default_model = &entry.metadata().default_model;
goose::model::ModelConfig::new(default_model) crate::model::ModelConfig::new(default_model)
.map_err(|e| e.to_string())? .map_err(|e| e.to_string())?
.with_canonical_limits(&provider_name) .with_canonical_limits(&provider_name)
} }
None => { None => {
let model_id = config.get_goose_model().map_err(|e| e.to_string())?; let model_id = config.get_goose_model().map_err(|e| e.to_string())?;
goose::model::ModelConfig::new(&model_id) crate::model::ModelConfig::new(&model_id)
.map_err(|e| e.to_string())? .map_err(|e| e.to_string())?
.with_canonical_limits(&provider_name) .with_canonical_limits(&provider_name)
} }
@ -586,7 +585,7 @@ async fn resolve_provider_and_model_from_config(
async fn resolve_provider_and_model( async fn resolve_provider_and_model(
config_dir: &std::path::Path, config_dir: &std::path::Path,
goose_session: &Session, goose_session: &Session,
) -> Result<(String, goose::model::ModelConfig), String> { ) -> Result<(String, crate::model::ModelConfig), String> {
let config = let config =
Config::new(config_dir.join(CONFIG_YAML_NAME), "goose").map_err(|e| e.to_string())?; Config::new(config_dir.join(CONFIG_YAML_NAME), "goose").map_err(|e| e.to_string())?;
resolve_provider_and_model_from_config(&config, goose_session).await resolve_provider_and_model_from_config(&config, goose_session).await
@ -704,7 +703,7 @@ impl GooseAcpAgent {
disable_session_naming: bool, disable_session_naming: bool,
) -> Result<Self> { ) -> Result<Self> {
let session_manager = Arc::new(SessionManager::new(data_dir)); let session_manager = Arc::new(SessionManager::new(data_dir));
let thread_manager = Arc::new(goose::session::ThreadManager::new( let thread_manager = Arc::new(crate::session::ThreadManager::new(
session_manager.storage().clone(), session_manager.storage().clone(),
)); ));
let permission_manager = Arc::new(PermissionManager::new(config_dir.clone())); let permission_manager = Arc::new(PermissionManager::new(config_dir.clone()));
@ -733,7 +732,7 @@ impl GooseAcpAgent {
async fn create_provider( async fn create_provider(
&self, &self,
provider_name: &str, provider_name: &str,
model_config: goose::model::ModelConfig, model_config: crate::model::ModelConfig,
extensions: Vec<ExtensionConfig>, extensions: Vec<ExtensionConfig>,
) -> Result<Arc<dyn Provider>> { ) -> Result<Arc<dyn Provider>> {
(self.provider_factory)(provider_name.to_string(), model_config, extensions).await (self.provider_factory)(provider_name.to_string(), model_config, extensions).await
@ -741,7 +740,7 @@ impl GooseAcpAgent {
async fn prepare_session_init_config( async fn prepare_session_init_config(
&self, &self,
resolved: &Result<(String, goose::model::ModelConfig), String>, resolved: &Result<(String, crate::model::ModelConfig), String>,
mode_state: &SessionModeState, mode_state: &SessionModeState,
goose_session: &Session, goose_session: &Session,
) -> ( ) -> (
@ -1187,7 +1186,7 @@ impl GooseAcpAgent {
async fn handle_tool_request( async fn handle_tool_request(
&self, &self,
tool_request: &goose::conversation::message::ToolRequest, tool_request: &crate::conversation::message::ToolRequest,
session_id: &SessionId, session_id: &SessionId,
session: &mut GooseAcpSession, session: &mut GooseAcpSession,
cx: &ConnectionTo<Client>, cx: &ConnectionTo<Client>,
@ -1235,7 +1234,7 @@ impl GooseAcpAgent {
.map(|a| { .map(|a| {
let s = serde_json::to_string(a).unwrap_or_default(); let s = serde_json::to_string(a).unwrap_or_default();
if s.len() > 300 { if s.len() > 300 {
format!("{}", goose::utils::safe_truncate(&s, 300)) format!("{}", crate::utils::safe_truncate(&s, 300))
} else { } else {
s s
} }
@ -1316,7 +1315,7 @@ impl GooseAcpAgent {
async fn handle_tool_response( async fn handle_tool_response(
&self, &self,
tool_response: &goose::conversation::message::ToolResponse, tool_response: &crate::conversation::message::ToolResponse,
session_id: &SessionId, session_id: &SessionId,
session: &mut GooseAcpSession, session: &mut GooseAcpSession,
cx: &ConnectionTo<Client>, cx: &ConnectionTo<Client>,
@ -1539,7 +1538,7 @@ impl GooseAcpAgent {
.map(|s| s.to_string()); .map(|s| s.to_string());
// Create the Thread — this IS the ACP session from the client's perspective. // Create the Thread — this IS the ACP session from the client's perspective.
let thread_metadata = goose::session::ThreadMetadata { let thread_metadata = crate::session::ThreadMetadata {
provider_id: requested_provider.clone(), provider_id: requested_provider.clone(),
mode: Some(self.goose_mode.to_string()), mode: Some(self.goose_mode.to_string()),
..Default::default() ..Default::default()
@ -1665,7 +1664,7 @@ impl GooseAcpAgent {
builder = builder.provider_name(provider); builder = builder.provider_name(provider);
} }
if let Some(model) = model_name { if let Some(model) = model_name {
if let Ok(mc) = goose::model::ModelConfig::new(model) { if let Ok(mc) = crate::model::ModelConfig::new(model) {
builder = builder.model_config(mc); builder = builder.model_config(mc);
} }
} }
@ -1820,7 +1819,7 @@ impl GooseAcpAgent {
// so that handle_tool_response can extract file locations from the // so that handle_tool_response can extract file locations from the
// matching request. No GooseAcpSession required. // matching request. No GooseAcpSession required.
let mut replay_tool_requests = let mut replay_tool_requests =
HashMap::<String, goose::conversation::message::ToolRequest>::new(); HashMap::<String, crate::conversation::message::ToolRequest>::new();
let t_replay = std::time::Instant::now(); let t_replay = std::time::Instant::now();
let mut replay_notifications: u32 = 0; let mut replay_notifications: u32 = 0;
@ -2090,7 +2089,7 @@ impl GooseAcpAgent {
} }
match event { match event {
Ok(goose::agents::AgentEvent::Message(message)) => { Ok(crate::agents::AgentEvent::Message(message)) => {
self.thread_manager self.thread_manager
.append_message(&thread_id, Some(&internal_session_id), &message) .append_message(&thread_id, Some(&internal_session_id), &message)
.await .await
@ -2217,7 +2216,7 @@ impl GooseAcpAgent {
let provider_name = current_provider.get_name().to_string(); let provider_name = current_provider.get_name().to_string();
let extensions = let extensions =
EnabledExtensionsState::for_session(&self.session_manager, &internal_id, &config).await; EnabledExtensionsState::for_session(&self.session_manager, &internal_id, &config).await;
let model_config = goose::model::ModelConfig::new(model_id) let model_config = crate::model::ModelConfig::new(model_id)
.map_err(|e| { .map_err(|e| {
sacp::Error::invalid_params().data(format!("Invalid model config: {}", e)) sacp::Error::invalid_params().data(format!("Invalid model config: {}", e))
})? })?
@ -2279,7 +2278,7 @@ impl GooseAcpAgent {
async fn update_thread_metadata( async fn update_thread_metadata(
&self, &self,
thread_id: &str, thread_id: &str,
f: impl FnOnce(&mut goose::session::ThreadMetadata), f: impl FnOnce(&mut crate::session::ThreadMetadata),
) -> Result<(), sacp::Error> { ) -> Result<(), sacp::Error> {
self.thread_manager self.thread_manager
.update_metadata(thread_id, f) .update_metadata(thread_id, f)
@ -2418,7 +2417,7 @@ impl GooseAcpAgent {
current_model current_model
}; };
let model = model_name.unwrap_or(&default_model); let model = model_name.unwrap_or(&default_model);
let model_config = goose::model::ModelConfig::new(model) let model_config = crate::model::ModelConfig::new(model)
.map_err(|e| { .map_err(|e| {
sacp::Error::invalid_params().data(format!("Invalid model config: {}", e)) sacp::Error::invalid_params().data(format!("Invalid model config: {}", e))
})? })?
@ -2765,8 +2764,8 @@ impl GooseAcpAgent {
#[custom_method(GetExtensionsRequest)] #[custom_method(GetExtensionsRequest)]
async fn on_get_extensions(&self) -> Result<GetExtensionsResponse, sacp::Error> { async fn on_get_extensions(&self) -> Result<GetExtensionsResponse, sacp::Error> {
let extensions = goose::config::extensions::get_all_extensions(); let extensions = crate::config::extensions::get_all_extensions();
let warnings = goose::config::extensions::get_warnings(); let warnings = crate::config::extensions::get_warnings();
let extensions_json = extensions let extensions_json = extensions
.into_iter() .into_iter()
.map(|e| serde_json::to_value(&e)) .map(|e| serde_json::to_value(&e))
@ -2792,7 +2791,7 @@ impl GooseAcpAgent {
let extensions = EnabledExtensionsState::extensions_or_default( let extensions = EnabledExtensionsState::extensions_or_default(
Some(&session.extension_data), Some(&session.extension_data),
goose::config::Config::global(), crate::config::Config::global(),
); );
let extensions_json = extensions let extensions_json = extensions
@ -2838,9 +2837,9 @@ impl GooseAcpAgent {
let provider_id = provider_id.clone(); let provider_id = provider_id.clone();
tokio::spawn(async move { tokio::spawn(async move {
let result = async { let result = async {
let metadata = goose::providers::get_from_registry(&provider_id).await?; let metadata = crate::providers::get_from_registry(&provider_id).await?;
let model_config = let model_config =
goose::model::ModelConfig::new(&metadata.metadata().default_model)? crate::model::ModelConfig::new(&metadata.metadata().default_model)?
.with_canonical_limits(&provider_id); .with_canonical_limits(&provider_id);
let provider = let provider =
provider_factory(provider_id.clone(), model_config, Vec::new()).await?; provider_factory(provider_id.clone(), model_config, Vec::new()).await?;
@ -2894,7 +2893,7 @@ impl GooseAcpAgent {
})?; })?;
let response = match config.get_param::<serde_json::Value>(&req.key) { let response = match config.get_param::<serde_json::Value>(&req.key) {
Ok(value) => ReadConfigResponse { value }, Ok(value) => ReadConfigResponse { value },
Err(goose::config::ConfigError::NotFound(_)) => ReadConfigResponse { Err(crate::config::ConfigError::NotFound(_)) => ReadConfigResponse {
value: serde_json::Value::Null, value: serde_json::Value::Null,
}, },
Err(e) => return Err(sacp::Error::internal_error().data(e.to_string())), Err(e) => return Err(sacp::Error::internal_error().data(e.to_string())),
@ -3076,7 +3075,7 @@ impl GooseAcpAgent {
&self, &self,
req: CreateSourceRequest, req: CreateSourceRequest,
) -> Result<CreateSourceResponse, sacp::Error> { ) -> Result<CreateSourceResponse, sacp::Error> {
let source = goose::sources::create_source( let source = crate::sources::create_source(
req.source_type, req.source_type,
&req.name, &req.name,
&req.description, &req.description,
@ -3092,7 +3091,7 @@ impl GooseAcpAgent {
&self, &self,
req: ListSourcesRequest, req: ListSourcesRequest,
) -> Result<ListSourcesResponse, sacp::Error> { ) -> Result<ListSourcesResponse, sacp::Error> {
let sources = goose::sources::list_sources(req.source_type, req.project_dir.as_deref())?; let sources = crate::sources::list_sources(req.source_type, req.project_dir.as_deref())?;
Ok(ListSourcesResponse { sources }) Ok(ListSourcesResponse { sources })
} }
@ -3101,7 +3100,7 @@ impl GooseAcpAgent {
&self, &self,
req: UpdateSourceRequest, req: UpdateSourceRequest,
) -> Result<UpdateSourceResponse, sacp::Error> { ) -> Result<UpdateSourceResponse, sacp::Error> {
let source = goose::sources::update_source( let source = crate::sources::update_source(
req.source_type, req.source_type,
&req.name, &req.name,
&req.description, &req.description,
@ -3117,7 +3116,7 @@ impl GooseAcpAgent {
&self, &self,
req: DeleteSourceRequest, req: DeleteSourceRequest,
) -> Result<EmptyResponse, sacp::Error> { ) -> Result<EmptyResponse, sacp::Error> {
goose::sources::delete_source( crate::sources::delete_source(
req.source_type, req.source_type,
&req.name, &req.name,
req.global, req.global,
@ -3131,7 +3130,7 @@ impl GooseAcpAgent {
&self, &self,
req: ExportSourceRequest, req: ExportSourceRequest,
) -> Result<ExportSourceResponse, sacp::Error> { ) -> Result<ExportSourceResponse, sacp::Error> {
let (json, filename) = goose::sources::export_source( let (json, filename) = crate::sources::export_source(
req.source_type, req.source_type,
&req.name, &req.name,
req.global, req.global,
@ -3146,7 +3145,7 @@ impl GooseAcpAgent {
req: ImportSourcesRequest, req: ImportSourcesRequest,
) -> Result<ImportSourcesResponse, sacp::Error> { ) -> Result<ImportSourcesResponse, sacp::Error> {
let sources = let sources =
goose::sources::import_sources(&req.data, req.global, req.project_dir.as_deref())?; crate::sources::import_sources(&req.data, req.global, req.project_dir.as_deref())?;
Ok(ImportSourcesResponse { sources }) Ok(ImportSourcesResponse { sources })
} }
@ -3156,7 +3155,7 @@ impl GooseAcpAgent {
req: DictationTranscribeRequest, req: DictationTranscribeRequest,
) -> Result<DictationTranscribeResponse, sacp::Error> { ) -> Result<DictationTranscribeResponse, sacp::Error> {
use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
let config = goose::config::Config::global(); let config = crate::config::Config::global();
#[cfg(not(feature = "local-inference"))] #[cfg(not(feature = "local-inference"))]
if req.provider == "local" { if req.provider == "local" {
@ -3245,7 +3244,7 @@ impl GooseAcpAgent {
&self, &self,
_req: DictationConfigRequest, _req: DictationConfigRequest,
) -> Result<DictationConfigResponse, sacp::Error> { ) -> Result<DictationConfigResponse, sacp::Error> {
let config = goose::config::Config::global(); let config = crate::config::Config::global();
let mut providers = std::collections::HashMap::new(); let mut providers = std::collections::HashMap::new();
for def in all_providers() { for def in all_providers() {
@ -3294,7 +3293,7 @@ impl GooseAcpAgent {
) -> Result<DictationModelsListResponse, sacp::Error> { ) -> Result<DictationModelsListResponse, sacp::Error> {
#[cfg(feature = "local-inference")] #[cfg(feature = "local-inference")]
{ {
use goose::download_manager::{get_download_manager, DownloadStatus}; use crate::download_manager::{get_download_manager, DownloadStatus};
let manager = get_download_manager(); let manager = get_download_manager();
let models = whisper::available_models() let models = whisper::available_models()
@ -3326,7 +3325,7 @@ impl GooseAcpAgent {
) -> Result<EmptyResponse, sacp::Error> { ) -> Result<EmptyResponse, sacp::Error> {
#[cfg(feature = "local-inference")] #[cfg(feature = "local-inference")]
{ {
use goose::download_manager::get_download_manager; use crate::download_manager::get_download_manager;
let model = whisper::get_model(&_req.model_id) let model = whisper::get_model(&_req.model_id)
.ok_or_else(|| sacp::Error::invalid_params().data("Unknown model id"))?; .ok_or_else(|| sacp::Error::invalid_params().data("Unknown model id"))?;
@ -3339,7 +3338,7 @@ impl GooseAcpAgent {
model.url.to_string(), model.url.to_string(),
model.local_path(), model.local_path(),
Some(Box::new(move || { Some(Box::new(move || {
let config = goose::config::Config::global(); let config = crate::config::Config::global();
// Only auto-select this model if the user has no model // Only auto-select this model if the user has no model
// currently selected. This prevents silently switching // currently selected. This prevents silently switching
// the active model mid-session when a user downloads an // the active model mid-session when a user downloads an
@ -3381,7 +3380,7 @@ impl GooseAcpAgent {
) -> Result<DictationModelDownloadProgressResponse, sacp::Error> { ) -> Result<DictationModelDownloadProgressResponse, sacp::Error> {
#[cfg(feature = "local-inference")] #[cfg(feature = "local-inference")]
{ {
use goose::download_manager::get_download_manager; use crate::download_manager::get_download_manager;
let manager = get_download_manager(); let manager = get_download_manager();
let progress = let progress =
@ -3412,7 +3411,7 @@ impl GooseAcpAgent {
) -> Result<EmptyResponse, sacp::Error> { ) -> Result<EmptyResponse, sacp::Error> {
#[cfg(feature = "local-inference")] #[cfg(feature = "local-inference")]
{ {
use goose::download_manager::get_download_manager; use crate::download_manager::get_download_manager;
let manager = get_download_manager(); let manager = get_download_manager();
manager manager
@ -3485,7 +3484,7 @@ impl GooseAcpAgent {
} }
}; };
goose::config::Config::global() crate::config::Config::global()
.set_param(key, req.model_id) .set_param(key, req.model_id)
.map_err(|e| sacp::Error::internal_error().data(e.to_string()))?; .map_err(|e| sacp::Error::internal_error().data(e.to_string()))?;
@ -3875,18 +3874,18 @@ where
} }
pub async fn run(builtins: Vec<String>) -> Result<()> { pub async fn run(builtins: Vec<String>) -> Result<()> {
register_builtin_extensions(goose_mcp::BUILTIN_EXTENSIONS.clone());
info!("listening on stdio"); info!("listening on stdio");
let outgoing = tokio::io::stdout().compat_write(); let outgoing = tokio::io::stdout().compat_write();
let incoming = tokio::io::stdin().compat(); let incoming = tokio::io::stdin().compat();
let server = let server = crate::acp::server_factory::AcpServer::new(
crate::server_factory::AcpServer::new(crate::server_factory::AcpServerFactoryConfig { crate::acp::server_factory::AcpServerFactoryConfig {
builtins, builtins,
data_dir: Paths::data_dir(), data_dir: Paths::data_dir(),
config_dir: Paths::config_dir(), config_dir: Paths::config_dir(),
}); },
);
let agent = server.create_agent().await?; let agent = server.create_agent().await?;
serve(agent, incoming, outgoing).await serve(agent, incoming, outgoing).await
} }
@ -3894,7 +3893,7 @@ pub async fn run(builtins: Vec<String>) -> Result<()> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use goose::conversation::message::{ToolRequest, ToolResponse}; use crate::conversation::message::{ToolRequest, ToolResponse};
use rmcp::model::{CallToolRequestParams, Content as RmcpContent}; use rmcp::model::{CallToolRequestParams, Content as RmcpContent};
use sacp::schema::{ use sacp::schema::{
EnvVariable, HttpHeader, McpServer, McpServerHttp, McpServerSse, McpServerStdio, EnvVariable, HttpHeader, McpServer, McpServerHttp, McpServerSse, McpServerStdio,
@ -4109,14 +4108,14 @@ print(\"hello, world\")
description: "Mock".to_string(), description: "Mock".to_string(),
default_model: "unused".to_string(), default_model: "unused".to_string(),
configured: true, configured: true,
provider_type: goose::providers::base::ProviderType::Builtin, provider_type: crate::providers::base::ProviderType::Builtin,
config_keys: vec![], config_keys: vec![],
setup_steps: vec![], setup_steps: vec![],
supports_refresh: true, supports_refresh: true,
refreshing: false, refreshing: false,
models: models models: models
.into_iter() .into_iter()
.map(|id| goose::providers::inventory::InventoryModel { .map(|id| crate::providers::inventory::InventoryModel {
name: id.clone(), name: id.clone(),
id, id,
family: None, family: None,
@ -4287,7 +4286,7 @@ print(\"hello, world\")
session_type: SessionType::Acp, session_type: SessionType::Acp,
created_at: Default::default(), created_at: Default::default(),
updated_at: Default::default(), updated_at: Default::default(),
extension_data: goose::session::ExtensionData::default(), extension_data: crate::session::ExtensionData::default(),
total_tokens, total_tokens,
input_tokens, input_tokens,
output_tokens, output_tokens,

View file

@ -1,9 +1,8 @@
use crate::acp::server::{AcpProviderFactory, GooseAcpAgent};
use anyhow::Result; use anyhow::Result;
use std::sync::Arc; use std::sync::Arc;
use tracing::info; use tracing::info;
use crate::server::{AcpProviderFactory, GooseAcpAgent};
pub struct AcpServerFactoryConfig { pub struct AcpServerFactoryConfig {
pub builtins: Vec<String>, pub builtins: Vec<String>,
pub data_dir: std::path::PathBuf, pub data_dir: std::path::PathBuf,
@ -23,18 +22,18 @@ impl AcpServer {
let config_path = self let config_path = self
.config .config
.config_dir .config_dir
.join(goose::config::base::CONFIG_YAML_NAME); .join(crate::config::base::CONFIG_YAML_NAME);
let config = goose::config::Config::new(&config_path, "goose")?; let config = crate::config::Config::new(&config_path, "goose")?;
let goose_mode = config let goose_mode = config
.get_goose_mode() .get_goose_mode()
.unwrap_or(goose::config::GooseMode::Auto); .unwrap_or(crate::config::GooseMode::Auto);
let disable_session_naming = config.get_goose_disable_session_naming().unwrap_or(false); let disable_session_naming = config.get_goose_disable_session_naming().unwrap_or(false);
let provider_factory: AcpProviderFactory = let provider_factory: AcpProviderFactory =
Arc::new(move |provider_name, model_config, extensions| { Arc::new(move |provider_name, model_config, extensions| {
Box::pin(async move { Box::pin(async move {
goose::providers::create(&provider_name, model_config, extensions).await crate::providers::create(&provider_name, model_config, extensions).await
}) })
}); });

View file

@ -13,8 +13,8 @@ use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt};
use tracing::{error, info}; use tracing::{error, info};
use super::*; use super::*;
use crate::adapters::{ReceiverToAsyncRead, SenderToAsyncWrite}; use crate::acp::adapters::{ReceiverToAsyncRead, SenderToAsyncWrite};
use crate::server_factory::AcpServer; use crate::acp::server_factory::AcpServer;
pub(crate) struct HttpState { pub(crate) struct HttpState {
server: Arc<AcpServer>, server: Arc<AcpServer>,
@ -43,7 +43,8 @@ impl HttpState {
let read_stream = ReceiverToAsyncRead::new(to_agent_rx); let read_stream = ReceiverToAsyncRead::new(to_agent_rx);
let write_stream = SenderToAsyncWrite::new(from_agent_tx); let write_stream = SenderToAsyncWrite::new(from_agent_tx);
let fut = crate::server::serve(agent, read_stream.compat(), write_stream.compat_write()); let fut =
crate::acp::server::serve(agent, read_stream.compat(), write_stream.compat_write());
let handle = tokio::spawn(async move { let handle = tokio::spawn(async move {
if let Err(e) = fut.await { if let Err(e) = fut.await {
error!("ACP session error: {}", e); error!("ACP session error: {}", e);

View file

@ -18,7 +18,7 @@ use serde_json::Value;
use tokio::sync::{mpsc, Mutex}; use tokio::sync::{mpsc, Mutex};
use tower_http::cors::{Any, CorsLayer}; use tower_http::cors::{Any, CorsLayer};
use crate::server_factory::AcpServer; use crate::acp::server_factory::AcpServer;
pub(crate) const HEADER_SESSION_ID: &str = "Acp-Session-Id"; pub(crate) const HEADER_SESSION_ID: &str = "Acp-Session-Id";
pub(crate) const EVENT_STREAM_MIME_TYPE: &str = "text/event-stream"; pub(crate) const EVENT_STREAM_MIME_TYPE: &str = "text/event-stream";

View file

@ -11,8 +11,8 @@ use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt};
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
use super::{TransportSession, HEADER_SESSION_ID}; use super::{TransportSession, HEADER_SESSION_ID};
use crate::adapters::{ReceiverToAsyncRead, SenderToAsyncWrite}; use crate::acp::adapters::{ReceiverToAsyncRead, SenderToAsyncWrite};
use crate::server_factory::AcpServer; use crate::acp::server_factory::AcpServer;
pub(crate) struct WsState { pub(crate) struct WsState {
server: Arc<AcpServer>, server: Arc<AcpServer>,
@ -38,7 +38,8 @@ impl WsState {
let read_stream = ReceiverToAsyncRead::new(to_agent_rx); let read_stream = ReceiverToAsyncRead::new(to_agent_rx);
let write_stream = SenderToAsyncWrite::new(from_agent_tx); let write_stream = SenderToAsyncWrite::new(from_agent_tx);
let fut = crate::server::serve(agent, read_stream.compat(), write_stream.compat_write()); let fut =
crate::acp::server::serve(agent, read_stream.compat(), write_stream.compat_write());
let handle = tokio::spawn(async move { let handle = tokio::spawn(async move {
if let Err(e) = fut.await { if let Err(e) = fut.await {
error!("ACP WebSocket session error: {}", e); error!("ACP WebSocket session error: {}", e);

View file

@ -1,4 +1,4 @@
use goose_acp::server::GooseAcpAgent; use goose::acp::server::GooseAcpAgent;
use schemars::SchemaGenerator; use schemars::SchemaGenerator;
use serde_json::{json, Map, Value}; use serde_json::{json, Map, Value};
use std::collections::{BTreeSet, HashMap}; use std::collections::{BTreeSet, HashMap};

View file

@ -5,6 +5,7 @@ compile_error!("At least one of `rustls-tls` or `native-tls` features must be en
compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive"); compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive");
pub mod acp; pub mod acp;
pub use goose_sdk::custom_requests;
pub mod action_required_manager; pub mod action_required_manager;
pub mod agents; pub mod agents;
pub mod builtin_extension; pub mod builtin_extension;

View file

@ -2,16 +2,16 @@
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![allow(unused_attributes)] #![allow(unused_attributes)]
#[path = "../fixtures/mod.rs"] #[path = "../acp_fixtures/mod.rs"]
pub mod fixtures; pub mod fixtures;
use fixtures::{ use fixtures::{
assert_notifications, Connection, FsFixture, Notification, OpenAiFixture, PermissionDecision, assert_notifications, Connection, FsFixture, Notification, OpenAiFixture, PermissionDecision,
Session, SessionData, TerminalCall, TerminalFixture, TestConnectionConfig, Session, SessionData, TerminalCall, TerminalFixture, TestConnectionConfig,
}; };
use fs_err as fs; use fs_err as fs;
use goose::acp::server::AcpProviderFactory;
use goose::config::base::CONFIG_YAML_NAME; use goose::config::base::CONFIG_YAML_NAME;
use goose::config::GooseMode; use goose::config::GooseMode;
use goose_acp::server::AcpProviderFactory;
use goose_test_support::{McpFixture, FAKE_CODE, TEST_IMAGE_B64, TEST_MODEL}; use goose_test_support::{McpFixture, FAKE_CODE, TEST_IMAGE_B64, TEST_MODEL};
use sacp::schema::{ use sacp::schema::{
ListSessionsResponse, McpServer, McpServerHttp, ModelId, SessionInfo, SessionModeId, ListSessionsResponse, McpServer, McpServerHttp, ModelId, SessionInfo, SessionModeId,
@ -32,7 +32,7 @@ async fn new_basic_session<C: Connection>(config: TestConnectionConfig) -> Basic
let openai = OpenAiFixture::new( let openai = OpenAiFixture::new(
vec![( vec![(
r#"</info-msg>\nwhat is 1+1""#.into(), r#"</info-msg>\nwhat is 1+1""#.into(),
include_str!("../test_data/openai_basic.txt"), include_str!("../acp_test_data/openai_basic.txt"),
)], )],
expected_session_id.clone(), expected_session_id.clone(),
) )
@ -147,11 +147,11 @@ pub async fn run_config_mcp<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -198,11 +198,11 @@ pub async fn run_fs_read_text_file_true<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_fs_read_tool_call.txt"), include_str!("../acp_test_data/openai_fs_read_tool_call.txt"),
), ),
( (
r#""content":"test-read-content-12345""#.into(), r#""content":"test-read-content-12345""#.into(),
include_str!("../test_data/openai_fs_read_tool_result.txt"), include_str!("../acp_test_data/openai_fs_read_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -247,11 +247,11 @@ pub async fn run_fs_write_text_file_false<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_fs_write_tool_call.txt"), include_str!("../acp_test_data/openai_fs_write_tool_call.txt"),
), ),
( (
r#"Created /tmp/test_acp_write.txt"#.into(), r#"Created /tmp/test_acp_write.txt"#.into(),
include_str!("../test_data/openai_fs_write_tool_result.txt"), include_str!("../acp_test_data/openai_fs_write_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -295,11 +295,11 @@ pub async fn run_fs_write_text_file_true<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_fs_write_tool_call.txt"), include_str!("../acp_test_data/openai_fs_write_tool_call.txt"),
), ),
( (
r#"Created /tmp/test_acp_write.txt"#.into(), r#"Created /tmp/test_acp_write.txt"#.into(),
include_str!("../test_data/openai_fs_write_tool_result.txt"), include_str!("../acp_test_data/openai_fs_write_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -366,11 +366,11 @@ pub async fn run_load_mode<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -426,7 +426,7 @@ pub async fn run_load_model<C: Connection>() {
let openai = OpenAiFixture::new( let openai = OpenAiFixture::new(
vec![( vec![(
r#""model":"o4-mini""#.into(), r#""model":"o4-mini""#.into(),
include_str!("../test_data/openai_basic.txt"), include_str!("../acp_test_data/openai_basic.txt"),
)], )],
expected_session_id.clone(), expected_session_id.clone(),
) )
@ -460,19 +460,19 @@ pub async fn run_load_session_mcp<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -602,11 +602,11 @@ async fn run_mode_set_impl<C: Connection>(via: SetModeVia) {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -779,12 +779,12 @@ async fn run_model_set_impl<C: Connection>(via: SetModelVia) {
// Session B prompt with switched model // Session B prompt with switched model
( (
r#""model":"o4-mini""#.into(), r#""model":"o4-mini""#.into(),
include_str!("../test_data/openai_basic.txt"), include_str!("../acp_test_data/openai_basic.txt"),
), ),
// Session A prompt with default model // Session A prompt with default model
( (
format!(r#""model":"{TEST_MODEL}""#), format!(r#""model":"{TEST_MODEL}""#),
include_str!("../test_data/openai_basic.txt"), include_str!("../acp_test_data/openai_basic.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -919,11 +919,11 @@ pub async fn run_permission_persistence<C: Connection>() {
vec![ vec![
( (
prompt.to_string(), prompt.to_string(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -961,7 +961,7 @@ pub async fn run_prompt_basic<C: Connection>() {
let openai = OpenAiFixture::new( let openai = OpenAiFixture::new(
vec![( vec![(
r#"</info-msg>\nwhat is 1+1""#.into(), r#"</info-msg>\nwhat is 1+1""#.into(),
include_str!("../test_data/openai_basic.txt"), include_str!("../acp_test_data/openai_basic.txt"),
)], )],
expected_session_id.clone(), expected_session_id.clone(),
) )
@ -989,15 +989,15 @@ pub async fn run_prompt_codemode<C: Connection>() {
vec![ vec![
( (
format!(r#"</info-msg>\n{prompt}""#), format!(r#"</info-msg>\n{prompt}""#),
include_str!("../test_data/openai_builtin_search.txt"), include_str!("../acp_test_data/openai_builtin_search.txt"),
), ),
( (
r#"export async function getCode"#.into(), r#"export async function getCode"#.into(),
include_str!("../test_data/openai_builtin_execute.txt"), include_str!("../acp_test_data/openai_builtin_execute.txt"),
), ),
( (
r#"Created /tmp/result.txt"#.into(), r#"Created /tmp/result.txt"#.into(),
include_str!("../test_data/openai_builtin_final.txt"), include_str!("../acp_test_data/openai_builtin_final.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -1037,11 +1037,11 @@ pub async fn run_prompt_image<C: Connection>() {
( (
r#"</info-msg>\nUse the get_image tool and describe what you see in its result.""# r#"</info-msg>\nUse the get_image tool and describe what you see in its result.""#
.into(), .into(),
include_str!("../test_data/openai_image_tool_call.txt"), include_str!("../acp_test_data/openai_image_tool_call.txt"),
), ),
( (
r#""type":"image_url""#.into(), r#""type":"image_url""#.into(),
include_str!("../test_data/openai_image_tool_result.txt"), include_str!("../acp_test_data/openai_image_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -1081,7 +1081,7 @@ pub async fn run_prompt_image_attachment<C: Connection>() {
let openai = OpenAiFixture::new( let openai = OpenAiFixture::new(
vec![( vec![(
r#""type":"image_url""#.into(), r#""type":"image_url""#.into(),
include_str!("../test_data/openai_image_attachment.txt"), include_str!("../acp_test_data/openai_image_attachment.txt"),
)], )],
expected_session_id.clone(), expected_session_id.clone(),
) )
@ -1112,11 +1112,11 @@ pub async fn run_prompt_mcp<C: Connection>() {
vec![ vec![
( (
r#"</info-msg>\nUse the get_code tool and output only its result.""#.into(), r#"</info-msg>\nUse the get_code tool and output only its result.""#.into(),
include_str!("../test_data/openai_tool_call.txt"), include_str!("../acp_test_data/openai_tool_call.txt"),
), ),
( (
format!(r#""content":"{FAKE_CODE}""#), format!(r#""content":"{FAKE_CODE}""#),
include_str!("../test_data/openai_tool_result.txt"), include_str!("../acp_test_data/openai_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -1178,7 +1178,7 @@ pub async fn run_prompt_skill<C: Connection>() {
let openai = OpenAiFixture::new( let openai = OpenAiFixture::new(
vec![( vec![(
"skill-loaded-in-acp-session".to_string(), "skill-loaded-in-acp-session".to_string(),
include_str!("../test_data/openai_basic.txt"), include_str!("../acp_test_data/openai_basic.txt"),
)], )],
expected_session_id.clone(), expected_session_id.clone(),
) )
@ -1209,11 +1209,11 @@ pub async fn run_shell_terminal_false<C: Connection>() {
vec![ vec![
( (
prompt.clone(), prompt.clone(),
include_str!("../test_data/openai_shell_tool_call.txt"), include_str!("../acp_test_data/openai_shell_tool_call.txt"),
), ),
( (
SHELL_TEST_CONTENT.into(), SHELL_TEST_CONTENT.into(),
include_str!("../test_data/openai_shell_tool_result.txt"), include_str!("../acp_test_data/openai_shell_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),
@ -1252,11 +1252,11 @@ pub async fn run_shell_terminal_true<C: Connection>() {
vec![ vec![
( (
prompt.clone(), prompt.clone(),
include_str!("../test_data/openai_shell_tool_call.txt"), include_str!("../acp_test_data/openai_shell_tool_call.txt"),
), ),
( (
SHELL_TEST_CONTENT.into(), SHELL_TEST_CONTENT.into(),
include_str!("../test_data/openai_shell_tool_result.txt"), include_str!("../acp_test_data/openai_shell_tool_result.txt"),
), ),
], ],
expected_session_id.clone(), expected_session_id.clone(),

View file

@ -1,4 +1,5 @@
#[allow(dead_code)] #[allow(dead_code)]
#[path = "acp_common_tests/mod.rs"]
mod common_tests; mod common_tests;
use common_tests::fixtures::server::AcpServerConnection; use common_tests::fixtures::server::AcpServerConnection;
@ -6,10 +7,10 @@ use common_tests::fixtures::{
run_test, send_custom, Connection, PermissionDecision, Session, SessionData, run_test, send_custom, Connection, PermissionDecision, Session, SessionData,
TestConnectionConfig, TestConnectionConfig,
}; };
use goose::acp::server::AcpProviderFactory;
use goose::model::ModelConfig; use goose::model::ModelConfig;
use goose::providers::base::{MessageStream, Provider}; use goose::providers::base::{MessageStream, Provider};
use goose::providers::errors::ProviderError; use goose::providers::errors::ProviderError;
use goose_acp::server::AcpProviderFactory;
use goose_test_support::{EnforceSessionId, IgnoreSessionId}; use goose_test_support::{EnforceSessionId, IgnoreSessionId};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -238,11 +239,11 @@ fn test_developer_fs_requests_use_acp_session_id() {
( (
"Use the read tool to read /tmp/test_acp_read.txt and output only its contents." "Use the read tool to read /tmp/test_acp_read.txt and output only its contents."
.to_string(), .to_string(),
include_str!("test_data/openai_fs_read_tool_call.txt"), include_str!("acp_test_data/openai_fs_read_tool_call.txt"),
), ),
( (
r#""content":"test-read-content-12345""#.into(), r#""content":"test-read-content-12345""#.into(),
include_str!("test_data/openai_fs_read_tool_result.txt"), include_str!("acp_test_data/openai_fs_read_tool_result.txt"),
), ),
], ],
Arc::new(IgnoreSessionId), Arc::new(IgnoreSessionId),

View file

@ -3,6 +3,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use fs_err as fs; use fs_err as fs;
use goose::acp::server::{serve, AcpProviderFactory, GooseAcpAgent};
pub use goose::acp::{map_permission_response, PermissionDecision}; pub use goose::acp::{map_permission_response, PermissionDecision};
use goose::builtin_extension::register_builtin_extensions; use goose::builtin_extension::register_builtin_extensions;
use goose::config::paths::Paths; use goose::config::paths::Paths;
@ -11,7 +12,6 @@ use goose::providers::api_client::{ApiClient, AuthMethod as ApiAuthMethod};
use goose::providers::base::Provider; use goose::providers::base::Provider;
use goose::providers::openai::OpenAiProvider; use goose::providers::openai::OpenAiProvider;
use goose::session_context::SESSION_ID_HEADER; use goose::session_context::SESSION_ID_HEADER;
use goose_acp::server::{serve, AcpProviderFactory, GooseAcpAgent};
use goose_test_support::{ExpectedSessionId, TEST_MODEL}; use goose_test_support::{ExpectedSessionId, TEST_MODEL};
use sacp::schema::{ use sacp::schema::{
CreateTerminalResponse, KillTerminalResponse, ListSessionsResponse, McpServer, CreateTerminalResponse, KillTerminalResponse, ListSessionsResponse, McpServer,
@ -52,7 +52,7 @@ impl OpenAiFixture {
.respond_with( .respond_with(
ResponseTemplate::new(200) ResponseTemplate::new(200)
.insert_header("content-type", "application/json") .insert_header("content-type", "application/json")
.set_body_string(include_str!("../test_data/openai_models.json")), .set_body_string(include_str!("../acp_test_data/openai_models.json")),
) )
.mount(&mock_server) .mount(&mock_server)
.await; .await;

View file

@ -1,6 +1,7 @@
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[allow(dead_code)] #[allow(dead_code)]
#[path = "acp_common_tests/mod.rs"]
mod common_tests; mod common_tests;
use common_tests::fixtures::provider::AcpProviderConnection; use common_tests::fixtures::provider::AcpProviderConnection;
use common_tests::fixtures::run_test; use common_tests::fixtures::run_test;

View file

@ -1,4 +1,5 @@
#[allow(dead_code)] #[allow(dead_code)]
#[path = "acp_common_tests/mod.rs"]
mod common_tests; mod common_tests;
use common_tests::fixtures::run_test; use common_tests::fixtures::run_test;
use common_tests::fixtures::server::AcpServerConnection; use common_tests::fixtures::server::AcpServerConnection;

View file

@ -177,7 +177,7 @@ npm install
**Option 1: Auto-launch server (recommended)** **Option 1: Auto-launch server (recommended)**
The TUI will automatically start the goose-acp-server if you have it installed: The TUI will automatically start the goose acp server if you have it installed:
```bash ```bash
npm start npm start
@ -191,7 +191,7 @@ For servers that support the draft standard ACP over Streamable HTTP https://git
npm start -- --server http://HOST:PORT npm start -- --server http://HOST:PORT
# example server # example server
cargo run -p goose-acp --bin goose-acp-server cargo run -p goose-cli --bin goose -- serve
``` ```
### Single Prompt Mode ### Single Prompt Mode

View file

@ -57,7 +57,7 @@ npm link @aaif/goose-sdk
### Schema Generation ### Schema Generation
The TypeScript types are generated from Rust schemas defined in `crates/goose-acp`. The TypeScript types are generated from Rust schemas defined in `crates/goose`.
The build process: The build process:
1. Builds the `generate-acp-schema` Rust binary 1. Builds the `generate-acp-schema` Rust binary

View file

@ -16,8 +16,8 @@ import * as prettier from "prettier";
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename); const __dirname = dirname(__filename);
const ROOT = resolve(__dirname, "../.."); const ROOT = resolve(__dirname, "../..");
const SCHEMA_PATH = resolve(ROOT, "crates/goose-acp/acp-schema.json"); const SCHEMA_PATH = resolve(ROOT, "crates/goose/acp-schema.json");
const META_PATH = resolve(ROOT, "crates/goose-acp/acp-meta.json"); const META_PATH = resolve(ROOT, "crates/goose/acp-meta.json");
const OUTPUT_DIR = resolve(__dirname, "src/generated"); const OUTPUT_DIR = resolve(__dirname, "src/generated");
// Export the main function so it can be imported by build-schema.ts // Export the main function so it can be imported by build-schema.ts