Improve dependency hygiene (#9360)

Signed-off-by: jh-block <jhugo@block.xyz>
This commit is contained in:
jh-block 2026-05-26 18:09:03 +02:00 committed by GitHub
parent bf0da953d5
commit 27dc0d5f83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 950 additions and 1639 deletions

1999
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -20,88 +20,96 @@ uninlined_format_args = "allow"
string_slice = "warn" string_slice = "warn"
[workspace.dependencies] [workspace.dependencies]
rmcp = { version = "1.7.0", features = ["schemars", "auth"] } rmcp = { version = "1.4", default-features = false, features = ["schemars", "auth"] }
agent-client-protocol-schema = { version = "0.13", features = ["unstable"] } agent-client-protocol-schema = { version = "0.12", default-features = false, features = ["unstable"] }
agent-client-protocol = "0.12" agent-client-protocol = { version = "0.11", default-features = false }
arboard = "3" arboard = { version = "3", default-features = false }
anyhow = "1.0" anyhow = { version = "1.0.102", default-features = false, features = ["std"] }
async-stream = "0.3" async-stream = { version = "0.3.6", default-features = false }
async-trait = "0.1" async-trait = { version = "0.1.89", default-features = false }
axum = "0.8" axum = { version = "0.8", default-features = false, features = ["http1", "http2", "json", "tokio", "query"] }
base64 = "0.22.1" base64 = { version = "0.22.1", default-features = false, features = ["std"] }
bytes = "1" bytes = { version = "1.10.1", default-features = false, features = ["std"] }
chrono = { version = "0.4", features = ["serde"] } candle-core = { version = "0.10", default-features = false }
clap = { version = "4", features = ["derive"] } candle-nn = { version = "0.10", default-features = false }
dirs = "5.0" chrono = { version = "0.4.44", default-features = false, features = ["serde", "std"] }
dotenvy = "0.15" clap = { version = "4.1.14", default-features = false, features = ["derive", "std", "help", "suggestions", "usage", "color", "error-context"] }
env-lock = "1.0.1" dirs = { version = "5", default-features = false }
etcetera = "0.11.0" dotenvy = { version = "0.15.7", default-features = false }
fs2 = "0.4" env-lock = { version = "1", default-features = false }
futures = "0.3" etcetera = { version = "0.11", default-features = false }
http = "1.0" fs2 = { version = "0.4", default-features = false }
ignore = "0.4.25" futures = { version = "0.3.32", default-features = false, features = ["std"] }
include_dir = "0.7.4" http = { version = "1.1", default-features = false, features = ["std"] }
indoc = "2.0" ignore = { version = "0.4.12", default-features = false }
lru = "0.18" include_dir = { version = "0.7", default-features = false }
once_cell = "1.20" indoc = { version = "2", default-features = false }
rand = "0.8" keyring = { version = "3.6.3", default-features = false, features = ["vendored"] }
regex = "1.12" lru = { version = "0.16", default-features = false }
reqwest = { version = "0.13", default-features = false, features = ["multipart", "form"] } once_cell = { version = "1.21.3", default-features = false, features = ["std"] }
schemars = { default-features = false, version = "1.0" } rand = { version = "0.8.5", default-features = false, features = ["std"] }
serde = { version = "1.0", features = ["derive"] } regex = { version = "1.12.3", default-features = false, features = ["std"] }
serde_json = "1.0" reqwest = { version = "0.13.2", default-features = false, features = ["multipart", "form"] }
serde_yaml = "0.9" rustls = { version = "0.23.31", default-features = false, features = ["aws_lc_rs", "std"] }
shellexpand = "3.1" schemars = { version = "1.0.2", default-features = false, features = ["std"] }
strum = { version = "0.28", features = ["derive"] } serde = { version = "1.0.228", default-features = false, features = ["derive", "std"] }
tempfile = "3" serde_json = { version = "1.0.145", default-features = false, features = ["std"] }
thiserror = "1.0" serde_yaml = { version = "0.9.32", default-features = false }
tokio = { version = "1.49", features = ["full"] } shellexpand = { version = "3", default-features = false, features = ["base-0", "tilde"] }
tokio-stream = "0.1" strum = { version = "0.27.1", default-features = false, features = ["derive", "std"] }
tokio-util = "0.7" tempfile = { version = "3.10.1", default-features = false }
tower-http = "0.6.11" thiserror = { version = "1.0.49", default-features = false }
tracing = "0.1" tokio = { version = "1.48", default-features = false }
tracing-appender = "0.2" tokio-stream = { version = "0.1.16", default-features = false }
tracing-subscriber = "0.3" tokio-util = { version = "0.7.12", default-features = false }
urlencoding = "2.1" tower-http = { version = "0.6.8", default-features = false }
utoipa = "4.1" tracing = { version = "0.1.43", default-features = false, features = ["std"] }
uuid = { version = "1.23", features = ["v4"] } tracing-appender = { version = "0.2.1", default-features = false }
webbrowser = "1.2" tracing-futures = { version = "0.2.4", default-features = false, features = ["futures-03", "std", "std-future"] }
which = "8.0.0" tracing-subscriber = { version = "0.3.22", default-features = false, features = ["std"] }
winapi = { version = "0.3", features = ["wincred"] } urlencoding = { version = "2.1", default-features = false }
wiremock = "0.6" utoipa = { version = "4.2", default-features = false }
zip = { version = "^8.6", default-features = false, features = ["deflate"] } uuid = { version = "1.18", default-features = false, features = ["v4", "std"] }
serial_test = "3.2.0" webbrowser = { version = "1", default-features = false }
sha2 = "0.10" which = { version = "8", default-features = false, features = ["real-sys"] }
shell-words = "1.1.1" winapi = { version = "0.3.9", default-features = false, features = ["wincred", "std"] }
test-case = "3.3.1" wiremock = { version = "0.6", default-features = false }
url = "2.5.8" zip = { version = "8", default-features = false, features = ["deflate"] }
opentelemetry = "0.31" serial_test = { version = "3", default-features = false }
opentelemetry_sdk = { version = "0.31", features = ["metrics"] } sha2 = { version = "0.10.8", default-features = false, features = ["std"] }
opentelemetry-otlp = "0.31" shell-words = { version = "1", default-features = false, features = ["std"] }
opentelemetry-appender-tracing = { version = "0.31", features = ["experimental_span_attributes"] } test-case = { version = "3", default-features = false }
opentelemetry-stdout = { version = "0.31", features = ["trace", "metrics", "logs"] } url = { version = "2.5.4", default-features = false, features = ["std"] }
tracing-futures = { version = "0.2", features = ["futures-03"] } opentelemetry = { version = "0.32", default-features = false }
tracing-opentelemetry = "0.32" opentelemetry_sdk = { version = "0.32", default-features = false, features = ["metrics"] }
opentelemetry-http = { version = "0.32", default-features = false, features = ["internal-logs", "reqwest"] }
opentelemetry-otlp = { version = "0.32", default-features = false, features = ["http-proto", "internal-logs", "logs", "metrics", "reqwest-client", "trace"] }
opentelemetry-appender-tracing = { version = "0.32", default-features = false, features = ["experimental_span_attributes"] }
opentelemetry-stdout = { version = "0.32", default-features = false, features = ["trace", "metrics", "logs"] }
tracing-opentelemetry = { version = "0.33", default-features = false, features = ["metrics"] }
rayon = "1.12" rayon = { version = "1.10", default-features = false }
tree-sitter = "0.26" tree-sitter = { version = "0.26", default-features = false, features = ["std"] }
tree-sitter-go = "0.25" tree-sitter-go = { version = "0.25", default-features = false }
tree-sitter-java = "0.23" tree-sitter-java = { version = "0.23", default-features = false }
tree-sitter-javascript = "0.25" tree-sitter-javascript = { version = "0.25", default-features = false }
tree-sitter-kotlin-ng = "1.1" tree-sitter-kotlin-ng = { version = "1", default-features = false }
tree-sitter-python = "0.25" tree-sitter-python = { version = "0.25", default-features = false }
tree-sitter-ruby = "0.23" tree-sitter-ruby = { version = "0.23", default-features = false }
tree-sitter-rust = "0.24" tree-sitter-rust = { version = "0.24", default-features = false }
tree-sitter-swift = "0.7" tree-sitter-swift = { version = "0.7", default-features = false }
tree-sitter-typescript = "0.23" tree-sitter-typescript = { version = "0.23", default-features = false }
# llama-cpp-2 doesn't pin the version of its sys crate, so we do it here. it also has breaking changes in patch releases, so we use an exact version pin
llama-cpp-2 = { version = "=0.1.146", default-features = false, features = ["sampler", "mtmd"] }
llama-cpp-sys-2 = { version = "=0.1.146", default-features = false }
# These are needed because temporal_rs 0.1 (a transitive dep via PCTX) enables unstable features on icu_calendar without pinning the dependency version
# A fix is available in temporal_rs 0.2 but PCTX has not updated
# They are just here to pin the version, and can be removed if PCTX updates temporal_rs
icu_calendar = { version = "=2.1.1", default-features = false }
icu_locale = { version = "=2.1.1", default-features = false }
[patch.crates-io] [patch.crates-io]
v8 = { path = "vendor/v8" } v8 = { path = "vendor/v8" }
cudaforge = { git = "https://github.com/jbg/cudaforge", rev = "e7c1967340e40673db98dc9e17da0f04834a456f" } cudaforge = { git = "https://github.com/jbg/cudaforge", rev = "e7c1967340e40673db98dc9e17da0f04834a456f" }
# TODO: switch to released version in opentelemetry 0.32.0
# https://github.com/open-telemetry/opentelemetry-rust/issues/3408
opentelemetry = { git = "https://github.com/open-telemetry/opentelemetry-rust", rev = "345cd74a" }
opentelemetry_sdk = { git = "https://github.com/open-telemetry/opentelemetry-rust", rev = "345cd74a" }
opentelemetry-appender-tracing = { git = "https://github.com/open-telemetry/opentelemetry-rust", rev = "345cd74a" }
opentelemetry-otlp = { git = "https://github.com/open-telemetry/opentelemetry-rust", rev = "345cd74a" }
opentelemetry-stdout = { git = "https://github.com/open-telemetry/opentelemetry-rust", rev = "345cd74a" }

View file

@ -188,7 +188,7 @@ 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 && cargo run --bin generate-acp-schema cd crates/goose && cargo run --features code-mode,local-inference,aws-providers,telemetry,otel,rustls-tls,system-keyring --bin generate-acp-schema
@echo "ACP schema generated: crates/goose/acp-schema.json, crates/goose/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)

View file

@ -12,8 +12,8 @@ description.workspace = true
proc-macro = true proc-macro = true
[dependencies] [dependencies]
quote = "1" quote = { version = "1.0.40", default-features = false }
syn = { version = "2", features = ["full", "extra-traits"] } syn = { version = "2.0.104", default-features = false, features = ["full", "extra-traits"] }
[lints] [lints]
workspace = true workspace = true

View file

@ -20,15 +20,15 @@ name = "generate_manpages"
path = "src/bin/generate_manpages.rs" path = "src/bin/generate_manpages.rs"
[dependencies] [dependencies]
clap_mangen = "0.3.0" clap_mangen = { version = "0.2", default-features = false }
goose = { path = "../goose", default-features = false } goose = { path = "../goose", default-features = false }
goose-mcp = { path = "../goose-mcp" } goose-mcp = { path = "../goose-mcp", default-features = false }
rmcp = { workspace = true } rmcp = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
cliclack = "0.5.4" cliclack = { version = "0.5", default-features = false }
console = "0.16.1" console = { version = "0.16", default-features = false, features = ["std"] }
dotenvy = { workspace = true } dotenvy = { workspace = true }
bat = { version = "0.26.1", default-features = false, features = ["regex-onig"] } bat = { version = "0.26", default-features = false, features = ["regex-onig"] }
anyhow = { workspace = true } anyhow = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
@ -39,33 +39,34 @@ strum = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }
etcetera = { workspace = true } etcetera = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
rustyline = "18.0.0" rustyline = { version = "18", default-features = false, features = ["custom-bindings", "with-dirs", "with-file-history"] }
tracing = { workspace = true } tracing = { workspace = true }
chrono = { workspace = true } chrono = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "json", "time"] } tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "json", "time"] }
shlex = "2.0.1" shlex = { version = "1.3", default-features = false, features = ["std"] }
async-trait = { workspace = true } async-trait = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
regex = { workspace = true } regex = { workspace = true }
tar = "0.4.46" tar = { version = "0.4.46", default-features = false }
reqwest = { workspace = true, features = ["blocking"], default-features = false } reqwest = { workspace = true, features = ["blocking"] }
zip = { workspace = true } zip = { workspace = true }
bzip2 = "0.6" bzip2 = { version = "0.6", default-features = false, features = ["default"] }
webbrowser = { workspace = true } webbrowser = { workspace = true }
indicatif = "0.18.1" indicatif = { version = "0.18", default-features = false }
tokio-util = { workspace = true, features = ["compat", "rt"] } tokio-util = { workspace = true, features = ["compat", "rt"] }
anstream = "1.0.0" anstream = { version = "1", default-features = false, features = ["auto"] }
open = "5.3.5" open = { version = "5", default-features = false }
url = { workspace = true } url = { workspace = true }
urlencoding = { workspace = true } urlencoding = { workspace = true }
clap_complete = "4.6.5" clap_complete = { version = "4", default-features = false }
comfy-table = "7.2.2" comfy-table = { version = "7", default-features = false }
sha2 = { workspace = true } sha2 = { workspace = true }
sigstore-verify = { version = "=0.8.0", default-features = false } sigstore-verify = { version = "0.8", default-features = false, optional = true }
axum.workspace = true axum.workspace = true
clap_complete_nushell = "4.6.0" clap_complete_nushell = { version = "4", default-features = false }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
anstream = { version = "1", default-features = false, features = ["wincon"] }
winapi = { workspace = true } winapi = { workspace = true }
[features] [features]
@ -74,9 +75,11 @@ default = [
"local-inference", "local-inference",
"aws-providers", "aws-providers",
"telemetry", "telemetry",
"nostr",
"otel", "otel",
"rustls-tls", "rustls-tls",
"system-keyring", "system-keyring",
"update",
] ]
code-mode = ["goose/code-mode"] code-mode = ["goose/code-mode"]
local-inference = ["goose/local-inference"] local-inference = ["goose/local-inference"]
@ -84,20 +87,22 @@ aws-providers = ["goose/aws-providers"]
cuda = ["goose/cuda", "local-inference"] cuda = ["goose/cuda", "local-inference"]
vulkan = ["goose/vulkan", "local-inference"] vulkan = ["goose/vulkan", "local-inference"]
telemetry = ["goose/telemetry"] telemetry = ["goose/telemetry"]
nostr = ["goose/nostr"]
otel = ["goose/otel"] otel = ["goose/otel"]
system-keyring = ["goose/system-keyring"] system-keyring = ["goose/system-keyring"]
update = ["dep:sigstore-verify"]
portable-default = ["rustls-tls", "aws-providers", "telemetry", "otel"] portable-default = ["rustls-tls", "aws-providers", "telemetry", "otel"]
# disables the update command # disables the update command
disable-update = [] disable-update = []
rustls-tls = [ rustls-tls = [
"reqwest/rustls", "reqwest/rustls",
"sigstore-verify/rustls", "sigstore-verify?/rustls",
"goose/rustls-tls", "goose/rustls-tls",
"goose-mcp/rustls-tls", "goose-mcp/rustls-tls",
] ]
native-tls = [ native-tls = [
"reqwest/native-tls", "reqwest/native-tls",
"sigstore-verify/native-tls", "sigstore-verify?/native-tls",
"goose/native-tls", "goose/native-tls",
"goose-mcp/native-tls", "goose-mcp/native-tls",
] ]

View file

@ -935,6 +935,7 @@ enum Command {
}, },
/// Update the goose CLI version /// Update the goose CLI version
#[cfg(feature = "update")]
#[command(about = "Update the goose CLI version")] #[command(about = "Update the goose CLI version")]
Update { Update {
/// Update to canary version /// Update to canary version
@ -1269,6 +1270,7 @@ fn get_command_name(command: &Option<Command>) -> &'static str {
Some(Command::Run { .. }) => "run", Some(Command::Run { .. }) => "run",
Some(Command::Gateway { .. }) => "gateway", Some(Command::Gateway { .. }) => "gateway",
Some(Command::Schedule { .. }) => "schedule", Some(Command::Schedule { .. }) => "schedule",
#[cfg(feature = "update")]
Some(Command::Update { .. }) => "update", Some(Command::Update { .. }) => "update",
Some(Command::Recipe { .. }) => "recipe", Some(Command::Recipe { .. }) => "recipe",
Some(Command::Plugin { .. }) => "plugin", Some(Command::Plugin { .. }) => "plugin",
@ -2099,6 +2101,7 @@ pub async fn cli() -> anyhow::Result<()> {
} }
Some(Command::Gateway { command }) => handle_gateway_command(command).await, Some(Command::Gateway { command }) => handle_gateway_command(command).await,
Some(Command::Schedule { command }) => handle_schedule_command(command).await, Some(Command::Schedule { command }) => handle_schedule_command(command).await,
#[cfg(feature = "update")]
Some(Command::Update { Some(Command::Update {
canary, canary,
reconfigure, reconfigure,

View file

@ -10,4 +10,5 @@ pub mod schedule;
pub mod session; pub mod session;
pub mod term; pub mod term;
pub mod tui; pub mod tui;
#[cfg(feature = "update")]
pub mod update; pub mod update;

View file

@ -3,8 +3,11 @@ use anyhow::{Context, Result};
use cliclack::{confirm, multiselect, select}; use cliclack::{confirm, multiselect, select};
use etcetera::home_dir; use etcetera::home_dir;
#[cfg(feature = "nostr")]
use goose::config::Config; use goose::config::Config;
use goose::session::{generate_diagnostics, nostr_share, Session, SessionManager, SessionType}; #[cfg(feature = "nostr")]
use goose::session::nostr_share;
use goose::session::{generate_diagnostics, Session, SessionManager, SessionType};
use goose::utils::safe_truncate; use goose::utils::safe_truncate;
use regex::Regex; use regex::Regex;
use std::fs; use std::fs;
@ -218,7 +221,7 @@ pub async fn handle_session_export(
output_path: Option<PathBuf>, output_path: Option<PathBuf>,
format: String, format: String,
nostr: bool, nostr: bool,
relays: Vec<String>, #[cfg_attr(not(feature = "nostr"), allow(unused_variables))] relays: Vec<String>,
) -> Result<()> { ) -> Result<()> {
let session_manager = SessionManager::instance(); let session_manager = SessionManager::instance();
let session = match session_manager.get_session(&session_id, true).await { let session = match session_manager.get_session(&session_id, true).await {
@ -244,6 +247,7 @@ pub async fn handle_session_export(
_ => return Err(anyhow::anyhow!("Unsupported format: {}", format)), _ => return Err(anyhow::anyhow!("Unsupported format: {}", format)),
}; };
#[cfg(feature = "nostr")]
if nostr { if nostr {
if format != "json" { if format != "json" {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
@ -266,6 +270,10 @@ pub async fn handle_session_export(
println!("{}", share.deeplink); println!("{}", share.deeplink);
return Ok(()); return Ok(());
} }
#[cfg(not(feature = "nostr"))]
if nostr {
return Err(anyhow::anyhow!("goose was not built with nostr support"));
}
if let Some(output_path) = output_path { if let Some(output_path) = output_path {
fs::write(&output_path, output).with_context(|| { fs::write(&output_path, output).with_context(|| {
@ -281,7 +289,12 @@ pub async fn handle_session_export(
pub async fn handle_session_import(input: String, nostr: bool) -> Result<()> { pub async fn handle_session_import(input: String, nostr: bool) -> Result<()> {
let json = if nostr || input.starts_with("goose://sessions/nostr") { let json = if nostr || input.starts_with("goose://sessions/nostr") {
nostr_share::import_session_json_from_deeplink(&input).await? #[cfg(feature = "nostr")]
{
nostr_share::import_session_json_from_deeplink(&input).await?
}
#[cfg(not(feature = "nostr"))]
return Err(anyhow::anyhow!("goose was not built with nostr support"));
} else { } else {
fs::read_to_string(&input) fs::read_to_string(&input)
.with_context(|| format!("Failed to read session import file: {input}"))? .with_context(|| format!("Failed to read session import file: {input}"))?

View file

@ -12,6 +12,7 @@ description.workspace = true
workspace = true workspace = true
[features] [features]
default = []
rustls-tls = ["reqwest/rustls"] rustls-tls = ["reqwest/rustls"]
native-tls = ["reqwest/native-tls"] native-tls = ["reqwest/native-tls"]
@ -28,15 +29,15 @@ serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
schemars = { workspace = true } schemars = { workspace = true }
indoc = { workspace = true } indoc = { workspace = true }
reqwest = { workspace = true, features = ["json", "system-proxy"], default-features = false } reqwest = { workspace = true, features = ["json", "system-proxy"] }
chrono = { workspace = true } chrono = { workspace = true }
etcetera = { workspace = true } etcetera = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }
include_dir = { workspace = true } include_dir = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
lopdf = "0.40.0" lopdf = { version = "0.40", default-features = false }
docx-rs = "0.4.20" docx-rs = { version = "0.4.18", default-features = false, features = ["image"] }
image = { version = "0.25.10", features = ["jpeg"] } image = { version = "0.24.4", default-features = false, features = ["bmp", "dds", "dxt", "farbfeld", "gif", "hdr", "ico", "jpeg", "jpeg_rayon", "openexr", "png", "pnm", "tga", "tiff", "webp"] }
umya-spreadsheet = "2.2.3" umya-spreadsheet = { version = "2", default-features = false }
shell-words = { workspace = true } shell-words = { workspace = true }
process-wrap = { version = "9.1.0", features = ["std"] } process-wrap = { version = "9", default-features = false, features = ["std"] }

View file

@ -17,6 +17,7 @@ default = [
"local-inference", "local-inference",
"aws-providers", "aws-providers",
"telemetry", "telemetry",
"nostr",
"otel", "otel",
"rustls-tls", "rustls-tls",
"system-keyring", "system-keyring",
@ -27,6 +28,7 @@ aws-providers = ["goose/aws-providers"]
cuda = ["goose/cuda", "local-inference"] cuda = ["goose/cuda", "local-inference"]
vulkan = ["goose/vulkan", "local-inference"] vulkan = ["goose/vulkan", "local-inference"]
telemetry = ["goose/telemetry"] telemetry = ["goose/telemetry"]
nostr = ["goose/nostr"]
otel = ["goose/otel"] otel = ["goose/otel"]
system-keyring = ["goose/system-keyring"] system-keyring = ["goose/system-keyring"]
portable-default = ["rustls-tls", "aws-providers", "telemetry", "otel"] portable-default = ["rustls-tls", "aws-providers", "telemetry", "otel"]
@ -50,7 +52,7 @@ native-tls = [
[dependencies] [dependencies]
goose = { path = "../goose", default-features = false } goose = { path = "../goose", default-features = false }
goose-mcp = { path = "../goose-mcp" } goose-mcp = { path = "../goose-mcp", default-features = false }
rmcp = { workspace = true } rmcp = { workspace = true }
axum = { workspace = true, features = ["ws", "macros"] } axum = { workspace = true, features = ["ws", "macros"] }
tokio = { workspace = true } tokio = { workspace = true }
@ -66,31 +68,31 @@ anyhow = { workspace = true }
bytes = { workspace = true } bytes = { workspace = true }
http = { workspace = true } http = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
config = { version = "0.15.23", features = ["toml"] } config = { version = "0.15", default-features = false, features = ["toml"] }
thiserror = { workspace = true } thiserror = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
serde_yaml = { workspace = true } serde_yaml = { workspace = true }
utoipa = { workspace = true, features = ["axum_extras", "chrono"] } utoipa = { workspace = true, features = ["axum_extras", "chrono"] }
reqwest = { workspace = true, features = ["json", "blocking", "multipart", "system-proxy"], default-features = false } reqwest = { workspace = true, features = ["json", "blocking", "multipart", "system-proxy"] }
tokio-util = { workspace = true } tokio-util = { workspace = true }
serde_path_to_error = "0.1.20" serde_path_to_error = { version = "0.1.8", default-features = false }
tokio-tungstenite = { version = "0.29.0" } tokio-tungstenite = { version = "0.29", default-features = false, features = ["connect"] }
url = { workspace = true } url = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
hex = "0.4.3" hex = { version = "0.4.3", default-features = false, features = ["std"] }
subtle = "2.6" subtle = { version = "2.5", default-features = false, features = ["std"] }
socket2 = "0.6.1" socket2 = { version = "0.6", default-features = false }
fs2 = { workspace = true } fs2 = { workspace = true }
rustls = { version = "0.23", features = ["aws_lc_rs"], optional = true } rustls = { workspace = true, optional = true }
uuid = { workspace = true } uuid = { workspace = true }
rcgen = "0.14" rcgen = { version = "0.14", default-features = false, features = ["aws_lc_rs", "crypto", "pem"] }
axum-server = { version = "0.8.0" } axum-server = { version = "0.8", default-features = false }
aws-lc-rs = { version = "1.17.0", optional = true } aws-lc-rs = { version = "1.17", default-features = false, optional = true }
openssl = { version = "0.10", optional = true } openssl = { version = "0.10.66", default-features = false, optional = true }
pem = "3.0.6" pem = { version = "3.0.2", default-features = false, features = ["std"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winreg = { version = "0.56.0" } winreg = { version = "0.56", default-features = false }
[[bin]] [[bin]]
name = "goosed" name = "goosed"
@ -101,7 +103,7 @@ name = "generate_schema"
path = "src/bin/generate_schema.rs" path = "src/bin/generate_schema.rs"
[dev-dependencies] [dev-dependencies]
tower = "0.5.2" tower = { version = "0.5.2", default-features = false }
[package.metadata.cargo-machete] [package.metadata.cargo-machete]
ignored = [ ignored = [

View file

@ -708,7 +708,9 @@ async fn agent_add_extension(
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
Json(request): Json<AddExtensionRequest>, Json(request): Json<AddExtensionRequest>,
) -> Result<StatusCode, ErrorResponse> { ) -> Result<StatusCode, ErrorResponse> {
#[cfg(feature = "telemetry")]
let extension_name = request.config.name(); let extension_name = request.config.name();
let agent = state.get_agent(request.session_id.clone()).await?; let agent = state.get_agent(request.session_id.clone()).await?;
agent agent

View file

@ -11,6 +11,7 @@ use axum::{
}; };
use goose::agents::ExtensionConfig; use goose::agents::ExtensionConfig;
use goose::recipe::Recipe; use goose::recipe::Recipe;
#[cfg(feature = "nostr")]
use goose::session::nostr_share; use goose::session::nostr_share;
use goose::session::session_manager::{SessionInsights, SessionType}; use goose::session::session_manager::{SessionInsights, SessionType};
use goose::session::{EnabledExtensionsState, Session}; use goose::session::{EnabledExtensionsState, Session};
@ -51,6 +52,7 @@ pub struct ImportSessionRequest {
json: String, json: String,
} }
#[cfg_attr(not(feature = "nostr"), allow(dead_code))]
#[derive(Deserialize, ToSchema)] #[derive(Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ShareSessionNostrRequest { pub struct ShareSessionNostrRequest {
@ -67,6 +69,7 @@ pub struct ShareSessionNostrResponse {
relays: Vec<String>, relays: Vec<String>,
} }
#[cfg_attr(not(feature = "nostr"), allow(dead_code))]
#[derive(Deserialize, ToSchema)] #[derive(Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ImportSessionNostrRequest { pub struct ImportSessionNostrRequest {
@ -387,6 +390,7 @@ async fn import_session(
Ok(Json(session)) Ok(Json(session))
} }
#[cfg_attr(not(feature = "nostr"), allow(unused_variables))]
#[utoipa::path( #[utoipa::path(
post, post,
path = "/sessions/{session_id}/share/nostr", path = "/sessions/{session_id}/share/nostr",
@ -410,25 +414,32 @@ async fn share_session_nostr(
Path(session_id): Path<String>, Path(session_id): Path<String>,
Json(request): Json<ShareSessionNostrRequest>, Json(request): Json<ShareSessionNostrRequest>,
) -> Result<Json<ShareSessionNostrResponse>, StatusCode> { ) -> Result<Json<ShareSessionNostrResponse>, StatusCode> {
let exported = state #[cfg(feature = "nostr")]
.session_manager() {
.export_session(&session_id) let exported = state
.await .session_manager()
.map_err(|_| StatusCode::NOT_FOUND)?; .export_session(&session_id)
.await
.map_err(|_| StatusCode::NOT_FOUND)?;
let relays = nostr_share::resolve_relays(request.relays, goose::config::Config::global()); let relays = nostr_share::resolve_relays(request.relays, goose::config::Config::global());
let share = nostr_share::publish_session_json(&exported, relays) let share = nostr_share::publish_session_json(&exported, relays)
.await .await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(Json(ShareSessionNostrResponse { Ok(Json(ShareSessionNostrResponse {
deeplink: share.deeplink, deeplink: share.deeplink,
nevent: share.nevent, nevent: share.nevent,
event_id: share.event_id, event_id: share.event_id,
relays: share.relays, relays: share.relays,
})) }))
}
#[cfg(not(feature = "nostr"))]
Err(StatusCode::NOT_FOUND)
} }
#[cfg_attr(not(feature = "nostr"), allow(unused_variables))]
#[utoipa::path( #[utoipa::path(
post, post,
path = "/sessions/import/nostr", path = "/sessions/import/nostr",
@ -448,16 +459,22 @@ async fn import_session_nostr(
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
Json(request): Json<ImportSessionNostrRequest>, Json(request): Json<ImportSessionNostrRequest>,
) -> Result<Json<Session>, StatusCode> { ) -> Result<Json<Session>, StatusCode> {
let json = nostr_share::import_session_json_from_deeplink(&request.deeplink) #[cfg(feature = "nostr")]
.await {
.map_err(|_| StatusCode::BAD_REQUEST)?; let json = nostr_share::import_session_json_from_deeplink(&request.deeplink)
let session = state .await
.session_manager() .map_err(|_| StatusCode::BAD_REQUEST)?;
.import_session(&json, Some(SessionType::User)) let session = state
.await .session_manager()
.map_err(|_| StatusCode::BAD_REQUEST)?; .import_session(&json, Some(SessionType::User))
.await
.map_err(|_| StatusCode::BAD_REQUEST)?;
Ok(Json(session)) Ok(Json(session))
}
#[cfg(not(feature = "nostr"))]
Err(StatusCode::NOT_FOUND)
} }
#[utoipa::path( #[utoipa::path(

View file

@ -8,6 +8,7 @@ use utoipa::ToSchema;
use crate::state::AppState; use crate::state::AppState;
#[cfg_attr(not(feature = "telemetry"), allow(dead_code))]
#[derive(Debug, Deserialize, ToSchema)] #[derive(Debug, Deserialize, ToSchema)]
pub struct TelemetryEventRequest { pub struct TelemetryEventRequest {
pub event_name: String, pub event_name: String,
@ -15,6 +16,7 @@ pub struct TelemetryEventRequest {
pub properties: HashMap<String, serde_json::Value>, pub properties: HashMap<String, serde_json::Value>,
} }
#[cfg_attr(not(feature = "telemetry"), allow(unused_variables))]
#[utoipa::path( #[utoipa::path(
post, post,
path = "/telemetry/event", path = "/telemetry/event",
@ -27,15 +29,17 @@ async fn send_telemetry_event(
State(_state): State<Arc<AppState>>, State(_state): State<Arc<AppState>>,
Json(request): Json<TelemetryEventRequest>, Json(request): Json<TelemetryEventRequest>,
) -> StatusCode { ) -> StatusCode {
let event_name = request.event_name;
let properties = request.properties;
#[cfg(feature = "telemetry")] #[cfg(feature = "telemetry")]
tokio::spawn(async move { {
if let Err(e) = emit_event(&event_name, properties).await { let event_name = request.event_name;
tracing::debug!("Failed to send telemetry event: {}", e); let properties = request.properties;
}
}); tokio::spawn(async move {
if let Err(e) = emit_event(&event_name, properties).await {
tracing::debug!("Failed to send telemetry event: {}", e);
}
});
}
StatusCode::ACCEPTED StatusCode::ACCEPTED
} }

View file

@ -5,7 +5,9 @@ use goose::scheduler_trait::SchedulerTrait;
use goose::session::SessionManager; use goose::session::SessionManager;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, OnceLock}; use std::sync::Arc;
#[cfg(feature = "local-inference")]
use std::sync::OnceLock;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;

View file

@ -9,15 +9,7 @@ repository.workspace = true
description.workspace = true description.workspace = true
[features] [features]
default = [ default = []
"code-mode",
"local-inference",
"aws-providers",
"telemetry",
"otel",
"rustls-tls",
"system-keyring",
]
telemetry = [] telemetry = []
otel = [ otel = [
"dep:tracing-opentelemetry", "dep:tracing-opentelemetry",
@ -43,6 +35,7 @@ aws-providers = [
"dep:aws-smithy-types", "dep:aws-smithy-types",
"dep:aws-sdk-bedrockruntime", "dep:aws-sdk-bedrockruntime",
"dep:aws-sdk-sagemakerruntime", "dep:aws-sdk-sagemakerruntime",
"dep:smithy-transport-reqwest",
] ]
cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "llama-cpp-2/cuda"] cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "llama-cpp-2/cuda"]
vulkan = ["local-inference", "llama-cpp-2/vulkan"] vulkan = ["local-inference", "llama-cpp-2/vulkan"]
@ -50,6 +43,7 @@ rustls-tls = [
"dep:rustls", "dep:rustls",
"reqwest/rustls", "reqwest/rustls",
"rmcp/reqwest", "rmcp/reqwest",
"smithy-transport-reqwest?/rustls",
"sqlx/runtime-tokio-rustls", "sqlx/runtime-tokio-rustls",
"jsonwebtoken/aws_lc_rs", "jsonwebtoken/aws_lc_rs",
"oauth2/reqwest", "oauth2/reqwest",
@ -62,6 +56,7 @@ native-tls = [
"dep:sec1", "dep:sec1",
"reqwest/native-tls", "reqwest/native-tls",
"rmcp/reqwest-native-tls", "rmcp/reqwest-native-tls",
"smithy-transport-reqwest?/native-tls",
"sqlx/runtime-tokio-native-tls", "sqlx/runtime-tokio-native-tls",
"jsonwebtoken/rust_crypto", "jsonwebtoken/rust_crypto",
"oauth2/reqwest", "oauth2/reqwest",
@ -69,7 +64,7 @@ native-tls = [
] ]
system-keyring = ["dep:keyring"] system-keyring = ["dep:keyring"]
portable-default = ["rustls-tls", "aws-providers", "telemetry", "otel"] portable-default = ["rustls-tls", "aws-providers", "telemetry", "otel"]
nostr = ["dep:nostr", "dep:nostr-sdk"]
[lints] [lints]
workspace = true workspace = true
@ -89,30 +84,30 @@ anyhow = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
dirs = { workspace = true } dirs = { workspace = true }
reqwest = { workspace = true, features = ["json", "cookies", "gzip", "brotli", "deflate", "zstd", "charset", "http2", "stream", "blocking", "multipart", "system-proxy"], default-features = false } reqwest = { workspace = true, features = ["json", "cookies", "gzip", "brotli", "deflate", "zstd", "charset", "http2", "stream", "blocking", "multipart", "system-proxy"] }
tokio = { workspace = true } tokio = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
serde_urlencoded = "0.7" serde_urlencoded = { version = "0.7.1", default-features = false }
jsonschema = "0.30.0" jsonschema = { version = "0.30", default-features = false }
uuid = { workspace = true, features = ["v7"] } 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 }
minijinja = { version = "2.20.0", features = ["loader"] } minijinja = { version = "2.18", default-features = false, features = ["loader", "multi_template", "serde"] }
include_dir = { workspace = true } include_dir = { workspace = true }
tiktoken-rs = "0.11.0" tiktoken-rs = { version = "0.11", default-features = false }
chrono = { workspace = true } chrono = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
indoc = { workspace = true } indoc = { workspace = true }
nanoid = "0.5" nanoid = { version = "0.5", default-features = false }
sha2 = { workspace = true } sha2 = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
url = { workspace = true } url = { workspace = true }
axum = { workspace = true, features = ["ws"] } axum = { workspace = true, features = ["ws"] }
webbrowser = { workspace = true } webbrowser = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "json", "time"] } tracing-subscriber = { workspace = true, features = ["ansi", "env-filter", "fmt", "json", "time"] }
tracing-futures = { workspace = true } tracing-futures = { workspace = true }
tracing-opentelemetry = { workspace = true, optional = true } tracing-opentelemetry = { workspace = true, optional = true }
opentelemetry = { workspace = true, optional = true } opentelemetry = { workspace = true, optional = true }
@ -120,19 +115,19 @@ opentelemetry_sdk = { workspace = true, optional = true }
opentelemetry-appender-tracing = { workspace = true, optional = true } opentelemetry-appender-tracing = { workspace = true, optional = true }
opentelemetry-otlp = { workspace = true, optional = true } opentelemetry-otlp = { workspace = true, optional = true }
opentelemetry-stdout = { workspace = true, optional = true } opentelemetry-stdout = { workspace = true, optional = true }
keyring = { version = "3.6.2", features = ["vendored"], optional = true } keyring = { workspace = true, optional = true }
serde_yaml = { workspace = true } serde_yaml = { workspace = true }
strum = { workspace = true } strum = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
etcetera = { workspace = true } etcetera = { workspace = true }
fs-err = "3" fs-err = { version = "3.1", default-features = false }
goose-sdk = { path = "../goose-sdk" } goose-sdk = { path = "../goose-sdk", default-features = false }
rand = { workspace = true } rand = { workspace = true }
utoipa = { workspace = true, features = ["chrono"] } utoipa = { workspace = true, features = ["chrono"] }
tokio-cron-scheduler = "0.15.1" tokio-cron-scheduler = { version = "0.15", default-features = false }
urlencoding = { workspace = true } urlencoding = { workspace = true }
v_htmlescape = "0.15" v_htmlescape = { version = "0.17", default-features = false, features = ["std"] }
sqlx = { version = "0.8", default-features = false, features = [ sqlx = { version = "0.8.5", default-features = false, features = [
"sqlite", "sqlite",
"chrono", "chrono",
"json", "json",
@ -141,43 +136,46 @@ sqlx = { version = "0.8", default-features = false, features = [
] } ] }
# For Bedrock provider (optional, behind "aws-providers" feature) # For Bedrock provider (optional, behind "aws-providers" feature)
aws-config = { version = "=1.8.16", features = ["behavior-version-latest"], optional = true } aws-config = { version = "1.6", default-features = false, features = ["credentials-process", "rt-tokio", "sso", "behavior-version-latest"], optional = true }
aws-smithy-types = { version = "=1.4.8", optional = true } aws-smithy-types = { version = "1.3.4", default-features = false, features = ["rt-tokio"], optional = true }
aws-sdk-bedrockruntime = { version = "=1.131.0", default-features = false, features = ["default-https-client", "rt-tokio"], optional = true } aws-sdk-bedrockruntime = { version = "1.119", default-features = false, features = ["rt-tokio"], optional = true }
smithy-transport-reqwest = { version = "0.1", default-features = false, features = ["http2", "system-proxy"], optional = true }
# For SageMaker TGI provider (optional, behind "aws-providers" feature) # For SageMaker TGI provider (optional, behind "aws-providers" feature)
aws-sdk-sagemakerruntime = { version = "1.102.0", default-features = false, features = ["default-https-client", "rt-tokio"], optional = true } aws-sdk-sagemakerruntime = { version = "1.64", default-features = false, features = ["rt-tokio"], optional = true }
# For GCP Vertex AI provider auth # For GCP Vertex AI provider auth
jsonwebtoken = { version = "10.4.0", default-features = false, features = ["use_pem"] } jsonwebtoken = { version = "10.2", default-features = false, features = ["use_pem"] }
blake3 = "1.8" blake3 = { version = "1", default-features = false, features = ["std"] }
fs2 = { workspace = true } fs2 = { workspace = true }
tokio-stream = { workspace = true, features = ["io-util"] } tokio-stream = { workspace = true, features = ["io-util"] }
tempfile.workspace = true tempfile = { workspace = true }
dashmap = "6.2" dashmap = { version = "6", default-features = false }
ahash = "0.8" ahash = { version = "0.8.11", default-features = false, features = ["std"] }
tokio-util = { workspace = true, features = ["compat"] } tokio-util = { workspace = true, features = ["compat"] }
agent-client-protocol-schema = { workspace = true } agent-client-protocol-schema = { workspace = true }
agent-client-protocol = { workspace = true, features = ["unstable"] } agent-client-protocol = { workspace = true, features = ["unstable"] }
unicode-normalization = "0.1" unicode-normalization = { version = "0.1.22", default-features = false, features = ["std"] }
# For local Whisper transcription (optional, behind "local-inference" feature) # For local Whisper transcription (optional, behind "local-inference" feature)
candle-core = { version = "0.10.2", default-features = false, optional = true } candle-core = { workspace = true, optional = true }
candle-nn = { version = "0.10.2", default-features = false, optional = true } candle-nn = { workspace = true, optional = true }
candle-transformers = { version = "0.10.2", default-features = false, optional = true } candle-transformers = { version = "0.10", default-features = false, optional = true }
byteorder = { version = "1.5.0", optional = true } byteorder = { version = "1.5", default-features = false, features = ["std"], optional = true }
tokenizers = { version = "0.21.0", default-features = false, features = ["onig"], optional = true } tokenizers = { version = "0.21", default-features = false, features = ["onig"], optional = true }
symphonia = { version = "0.5", features = ["all"], optional = true } symphonia = { version = "0.5", default-features = false, features = ["aac", "adpcm", "alac", "isomp4", "mkv", "mp3", "pcm", "vorbis", "wav"], optional = true }
rubato = { version = "0.16", optional = true } rubato = { version = "0.16", default-features = false, optional = true }
zip = { workspace = true } zip = { workspace = true }
sys-info = "0.9" sys-info = { version = "0.9", default-features = false }
llama-cpp-2 = { workspace = true, optional = true }
schemars = { workspace = true, features = [ schemars = { workspace = true, features = [
"derive", "derive",
] } ] }
shellexpand = { workspace = true } shellexpand = { workspace = true }
indexmap = "2.14.0" indexmap = { version = "2.9", default-features = false, features = ["std"] }
ignore = { workspace = true } ignore = { workspace = true }
rayon = { workspace = true } rayon = { workspace = true }
tree-sitter = { workspace = true } tree-sitter = { workspace = true }
@ -191,59 +189,64 @@ tree-sitter-rust = { workspace = true }
tree-sitter-swift = { workspace = true } tree-sitter-swift = { workspace = true }
tree-sitter-typescript = { workspace = true } tree-sitter-typescript = { workspace = true }
which = { workspace = true } which = { workspace = true }
pctx_code_mode = { version = "^0.3.0", optional = true } pulldown-cmark = { version = "0.13", default-features = false }
pulldown-cmark = "0.13.4" encoding_rs = { version = "0.8.35", default-features = false }
llama-cpp-2 = { version = "0.1.145", features = ["sampler", "mtmd"], optional = true } pastey = { version = "0.2", default-features = false }
encoding_rs = "0.8.35"
pastey = "0.2.3"
shell-words = { workspace = true } shell-words = { workspace = true }
pem = { version = "3", optional = true } pem = { version = "3.0.2", default-features = false, features = ["std"], optional = true }
pkcs1 = { version = "0.7", default-features = false, features = ["pkcs8"], optional = true } pkcs1 = { version = "0.7.5", default-features = false, features = ["pkcs8", "std"], optional = true }
pkcs8 = { version = "0.10", default-features = false, features = ["alloc"], optional = true } pkcs8 = { version = "0.10.2", default-features = false, features = ["alloc", "std"], optional = true }
sec1 = { version = "0.7", default-features = false, features = ["der", "pkcs8"], optional = true } sec1 = { version = "0.7", default-features = false, features = ["der", "pkcs8", "std"], optional = true }
goose-acp-macros = { path = "../goose-acp-macros" } goose-acp-macros = { path = "../goose-acp-macros", default-features = false }
tower-http = { workspace = true, features = ["cors"] } tower-http = { workspace = true, features = ["cors"] }
http-body-util = "0.1.3" http-body-util = { version = "0.1.2", default-features = false }
tracing-appender.workspace = true tracing-appender = { workspace = true }
process-wrap = { version = "9.1.0", features = ["std"] } process-wrap = { version = "9", default-features = false, features = ["std"] }
nostr = { version = "0.44.3", features = ["nip44"] } nostr = { version = "0.44", default-features = false, features = ["nip44", "std"], optional = true }
nostr-sdk = { version = "0.44.1", features = ["nip44"] } nostr-sdk = { version = "0.44", default-features = false, features = ["nip44"], optional = true }
rustls = { version = "0.23", features = ["aws_lc_rs"], optional = true } rustls = { workspace = true, optional = true }
pctx_code_mode = { version = "0.3", default-features = false, optional = true }
# These are needed because temporal_rs 0.1 (a transitive dep via PCTX) enables unstable features on icu_calendar without pinning the dependency version
# A fix is available in temporal_rs 0.2 but PCTX has not updated
# They are just here to pin the version, and can be removed if PCTX updates temporal_rs
icu_calendar = { version = "=2.1.1", default-features = false }
icu_locale = { version = "=2.1.1", default-features = false }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = { workspace = true } winapi = { workspace = true }
keyring = { version = "3.6.2", features = ["windows-native"], optional = true } keyring = { workspace = true, features = ["windows-native"], optional = true }
# Platform-specific GPU acceleration for Whisper and local inference # Platform-specific GPU acceleration for Whisper and local inference
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
candle-core = { version = "0.10.2", default-features = false, features = ["metal"], optional = true } candle-core = { workspace = true, features = ["metal"], optional = true }
candle-nn = { version = "0.10.2", default-features = false, features = ["metal"], optional = true } candle-nn = { workspace = true, features = ["metal"], optional = true }
llama-cpp-2 = { version = "0.1.145", features = ["sampler", "metal", "mtmd"], optional = true } llama-cpp-2 = { workspace = true, features = ["sampler", "metal", "mtmd"], optional = true }
keyring = { version = "3.6.2", features = ["apple-native"], optional = true } keyring = { workspace = true, features = ["apple-native"], optional = true }
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
keyring = { version = "3.6.2", features = ["sync-secret-service"], optional = true } keyring = { workspace = true, features = ["sync-secret-service"], optional = true }
libc = "0.2.186" libc = { version = "0.2.182", default-features = false, features = ["std"] }
[dev-dependencies] [dev-dependencies]
serial_test = { workspace = true } serial_test = { workspace = true }
mockall = "0.14.0" mockall = { version = "0.13", default-features = false }
wiremock = { workspace = true } wiremock = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
tokio-util = { workspace = true, features = ["compat"] } tokio-util = { workspace = true, features = ["compat"] }
dotenvy = { workspace = true } dotenvy = { workspace = true }
ctor = "1.0.6" ctor = { version = "0.2", default-features = false }
test-case = { workspace = true } test-case = { workspace = true }
env-lock = { workspace = true } env-lock = { workspace = true }
rmcp = { workspace = true, features = ["transport-streamable-http-server"] } rmcp = { workspace = true, features = ["transport-streamable-http-server"] }
opentelemetry_sdk = { workspace = true, features = ["testing"] } opentelemetry_sdk = { workspace = true, features = ["testing"] }
goose-test-support = { path = "../goose-test-support" } goose-test-support = { path = "../goose-test-support", default-features = false }
bytes.workspace = true bytes = { workspace = true }
http.workspace = true http = { workspace = true }
goose-mcp = { path = "../goose-mcp" } goose-mcp = { path = "../goose-mcp", default-features = false }
insta = "1.47.2" insta = { version = "1", default-features = false }
dtor = "1.0.3" dtor = { version = "1.0.3", default-features = false, features = ["proc_macro"] }
[[example]] [[example]]
name = "agent" name = "agent"
@ -271,12 +274,11 @@ name = "generate-acp-schema"
path = "src/bin/generate_acp_schema.rs" path = "src/bin/generate_acp_schema.rs"
[package.metadata.cargo-machete] [package.metadata.cargo-machete]
ignored = [ ignored = [
# Used only on windows # Used only on windows
"winapi", "winapi",
# Used to provide extras imports for agent-client-protocol
"agent-client-protocol-schema", # Included only to pin version
# Used via http transport "icu_calendar",
"http-body-util", "icu_locale",
] ]

View file

@ -1,6 +1,3 @@
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled");
#[cfg(all(feature = "rustls-tls", feature = "native-tls"))] #[cfg(all(feature = "rustls-tls", feature = "native-tls"))]
compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive"); compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive");

View file

@ -1,6 +1,6 @@
use opentelemetry::trace::TracerProvider; use opentelemetry::trace::TracerProvider;
use opentelemetry::{global, KeyValue}; use opentelemetry::{global, KeyValue};
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; use opentelemetry_appender_tracing::layer::{OpenTelemetryTracingBridge, TracingSpanAttributes};
use opentelemetry_sdk::logs::{SdkLogger, SdkLoggerProvider}; use opentelemetry_sdk::logs::{SdkLogger, SdkLoggerProvider};
use opentelemetry_sdk::metrics::{SdkMeterProvider, Temporality}; use opentelemetry_sdk::metrics::{SdkMeterProvider, Temporality};
use opentelemetry_sdk::propagation::TraceContextPropagator; use opentelemetry_sdk::propagation::TraceContextPropagator;
@ -242,7 +242,7 @@ fn create_otlp_logs_layer() -> OtlpResult<OtlpLogsLayer> {
}; };
let bridge = OpenTelemetryTracingBridge::builder(&logger_provider) let bridge = OpenTelemetryTracingBridge::builder(&logger_provider)
.with_span_attribute_allowlist(["session.id"]) .with_tracing_span_attributes(TracingSpanAttributes::allowlist(["session.id"]))
.build(); .build();
*LOGGER_PROVIDER.lock().unwrap_or_else(|e| e.into_inner()) = Some(logger_provider); *LOGGER_PROVIDER.lock().unwrap_or_else(|e| e.into_inner()) = Some(logger_provider);

View file

@ -4,10 +4,13 @@ use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use reqwest::{ use reqwest::{
header::{HeaderMap, HeaderName, HeaderValue}, header::{HeaderMap, HeaderName, HeaderValue},
Certificate, Client, Identity, Response, StatusCode, Client, Response, StatusCode,
}; };
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
use reqwest::{Certificate, Identity};
use serde_json::Value; use serde_json::Value;
use std::fmt; use std::fmt;
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
use std::fs::read_to_string; use std::fs::read_to_string;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
@ -113,7 +116,8 @@ impl TlsConfig {
self.client_identity.is_some() || self.ca_cert_path.is_some() self.client_identity.is_some() || self.ca_cert_path.is_some()
} }
pub fn load_identity(&self) -> Result<Option<Identity>> { #[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
fn load_identity(&self) -> Result<Option<Identity>> {
if let Some(cert_key_pair) = &self.client_identity { if let Some(cert_key_pair) = &self.client_identity {
let cert_pem = read_to_string(&cert_key_pair.cert_path) let cert_pem = read_to_string(&cert_key_pair.cert_path)
.map_err(|e| anyhow::anyhow!("Failed to read client certificate: {}", e))?; .map_err(|e| anyhow::anyhow!("Failed to read client certificate: {}", e))?;
@ -142,7 +146,8 @@ impl TlsConfig {
} }
} }
pub fn load_ca_certificates(&self) -> Result<Vec<Certificate>> { #[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
fn load_ca_certificates(&self) -> Result<Vec<Certificate>> {
match &self.ca_cert_path { match &self.ca_cert_path {
Some(ca_path) => { Some(ca_path) => {
let ca_pem = read_to_string(ca_path) let ca_pem = read_to_string(ca_path)
@ -323,6 +328,7 @@ impl ApiClient {
} }
/// Configure TLS settings on a reqwest ClientBuilder /// Configure TLS settings on a reqwest ClientBuilder
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
fn configure_tls( fn configure_tls(
mut client_builder: reqwest::ClientBuilder, mut client_builder: reqwest::ClientBuilder,
tls_config: &TlsConfig, tls_config: &TlsConfig,
@ -342,6 +348,20 @@ impl ApiClient {
Ok(client_builder) Ok(client_builder)
} }
/// Reject custom TLS settings when goose is compiled without a TLS backend.
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
fn configure_tls(
client_builder: reqwest::ClientBuilder,
tls_config: &TlsConfig,
) -> Result<reqwest::ClientBuilder> {
if tls_config.is_configured() {
return Err(anyhow::anyhow!(
"Custom TLS configuration requires the `rustls-tls` or `native-tls` feature"
));
}
Ok(client_builder)
}
pub fn with_headers(mut self, headers: HeaderMap) -> Result<Self> { pub fn with_headers(mut self, headers: HeaderMap) -> Result<Self> {
self.default_headers = headers; self.default_headers = headers;
self.rebuild_client()?; self.rebuild_client()?;

View file

@ -17,6 +17,7 @@ use futures::future::BoxFuture;
use reqwest::header::HeaderValue; use reqwest::header::HeaderValue;
use rmcp::model::Tool; use rmcp::model::Tool;
use serde_json::Value; use serde_json::Value;
use smithy_transport_reqwest::ReqwestHttpClient;
use super::formats::bedrock::{ use super::formats::bedrock::{
from_bedrock_message, from_bedrock_usage, to_bedrock_message_with_caching, from_bedrock_message, from_bedrock_usage, to_bedrock_message_with_caching,
@ -98,7 +99,8 @@ impl BedrockProvider {
}; };
// Use load_defaults() which supports AWS SSO, profiles, and environment variables // Use load_defaults() which supports AWS SSO, profiles, and environment variables
let mut loader = aws_config::defaults(aws_config::BehaviorVersion::latest()); let mut loader = aws_config::defaults(aws_config::BehaviorVersion::latest())
.http_client(ReqwestHttpClient::new());
if let Ok(profile_name) = config.get_param::<String>("AWS_PROFILE") { if let Ok(profile_name) = config.get_param::<String>("AWS_PROFILE") {
if !profile_name.is_empty() { if !profile_name.is_empty() {

View file

@ -624,7 +624,7 @@ fn html_success() -> String {
} }
fn html_error(error: &str) -> String { fn html_error(error: &str) -> String {
let safe_error = v_htmlescape::escape(error).to_string(); let safe_error = v_htmlescape::escape_fmt(error);
format!( format!(
r#"<!doctype html> r#"<!doctype html>
<html> <html>

View file

@ -531,7 +531,7 @@ fn html_success() -> String {
} }
fn html_error(error: &str) -> String { fn html_error(error: &str) -> String {
let safe_error = v_htmlescape::escape(error).to_string(); let safe_error = v_htmlescape::escape_fmt(error);
format!( format!(
r#"<!doctype html> r#"<!doctype html>
<html> <html>

View file

@ -8,6 +8,7 @@ use aws_sdk_bedrockruntime::config::ProvideCredentials;
use aws_sdk_sagemakerruntime::Client as SageMakerClient; use aws_sdk_sagemakerruntime::Client as SageMakerClient;
use rmcp::model::Tool; use rmcp::model::Tool;
use serde_json::{json, Value}; use serde_json::{json, Value};
use smithy_transport_reqwest::ReqwestHttpClient;
use super::base::{ use super::base::{
ConfigKey, MessageStream, Provider, ProviderDef, ProviderMetadata, ProviderUsage, Usage, ConfigKey, MessageStream, Provider, ProviderDef, ProviderMetadata, ProviderUsage, Usage,
@ -61,7 +62,10 @@ impl SageMakerTgiProvider {
set_aws_env_vars(config.all_values()); set_aws_env_vars(config.all_values());
set_aws_env_vars(config.all_secrets()); set_aws_env_vars(config.all_secrets());
let aws_config = aws_config::load_from_env().await; let aws_config = aws_config::from_env()
.http_client(ReqwestHttpClient::new())
.load()
.await;
// Validate credentials // Validate credentials
aws_config aws_config

View file

@ -2,6 +2,7 @@ mod chat_history_search;
mod diagnostics; mod diagnostics;
pub mod extension_data; pub mod extension_data;
mod legacy; mod legacy;
#[cfg(feature = "nostr")]
pub mod nostr_share; pub mod nostr_share;
pub mod session_manager; pub mod session_manager;

View file

@ -161,7 +161,9 @@ async fn make_request(provider: &dyn Provider, session_id: &str) {
async fn test_session_id_propagates_to_log_records() { async fn test_session_id_propagates_to_log_records() {
use opentelemetry::logs::AnyValue; use opentelemetry::logs::AnyValue;
use opentelemetry::Key; use opentelemetry::Key;
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; use opentelemetry_appender_tracing::layer::{
OpenTelemetryTracingBridge, TracingSpanAttributes,
};
use opentelemetry_sdk::logs::{InMemoryLogExporterBuilder, SdkLoggerProvider}; use opentelemetry_sdk::logs::{InMemoryLogExporterBuilder, SdkLoggerProvider};
use tracing_subscriber::prelude::*; use tracing_subscriber::prelude::*;
@ -171,7 +173,7 @@ async fn test_session_id_propagates_to_log_records() {
.build(); .build();
let layer = OpenTelemetryTracingBridge::builder(&provider) let layer = OpenTelemetryTracingBridge::builder(&provider)
.with_span_attribute_allowlist(["session.id"]) .with_tracing_span_attributes(TracingSpanAttributes::allowlist(["session.id"]))
.build(); .build();
let subscriber = tracing_subscriber::registry().with(layer); let subscriber = tracing_subscriber::registry().with(layer);
let _guard = tracing::subscriber::set_default(subscriber); let _guard = tracing::subscriber::set_default(subscriber);