Skip to content
Open
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
4 changes: 4 additions & 0 deletions apps/desktop/src/lib/settings/appSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export class SettingsService {
await this.invokeAndRefresh("update_reviews", { update });
}

async updateAgents(update: Partial<AppSettings["agents"]>) {
await this.invokeAndRefresh("update_agents", { update });
}

async updateFetch(update: Partial<AppSettings["fetch"]>) {
await this.invokeAndRefresh("update_fetch", { update });
}
Expand Down
670 changes: 670 additions & 0 deletions crates/but-api/src/agents.rs

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion crates/but-api/src/legacy/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
use anyhow::Result;
use but_settings::{
AppSettingsWithDiskSync,
api::{FeatureFlagsUpdate, FetchUpdate, ReviewsUpdate, TelemetryUpdate, UiUpdate},
api::{
AgentsUpdate, FeatureFlagsUpdate, FetchUpdate, ReviewsUpdate, TelemetryUpdate, UiUpdate,
},
};
use serde::Deserialize;

Expand Down Expand Up @@ -58,6 +60,19 @@ pub fn update_feature_flags(
app_settings_sync.update_feature_flags(params.update)
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAgentsParams {
pub update: AgentsUpdate,
}

pub fn update_agents(
app_settings_sync: &AppSettingsWithDiskSync,
params: UpdateAgentsParams,
) -> Result<()> {
app_settings_sync.update_agents(params.update)
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateReviewsParams {
Expand Down
3 changes: 3 additions & 0 deletions crates/but-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use but_workspace::RefInfo;
#[cfg(feature = "legacy")]
pub mod legacy;

/// Managing coding-agent skills and the `but` CLI symlink.
pub mod agents;

/// Functions for GitHub authentication.
pub mod github;

Expand Down
8 changes: 8 additions & 0 deletions crates/but-napi/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ pub async fn update_feature_flags(
apply_update(update, AppSettingsWithDiskSync::update_feature_flags)
}

/// Update agent settings; unset fields are left unchanged.
#[napi]
pub async fn update_agents(
#[napi(ts_arg_type = "AgentsUpdate")] update: serde_json::Value,
) -> napi::Result<()> {
apply_update(update, AppSettingsWithDiskSync::update_agents)
}

/// Update review settings; unset fields are left unchanged.
#[napi]
pub async fn update_reviews(
Expand Down
26 changes: 25 additions & 1 deletion crates/but-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use axum::{
response::IntoResponse,
routing::{MethodRouter, any, post},
};
use but_api::{commit, diff, github, gitlab, json, legacy, open, platform, workspace};
use but_api::{agents, commit, diff, github, gitlab, json, legacy, open, platform, workspace};
use but_ctx::ProjectHandleOrLegacyProjectId;

mod broadcaster;
Expand Down Expand Up @@ -745,6 +745,22 @@ pub async fn run(config: Config) -> anyhow::Result<()> {
)
.route("/install_cli", but_post(legacy::cli::install_cli_cmd))
.route("/cli_path", but_post(legacy::cli::cli_path_cmd))
.route(
"/cli_install_state",
but_post(agents::cli_install_state_cmd),
)
.route("/uninstall_cli", but_post(agents::uninstall_cli_cmd))
Comment on lines +748 to +752
.route("/agents_status", but_post(agents::agents_status_cmd))
.route(
"/agent_skill_install",
but_post(agents::agent_skill_install_cmd),
)
.route(
"/agent_skill_uninstall",
but_post(agents::agent_skill_uninstall_cmd),
)
.route("/agent_policy_get", but_post(agents::agent_policy_get_cmd))
.route("/agent_policy_set", but_post(agents::agent_policy_set_cmd))
.route("/open_url", but_post(open::open_url_cmd))
.route("/open_in_terminal", but_post(open::open_in_terminal_cmd))
.route("/show_in_finder", but_post(open::show_in_finder_cmd))
Expand Down Expand Up @@ -981,6 +997,14 @@ async fn handle_command(
"update_reviews" => deserialize_json(request.params).and_then(|params| {
legacy::settings::update_reviews(&app_settings_sync, params).map(|r| json!(r))
}),
"update_agents" => deserialize_json(request.params).and_then(|params| {
legacy::settings::update_agents(&app_settings_sync, params).map(|r| json!(r))
}),
// Registered in Tauri since it was added, but never here, so any
// non-Tauri caller silently fell through to the catch-all.
"update_ui" => deserialize_json(request.params).and_then(|params| {
legacy::settings::update_ui(&app_settings_sync, params).map(|r| json!(r))
}),
// Project management (need extra or app)
"list_projects" => projects::list_projects(&extra).await,
"set_project_active" => {
Expand Down
5 changes: 5 additions & 0 deletions crates/but-settings/assets/defaults.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
"autoFillPrDescriptionFromCommit": true
},
// UI settings.
// Coding-agent skills and the `but` CLI.
"agents": {
// Whether the user dismissed the prompt offering to set up agent skills.
"skillsPromptDismissed": false
},
"ui": {
// Whether to use the native system title bar.
"useNativeTitleBar": false,
Expand Down
19 changes: 19 additions & 0 deletions crates/but-settings/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ pub struct ReviewsUpdate {
}
but_schemars::register_sdk_type!(ReviewsUpdate);

#[derive(
Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema,
)]
#[serde(rename_all = "camelCase", default)]
#[schemars(extend("x-input" = true))]
/// Update request for [`crate::app_settings::Agents`].
pub struct AgentsUpdate {
pub skills_prompt_dismissed: Option<bool>,
}
but_schemars::register_sdk_type!(AgentsUpdate);

#[derive(
Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema,
)]
Expand Down Expand Up @@ -109,6 +120,14 @@ impl AppSettingsWithDiskSync {
settings.save()
}

pub fn update_agents(&self, update: AgentsUpdate) -> Result<()> {
let mut settings = self.get_mut_enforce_save()?;
if let Some(skills_prompt_dismissed) = update.skills_prompt_dismissed {
settings.agents.skills_prompt_dismissed = skills_prompt_dismissed;
}
settings.save()
}

pub fn update_reviews(&self, update: ReviewsUpdate) -> Result<()> {
let mut settings = self.get_mut_enforce_save()?;
if let Some(auto_fill_pr_description_from_commit) =
Expand Down
10 changes: 10 additions & 0 deletions crates/but-settings/src/app_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ pub struct Reviews {
}
but_schemars::register_sdk_type!(Reviews);

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Agents {
/// Whether the user dismissed the prompt offering to set up agent skills.
/// Set when they decline, and when they complete setup, so the nudge is
/// shown at most once per user.
pub skills_prompt_dismissed: bool,
}
but_schemars::register_sdk_type!(Agents);

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct UiSettings {
Expand Down
1 change: 1 addition & 0 deletions crates/but-settings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct AppSettings {
/// Settings related to code reviews and pull requests.
pub reviews: app_settings::Reviews,
/// UI settings.
pub agents: app_settings::Agents,
pub ui: app_settings::UiSettings,
/// The duration between application update checks in seconds. If `0`, no update checks will be performed.
/// This setting controls background update checks for both the CLI and GUI.
Expand Down
6 changes: 5 additions & 1 deletion crates/but-testsupport/src/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,17 @@ impl Sandbox {
use but_settings::{
AppSettings,
app_settings::{
Claude, ExtraCsp, FeatureFlags, Fetch, GitHubOAuthAppSettings, Reviews,
Agents, Claude, ExtraCsp, FeatureFlags, Fetch, GitHubOAuthAppSettings, Reviews,
TelemetrySettings, UiSettings,
},
};
let settings = AppSettings {
context_lines: 3,
onboarding_complete: true,
// Tests never see the agent-skills prompt.
agents: Agents {
skills_prompt_dismissed: true,
},
telemetry: TelemetrySettings {
app_metrics_enabled: false,
app_error_reporting_enabled: false,
Expand Down
10 changes: 9 additions & 1 deletion crates/gitbutler-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use anyhow::{Context, bail};
use but_api::{
bitbucket, branch, commit, diff, github, gitlab, land, legacy, open, platform, resolve,
agents, bitbucket, branch, commit, diff, github, gitlab, land, legacy, open, platform, resolve,
workspace,
};
use but_settings::AppSettingsWithDiskSync;
Expand Down Expand Up @@ -335,6 +335,13 @@ fn main() -> anyhow::Result<()> {
legacy::forge::tauri_update_review_footers::update_review_footers,
legacy::cli::tauri_install_cli::install_cli,
legacy::cli::tauri_cli_path::cli_path,
agents::tauri_cli_install_state::cli_install_state,
agents::tauri_uninstall_cli::uninstall_cli,
agents::tauri_agents_status::agents_status,
agents::tauri_agent_skill_install::agent_skill_install,
agents::tauri_agent_skill_uninstall::agent_skill_uninstall,
Comment on lines +338 to +342
agents::tauri_agent_policy_get::agent_policy_get,
agents::tauri_agent_policy_set::agent_policy_set,
legacy::workspace::tauri_head_info::head_info,
legacy::workspace::tauri_branch_details::branch_details,
legacy::workspace::tauri_discard_worktree_changes::discard_worktree_changes,
Expand Down Expand Up @@ -363,6 +370,7 @@ fn main() -> anyhow::Result<()> {
settings::update_feature_flags,
settings::update_telemetry_distinct_id,
settings::update_fetch,
settings::update_agents,
settings::update_reviews,
settings::update_ui,
// Debug-only - not for production!
Expand Down
14 changes: 13 additions & 1 deletion crates/gitbutler-tauri/src/settings.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use but_api::{json::Error, legacy::settings};
use but_settings::{
AppSettings, AppSettingsWithDiskSync,
api::{FeatureFlagsUpdate, FetchUpdate, ReviewsUpdate, TelemetryUpdate, UiUpdate},
api::{
AgentsUpdate, FeatureFlagsUpdate, FetchUpdate, ReviewsUpdate, TelemetryUpdate, UiUpdate,
},
};
use tauri::State;
use tracing::instrument;
Expand Down Expand Up @@ -68,6 +70,16 @@ pub fn update_fetch(
.map_err(Into::into)
}

#[tauri::command(async)]
#[instrument(skip(app_settings_sync), err(Debug))]
pub fn update_agents(
app_settings_sync: State<'_, AppSettingsWithDiskSync>,
update: AgentsUpdate,
) -> Result<(), Error> {
settings::update_agents(&app_settings_sync, settings::UpdateAgentsParams { update })
.map_err(Into::into)
}

#[tauri::command(async)]
#[instrument(skip(app_settings_sync), err(Debug))]
pub fn update_reviews(
Expand Down
Loading
Loading