mirror of
https://github.com/block/goose.git
synced 2026-04-28 03:29:36 +00:00
Make it startable from playwright and also isolate (#5016)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
parent
1690cf9091
commit
d3a222ddbf
22 changed files with 150 additions and 144 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
|
@ -2705,6 +2705,7 @@ dependencies = [
|
|||
"jsonschema",
|
||||
"nix 0.30.1",
|
||||
"once_cell",
|
||||
"open",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"rmcp",
|
||||
|
|
@ -3531,6 +3532,15 @@ version = "2.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||
|
||||
[[package]]
|
||||
name = "is-docker"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.16"
|
||||
|
|
@ -3542,6 +3552,16 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-wsl"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
|
||||
dependencies = [
|
||||
"is-docker",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
|
|
@ -4418,6 +4438,17 @@ version = "11.1.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "5.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95"
|
||||
dependencies = [
|
||||
"is-wsl",
|
||||
"libc",
|
||||
"pathdiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.73"
|
||||
|
|
|
|||
11
Justfile
11
Justfile
|
|
@ -143,6 +143,15 @@ run-ui:
|
|||
@echo "Running UI..."
|
||||
cd ui/desktop && npm install && npm run start-gui
|
||||
|
||||
run-ui-playwright:
|
||||
#!/usr/bin/env sh
|
||||
just release-binary
|
||||
echo "Running UI with Playwright debugging..."
|
||||
RUN_DIR="$HOME/goose-runs/$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$RUN_DIR"
|
||||
echo "Using isolated directory: $RUN_DIR"
|
||||
cd ui/desktop && ENABLE_PLAYWRIGHT=true GOOSE_PATH_ROOT="$RUN_DIR" npm run start-gui
|
||||
|
||||
run-ui-only:
|
||||
@echo "Running UI..."
|
||||
cd ui/desktop && npm install && npm run start-gui
|
||||
|
|
@ -463,4 +472,4 @@ build-test-tools:
|
|||
|
||||
record-mcp-tests: build-test-tools
|
||||
GOOSE_RECORD_MCP=1 cargo test --package goose --test mcp_integration_test
|
||||
git add crates/goose/tests/mcp_replays/
|
||||
git add crates/goose/tests/mcp_replays/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use console::style;
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use goose::config::paths::Paths;
|
||||
use goose::config::Config;
|
||||
use serde_yaml;
|
||||
|
||||
|
|
@ -9,11 +9,8 @@ fn print_aligned(label: &str, value: &str, width: usize) {
|
|||
}
|
||||
|
||||
pub fn handle_info(verbose: bool) -> Result<()> {
|
||||
let data_dir = choose_app_strategy(crate::APP_STRATEGY.clone())?;
|
||||
let logs_dir = data_dir
|
||||
.in_state_dir("logs")
|
||||
.unwrap_or_else(|| data_dir.in_data_dir("logs"));
|
||||
let sessions_dir = data_dir.in_data_dir("sessions");
|
||||
let logs_dir = Paths::in_state_dir("logs");
|
||||
let sessions_dir = Paths::in_data_dir("sessions");
|
||||
|
||||
// Get paths using a stored reference to the global config
|
||||
let config = Config::global();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use etcetera::AppStrategyArgs;
|
||||
use once_cell::sync::Lazy;
|
||||
pub mod cli;
|
||||
pub mod commands;
|
||||
pub mod logging;
|
||||
|
|
@ -11,9 +9,3 @@ pub mod signal;
|
|||
|
||||
// Re-export commonly used types
|
||||
pub use session::CliSession;
|
||||
|
||||
pub static APP_STRATEGY: Lazy<AppStrategyArgs> = Lazy::new(|| AppStrategyArgs {
|
||||
top_level_domain: "Block".to_string(),
|
||||
author: "Block".to_string(),
|
||||
app_name: "goose".to_string(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::{Context, Result};
|
||||
use chrono::{DateTime, Utc};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use goose::config::paths::Paths;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
|
|
@ -41,11 +41,7 @@ pub struct ProjectInfoDisplay {
|
|||
impl ProjectTracker {
|
||||
/// Get the path to the projects.json file
|
||||
fn get_projects_file() -> Result<PathBuf> {
|
||||
let projects_file = choose_app_strategy(crate::APP_STRATEGY.clone())
|
||||
.context("goose requires a home dir")?
|
||||
.in_data_dir("projects.json");
|
||||
|
||||
// Ensure data directory exists
|
||||
let projects_file = Paths::in_data_dir("projects.json");
|
||||
if let Some(parent) = projects_file.parent() {
|
||||
if !parent.exists() {
|
||||
fs::create_dir_all(parent)?;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ use goose::utils::safe_truncate;
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use completion::GooseCompleter;
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use goose::agents::extension::{Envs, ExtensionConfig};
|
||||
use goose::agents::types::RetryConfig;
|
||||
use goose::agents::{Agent, SessionConfig};
|
||||
|
|
@ -37,6 +36,7 @@ use rmcp::model::PromptMessage;
|
|||
use rmcp::model::ServerNotification;
|
||||
use rmcp::model::{ErrorCode, ErrorData};
|
||||
|
||||
use goose::config::paths::Paths;
|
||||
use goose::conversation::message::{Message, MessageContent};
|
||||
use rand::{distributions::Alphanumeric, Rng};
|
||||
use rustyline::EditMode;
|
||||
|
|
@ -413,29 +413,20 @@ impl CliSession {
|
|||
let completer = GooseCompleter::new(self.completion_cache.clone());
|
||||
editor.set_helper(Some(completer));
|
||||
|
||||
// Create and use a global history file in ~/.config/goose directory
|
||||
// This allows command history to persist across different chat sessions
|
||||
// instead of being tied to each individual session's messages
|
||||
let strategy =
|
||||
choose_app_strategy(crate::APP_STRATEGY.clone()).expect("goose requires a home dir");
|
||||
let config_dir = strategy.config_dir();
|
||||
let history_file = config_dir.join("history.txt");
|
||||
let history_file = Paths::config_dir().join("history.txt");
|
||||
|
||||
// Ensure config directory exists
|
||||
if let Some(parent) = history_file.parent() {
|
||||
if !parent.exists() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Load history from the global file
|
||||
if history_file.exists() {
|
||||
if let Err(err) = editor.load_history(&history_file) {
|
||||
eprintln!("Warning: Failed to load command history: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to save history after commands
|
||||
let save_history =
|
||||
|editor: &mut rustyline::Editor<GooseCompleter, rustyline::history::DefaultHistory>| {
|
||||
if let Err(err) = editor.save_history(&history_file) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use goose::config::get_config_dir;
|
||||
use std::{env, ffi::OsString, process::Stdio};
|
||||
|
||||
use goose::config::paths::Paths;
|
||||
#[cfg(unix)]
|
||||
#[allow(unused_imports)] // False positive: trait is used for process_group method
|
||||
use std::os::unix::process::CommandExt;
|
||||
|
|
@ -30,7 +30,7 @@ impl Default for ShellConfig {
|
|||
|
||||
// Configure environment based on shell type
|
||||
let envs = if shell_name == "bash" {
|
||||
let bash_env = get_config_dir().join(".bash_env").into_os_string();
|
||||
let bash_env = Paths::config_dir().join(".bash_env").into_os_string();
|
||||
vec![(OsString::from("BASH_ENV"), bash_env)]
|
||||
} else {
|
||||
vec![]
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ use axum::{
|
|||
routing::{delete, get, post},
|
||||
Json, Router,
|
||||
};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use goose::config::paths::Paths;
|
||||
use goose::config::ExtensionEntry;
|
||||
use goose::config::APP_STRATEGY;
|
||||
use goose::config::{Config, ConfigError};
|
||||
use goose::model::ModelConfig;
|
||||
use goose::providers::base::ProviderMetadata;
|
||||
|
|
@ -565,11 +564,7 @@ pub async fn upsert_permissions(
|
|||
)
|
||||
)]
|
||||
pub async fn backup_config() -> Result<Json<String>, StatusCode> {
|
||||
let config_dir = choose_app_strategy(APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.config_dir();
|
||||
|
||||
let config_path = config_dir.join("config.yaml");
|
||||
let config_path = Paths::config_dir().join("config.yaml");
|
||||
|
||||
if config_path.exists() {
|
||||
let file_name = config_path
|
||||
|
|
@ -630,11 +625,7 @@ pub async fn recover_config() -> Result<Json<String>, StatusCode> {
|
|||
)
|
||||
)]
|
||||
pub async fn validate_config() -> Result<Json<String>, StatusCode> {
|
||||
let config_dir = choose_app_strategy(APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.config_dir();
|
||||
|
||||
let config_path = config_dir.join("config.yaml");
|
||||
let config_path = Paths::config_dir().join("config.yaml");
|
||||
|
||||
if !config_path.exists() {
|
||||
return Ok(Json("Config file does not exist".to_string()));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs};
|
||||
use crate::config::paths::Paths;
|
||||
use fs2::FileExt;
|
||||
use keyring::Entry;
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
use once_cell::sync::OnceCell;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -11,12 +11,6 @@ use std::io::Write;
|
|||
use std::path::{Path, PathBuf};
|
||||
use thiserror::Error;
|
||||
|
||||
pub static APP_STRATEGY: Lazy<AppStrategyArgs> = Lazy::new(|| AppStrategyArgs {
|
||||
top_level_domain: "Block".to_string(),
|
||||
author: "Block".to_string(),
|
||||
app_name: "goose".to_string(),
|
||||
});
|
||||
|
||||
const KEYRING_SERVICE: &str = "goose";
|
||||
const KEYRING_USERNAME: &str = "secrets";
|
||||
|
||||
|
|
@ -116,18 +110,9 @@ 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 = get_config_dir();
|
||||
let config_dir = Paths::config_dir();
|
||||
|
||||
std::fs::create_dir_all(&config_dir).expect("Failed to create config directory");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
use crate::config::{Config, APP_STRATEGY};
|
||||
use crate::config::paths::Paths;
|
||||
use crate::config::Config;
|
||||
use crate::model::ModelConfig;
|
||||
use crate::providers::anthropic::AnthropicProvider;
|
||||
use crate::providers::base::ModelInfo;
|
||||
use crate::providers::ollama::OllamaProvider;
|
||||
use crate::providers::openai::OpenAiProvider;
|
||||
use anyhow::Result;
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn custom_providers_dir() -> std::path::PathBuf {
|
||||
choose_app_strategy(APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.config_dir()
|
||||
.join("custom_providers")
|
||||
Paths::config_dir().join("custom_providers")
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@ pub mod base;
|
|||
pub mod custom_providers;
|
||||
mod experiments;
|
||||
pub mod extensions;
|
||||
pub mod paths;
|
||||
pub mod permission;
|
||||
pub mod signup_openrouter;
|
||||
pub mod signup_tetrate;
|
||||
|
||||
pub use crate::agents::ExtensionConfig;
|
||||
pub use base::{get_config_dir, Config, ConfigError, APP_STRATEGY};
|
||||
pub use base::{Config, ConfigError};
|
||||
pub use custom_providers::CustomProviderConfig;
|
||||
pub use experiments::ExperimentManager;
|
||||
pub use extensions::{
|
||||
|
|
|
|||
60
crates/goose/src/config/paths.rs
Normal file
60
crates/goose/src/config/paths.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Paths;
|
||||
|
||||
impl Paths {
|
||||
fn get_dir(dir_type: DirType) -> PathBuf {
|
||||
if let Ok(test_root) = std::env::var("GOOSE_PATH_ROOT") {
|
||||
let base = PathBuf::from(test_root);
|
||||
match dir_type {
|
||||
DirType::Config => base.join("config"),
|
||||
DirType::Data => base.join("data"),
|
||||
DirType::State => base.join("state"),
|
||||
}
|
||||
} else {
|
||||
let strategy = choose_app_strategy(AppStrategyArgs {
|
||||
top_level_domain: "Block".to_string(),
|
||||
author: "Block".to_string(),
|
||||
app_name: "goose".to_string(),
|
||||
})
|
||||
.expect("goose requires a home dir");
|
||||
|
||||
match dir_type {
|
||||
DirType::Config => strategy.config_dir(),
|
||||
DirType::Data => strategy.data_dir(),
|
||||
DirType::State => strategy.state_dir().unwrap_or(strategy.data_dir()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config_dir() -> PathBuf {
|
||||
Self::get_dir(DirType::Config)
|
||||
}
|
||||
|
||||
pub fn data_dir() -> PathBuf {
|
||||
Self::get_dir(DirType::Data)
|
||||
}
|
||||
|
||||
pub fn state_dir() -> PathBuf {
|
||||
Self::get_dir(DirType::State)
|
||||
}
|
||||
|
||||
pub fn in_state_dir(subpath: &str) -> PathBuf {
|
||||
Self::state_dir().join(subpath)
|
||||
}
|
||||
|
||||
pub fn in_config_dir(subpath: &str) -> PathBuf {
|
||||
Self::config_dir().join(subpath)
|
||||
}
|
||||
|
||||
pub fn in_data_dir(subpath: &str) -> PathBuf {
|
||||
Self::data_dir().join(subpath)
|
||||
}
|
||||
}
|
||||
|
||||
enum DirType {
|
||||
Config,
|
||||
Data,
|
||||
State,
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
use super::APP_STRATEGY;
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use crate::config::paths::Paths;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
|
|
@ -37,14 +36,7 @@ const SMART_APPROVE_PERMISSION: &str = "smart_approve";
|
|||
/// Implements the default constructor for `PermissionManager`.
|
||||
impl Default for PermissionManager {
|
||||
fn default() -> Self {
|
||||
// Choose the app strategy and determine the config directory
|
||||
let config_dir = choose_app_strategy(APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.config_dir();
|
||||
|
||||
// Ensure the configuration directory exists
|
||||
std::fs::create_dir_all(&config_dir).expect("Failed to create config directory");
|
||||
let config_path = config_dir.join("permission.yaml");
|
||||
let config_path = Paths::config_dir().join("permission.yaml");
|
||||
|
||||
// Load the existing configuration file or create an empty map if the file doesn't exist
|
||||
let permission_map = if config_path.exists() {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use crate::agents::extension::PlatformExtensionContext;
|
||||
use crate::agents::Agent;
|
||||
use crate::config::APP_STRATEGY;
|
||||
use crate::config::paths::Paths;
|
||||
use crate::model::ModelConfig;
|
||||
use crate::providers::create;
|
||||
use crate::scheduler_factory::SchedulerFactory;
|
||||
use crate::scheduler_trait::SchedulerTrait;
|
||||
use anyhow::Result;
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use lru::LruCache;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -37,10 +36,7 @@ impl AgentManager {
|
|||
|
||||
// Private constructor - prevents direct instantiation in production
|
||||
async fn new(max_sessions: Option<usize>) -> Result<Self> {
|
||||
// Construct scheduler with the standard goose-server path
|
||||
let schedule_file_path = choose_app_strategy(APP_STRATEGY.clone())?
|
||||
.data_dir()
|
||||
.join("schedule.json");
|
||||
let schedule_file_path = Paths::data_dir().join("schedule.json");
|
||||
|
||||
let scheduler = SchedulerFactory::create(schedule_file_path).await?;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
use crate::config::paths::Paths;
|
||||
use anyhow::{Context, Result};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::config::APP_STRATEGY;
|
||||
|
||||
/// Returns the directory where log files should be stored for a specific component.
|
||||
/// Creates the directory structure if it doesn't exist.
|
||||
///
|
||||
|
|
@ -12,17 +10,8 @@ use crate::config::APP_STRATEGY;
|
|||
///
|
||||
/// * `component` - The component name (e.g., "cli", "server", "debug")
|
||||
/// * `use_date_subdir` - Whether to create a date-based subdirectory
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The path to the log directory for the specified component
|
||||
pub fn get_log_directory(component: &str, use_date_subdir: bool) -> Result<PathBuf> {
|
||||
let home_dir =
|
||||
choose_app_strategy(APP_STRATEGY.clone()).context("HOME environment variable not set")?;
|
||||
|
||||
let base_log_dir = home_dir
|
||||
.in_state_dir("logs")
|
||||
.unwrap_or_else(|| home_dir.in_data_dir("logs"));
|
||||
let base_log_dir = Paths::in_state_dir("logs");
|
||||
|
||||
let component_dir = base_log_dir.join(component);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::config::paths::Paths;
|
||||
use crate::conversation::message::ToolRequest;
|
||||
use anyhow::Result;
|
||||
use blake3::Hasher;
|
||||
use chrono::Utc;
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
|
@ -35,14 +35,10 @@ impl Default for ToolPermissionStore {
|
|||
|
||||
impl ToolPermissionStore {
|
||||
pub fn new() -> Self {
|
||||
let permissions_dir = choose_app_strategy(crate::config::APP_STRATEGY.clone())
|
||||
.map(|strategy| strategy.config_dir())
|
||||
.unwrap_or_else(|_| PathBuf::from(".config/goose"));
|
||||
|
||||
Self {
|
||||
permissions: HashMap::new(),
|
||||
version: 1,
|
||||
permissions_dir,
|
||||
permissions_dir: Paths::config_dir().join("permissions"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::config::paths::Paths;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use axum::http;
|
||||
use chrono::{DateTime, Utc};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
|
@ -81,9 +81,7 @@ struct DiskCache {
|
|||
|
||||
impl DiskCache {
|
||||
fn new() -> Self {
|
||||
let cache_path = choose_app_strategy(crate::config::APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.in_config_dir("githubcopilot/info.json");
|
||||
let cache_path = Paths::in_config_dir("githubcopilot/info.json");
|
||||
Self { cache_path }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::config::paths::Paths;
|
||||
use anyhow::Result;
|
||||
use axum::{extract::Query, response::Html, routing::get, Router};
|
||||
use base64::Engine;
|
||||
use chrono::{DateTime, Utc};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
|
@ -38,12 +38,7 @@ struct TokenCache {
|
|||
}
|
||||
|
||||
fn get_base_path() -> PathBuf {
|
||||
// choose_app_strategy().config_dir()
|
||||
// - macOS/Linux: ~/.config/goose/databricks/oauth
|
||||
// - Windows: ~\AppData\Roaming\Block\goose\config\databricks\oauth\
|
||||
choose_app_strategy(crate::config::APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.in_config_dir("databricks/oauth")
|
||||
Paths::in_config_dir("databricks/oauth")
|
||||
}
|
||||
|
||||
impl TokenCache {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::config::APP_STRATEGY;
|
||||
use crate::config::paths::Paths;
|
||||
use crate::recipe::read_recipe_file_content::{read_recipe_file, RecipeFile};
|
||||
use crate::recipe::Recipe;
|
||||
use crate::recipe::RECIPE_FILE_EXTENSIONS;
|
||||
|
|
@ -14,10 +13,7 @@ const GOOSE_RECIPE_PATH_ENV_VAR: &str = "GOOSE_RECIPE_PATH";
|
|||
|
||||
pub fn get_recipe_library_dir(is_global: bool) -> PathBuf {
|
||||
if is_global {
|
||||
choose_app_strategy(APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.config_dir()
|
||||
.join("recipes")
|
||||
Paths::config_dir().join("recipes")
|
||||
} else {
|
||||
std::env::current_dir().unwrap().join(".goose/recipes")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ use std::sync::Arc;
|
|||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_cron_scheduler::{job::JobId, Job, JobScheduler as TokioJobScheduler};
|
||||
|
||||
use crate::agents::AgentEvent;
|
||||
use crate::agents::{Agent, SessionConfig};
|
||||
use crate::config::{self, Config};
|
||||
use crate::config::paths::Paths;
|
||||
use crate::config::Config;
|
||||
use crate::conversation::message::Message;
|
||||
use crate::conversation::Conversation;
|
||||
use crate::providers::base::Provider as GooseProvider; // Alias to avoid conflict in test section
|
||||
|
|
@ -63,18 +63,13 @@ pub fn normalize_cron_expression(src: &str) -> String {
|
|||
}
|
||||
|
||||
pub fn get_default_scheduler_storage_path() -> Result<PathBuf, io::Error> {
|
||||
let strategy = choose_app_strategy(config::APP_STRATEGY.clone())
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::NotFound, e.to_string()))?;
|
||||
let data_dir = strategy.data_dir();
|
||||
let data_dir = Paths::data_dir();
|
||||
fs::create_dir_all(&data_dir)?;
|
||||
Ok(data_dir.join("schedules.json"))
|
||||
}
|
||||
|
||||
pub fn get_default_scheduled_recipes_dir() -> Result<PathBuf, SchedulerError> {
|
||||
let strategy = choose_app_strategy(config::APP_STRATEGY.clone()).map_err(|e| {
|
||||
SchedulerError::StorageError(io::Error::new(io::ErrorKind::NotFound, e.to_string()))
|
||||
})?;
|
||||
let data_dir = strategy.data_dir();
|
||||
let data_dir = Paths::data_dir();
|
||||
let recipes_dir = data_dir.join("scheduled_recipes");
|
||||
fs::create_dir_all(&recipes_dir).map_err(SchedulerError::StorageError)?;
|
||||
tracing::debug!(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::config::APP_STRATEGY;
|
||||
use crate::config::paths::Paths;
|
||||
use crate::conversation::message::Message;
|
||||
use crate::conversation::Conversation;
|
||||
use crate::providers::base::{Provider, MSG_COUNT_FOR_SESSION_NAME_GENERATION};
|
||||
|
|
@ -6,7 +6,6 @@ use crate::recipe::Recipe;
|
|||
use crate::session::extension_data::ExtensionData;
|
||||
use anyhow::Result;
|
||||
use chrono::{DateTime, Utc};
|
||||
use etcetera::{choose_app_strategy, AppStrategy};
|
||||
use rmcp::model::Role;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::sqlite::SqliteConnectOptions;
|
||||
|
|
@ -241,16 +240,13 @@ pub struct SessionStorage {
|
|||
}
|
||||
|
||||
pub fn ensure_session_dir() -> Result<PathBuf> {
|
||||
let data_dir = choose_app_strategy(APP_STRATEGY.clone())
|
||||
.expect("goose requires a home dir")
|
||||
.data_dir()
|
||||
.join("sessions");
|
||||
let session_dir = Paths::data_dir().join("sessions");
|
||||
|
||||
if !data_dir.exists() {
|
||||
fs::create_dir_all(&data_dir)?;
|
||||
if !session_dir.exists() {
|
||||
fs::create_dir_all(&session_dir)?;
|
||||
}
|
||||
|
||||
Ok(data_dir)
|
||||
Ok(session_dir)
|
||||
}
|
||||
|
||||
fn role_to_string(role: &Role) -> &'static str {
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ async function ensureTempDirExists(): Promise<string> {
|
|||
|
||||
if (started) app.quit();
|
||||
|
||||
if (process.env.ENABLE_PLAYWRIGHT) {
|
||||
console.log('[Main] Enabling Playwright remote debugging on port 9222');
|
||||
app.commandLine.appendSwitch('remote-debugging-port', '9222');
|
||||
}
|
||||
|
||||
// In development mode, force registration as the default protocol client
|
||||
// In production, register normally
|
||||
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
|
||||
|
|
@ -519,10 +524,9 @@ const createChat = async (
|
|||
const settings = loadSettings();
|
||||
updateSchedulingEngineEnvironment(settings.schedulingEngine);
|
||||
|
||||
// Start new Goosed process for regular windows
|
||||
// Pass through scheduling engine environment variables
|
||||
const envVars = {
|
||||
GOOSE_SCHEDULER_TYPE: process.env.GOOSE_SCHEDULER_TYPE,
|
||||
GOOSE_PATH_ROOT: process.env.GOOSE_PATH_ROOT,
|
||||
};
|
||||
const [newPort, newWorkingDir, newGoosedProcess] = await startGoosed(
|
||||
app,
|
||||
|
|
@ -1679,7 +1683,6 @@ async function appMain() {
|
|||
// Ensure Windows shims are available before any MCP processes are spawned
|
||||
await ensureWinShims();
|
||||
|
||||
// Register update IPC handlers once (but don't setup auto-updater yet)
|
||||
registerUpdateIpcHandlers();
|
||||
|
||||
// Handle microphone permission requests
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue