Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/goose-mcp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description.workspace = true
workspace = true

[dependencies]
goose = { path = "../goose" }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hrm - is this an issue adding in the goose dep to mcp?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(feels circular but isn't...)

mcp-core = { path = "../mcp-core" }
mcp-server = { path = "../mcp-server" }
rmcp = { version = "0.6.0", features = ["server", "client", "transport-io", "macros"] }
Expand Down
33 changes: 15 additions & 18 deletions crates/goose-mcp/src/developer/shell.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{env, process::Stdio};
use goose::config::get_config_dir;
use std::{env, ffi::OsString, process::Stdio};

#[cfg(unix)]
#[allow(unused_imports)] // False positive: trait is used for process_group method
Expand All @@ -8,30 +9,23 @@ use std::os::unix::process::CommandExt;
pub struct ShellConfig {
pub executable: String,
pub args: Vec<String>,
#[allow(dead_code)]
pub envs: Vec<(OsString, OsString)>,
}

impl Default for ShellConfig {
fn default() -> Self {
if cfg!(windows) {
// Detect the default shell on Windows
#[cfg(windows)]
{
Self::detect_windows_shell()
}
#[cfg(not(windows))]
{
// This branch should never be taken on non-Windows
// but we need it for compilation
Self {
executable: "cmd".to_string(),
args: vec!["/c".to_string()],
}
}
} else {
// Use bash on Unix/macOS (keep existing behavior)
#[cfg(windows)]
{
Self::detect_windows_shell()
}
#[cfg(not(windows))]
{
let bash_env = get_config_dir().join(".bash_env").into_os_string();
Self {
executable: "bash".to_string(),
args: vec!["-c".to_string()],
envs: vec![(OsString::from("BASH_ENV"), bash_env)],
}
}
}
Expand All @@ -50,6 +44,7 @@ impl ShellConfig {
"-NonInteractive".to_string(),
"-Command".to_string(),
],
envs: vec![],
}
} else if let Ok(ps_path) = which::which("powershell") {
// Windows PowerShell 5.1
Expand All @@ -60,12 +55,14 @@ impl ShellConfig {
"-NonInteractive".to_string(),
"-Command".to_string(),
],
envs: vec![],
}
} else {
// Fall back to cmd.exe
Self {
executable: "cmd".to_string(),
args: vec!["/c".to_string()],
envs: vec![],
}
}
}
Expand Down
10 changes: 7 additions & 3 deletions crates/goose/src/config/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,18 @@ enum SecretStorage {
// Global instance
static GLOBAL_CONFIG: OnceCell<Config> = OnceCell::new();

pub fn get_config_dir() -> PathBuf {
choose_app_strategy(APP_STRATEGY.clone())
.expect("goose requires a home dir")
.config_dir()
}

impl Default for Config {
fn default() -> Self {
// choose_app_strategy().config_dir()
// - macOS/Linux: ~/.config/goose/
// - Windows: ~\AppData\Roaming\Block\goose\config\
let config_dir = choose_app_strategy(APP_STRATEGY.clone())
.expect("goose requires a home dir")
.config_dir();
let config_dir = get_config_dir();

std::fs::create_dir_all(&config_dir).expect("Failed to create config directory");

Expand Down
2 changes: 1 addition & 1 deletion crates/goose/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod signup_openrouter;
pub mod signup_tetrate;

pub use crate::agents::ExtensionConfig;
pub use base::{Config, ConfigError, APP_STRATEGY};
pub use base::{get_config_dir, Config, ConfigError, APP_STRATEGY};
pub use custom_providers::CustomProviderConfig;
pub use experiments::ExperimentManager;
pub use extensions::{ExtensionConfigManager, ExtensionEntry};
Expand Down
56 changes: 23 additions & 33 deletions ui/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { spawn } from 'child_process';
import 'dotenv/config';
import { startGoosed } from './goosed';
import { expandTilde, getBinaryPath } from './utils/pathUtils';
import { loadShellEnv } from './utils/loadEnv';
import log from './utils/logger';
import { ensureWinShims } from './utils/winShims';
import { addRecentDir, loadRecentDirs } from './utils/recentDirs';
Expand Down Expand Up @@ -448,46 +447,37 @@ const parseArgs = () => {
return { dirPath };
};

const getGooseProvider = () => {
loadShellEnv(app.isPackaged);
interface BundledConfig {
defaultProvider?: string;
defaultModel?: string;
predefinedModels?: string;
baseUrlShare?: string;
version?: string;
}

const getBundledConfig = (): BundledConfig => {
//{env-macro-start}//
//needed when goose is bundled for a specific provider
//{env-macro-end}//
return [
process.env.GOOSE_DEFAULT_PROVIDER,
process.env.GOOSE_DEFAULT_MODEL,
process.env.GOOSE_PREDEFINED_MODELS,
];
};

const getSharingUrl = () => {
// checks app env for sharing url
loadShellEnv(app.isPackaged); // will try to take it from the zshrc file
// if GOOSE_BASE_URL_SHARE is found, we will set process.env.GOOSE_BASE_URL_SHARE, otherwise we return what it is set
// to in the env at bundle time
return process.env.GOOSE_BASE_URL_SHARE;
};

const getVersion = () => {
// checks app env for sharing url
loadShellEnv(app.isPackaged); // will try to take it from the zshrc file
// to in the env at bundle time
return process.env.GOOSE_VERSION;
return {
defaultProvider: process.env.GOOSE_DEFAULT_PROVIDER,
defaultModel: process.env.GOOSE_DEFAULT_MODEL,
predefinedModels: process.env.GOOSE_PREDEFINED_MODELS,
baseUrlShare: process.env.GOOSE_BASE_URL_SHARE,
version: process.env.GOOSE_VERSION,
};
};

const [provider, model, predefinedModels] = getGooseProvider();

const sharingUrl = getSharingUrl();

const gooseVersion = getVersion();
const { defaultProvider, defaultModel, predefinedModels, baseUrlShare, version } =
getBundledConfig();

const SERVER_SECRET = process.env.GOOSE_EXTERNAL_BACKEND
? 'test'
: crypto.randomBytes(32).toString('hex');

let appConfig = {
GOOSE_DEFAULT_PROVIDER: provider,
GOOSE_DEFAULT_MODEL: model,
GOOSE_DEFAULT_PROVIDER: defaultProvider,
GOOSE_DEFAULT_MODEL: defaultModel,
GOOSE_PREDEFINED_MODELS: predefinedModels,
GOOSE_API_HOST: 'http://127.0.0.1',
GOOSE_PORT: 0,
Expand Down Expand Up @@ -603,8 +593,8 @@ const createChat = async (
GOOSE_PORT: port,
GOOSE_WORKING_DIR: working_dir,
REQUEST_DIR: dir,
GOOSE_BASE_URL_SHARE: sharingUrl,
GOOSE_VERSION: gooseVersion,
GOOSE_BASE_URL_SHARE: baseUrlShare,
GOOSE_VERSION: version,
recipe: recipe,
}),
],
Expand Down Expand Up @@ -1927,7 +1917,7 @@ async function appMain() {
if (aboutGooseMenuItem.submenu) {
aboutGooseMenuItem.submenu.append(
new MenuItem({
label: `Version ${gooseVersion || app.getVersion()}`,
label: `Version ${version || app.getVersion()}`,
enabled: false,
})
);
Expand Down
38 changes: 0 additions & 38 deletions ui/desktop/src/utils/loadEnv.ts

This file was deleted.

Loading