Synced from monorepo
Changes: - Non-blocking coding-data sharing upsell banner - Consolidate remediation in Doctor - Auto mode defers fail-closed gate asks to the classifier - Coalesce marketplace list fetches - Allow removing a marketplace source by name - Contain hung git marketplace sources (timeouts, non-blocking refresh, unbrick modal) - Label failed workspace RPCs with error_kind - Drop redundant explicit tonic/prost deps from xai-grok-shell - Report real exit codes for completed background shells - Narrow the date-rollover reminder to date-bearing templates - Wire toolOverrides through the session and agent - Security: Bash(git:*) allowlist matches whole command chain by prefix - Split prompt-trigger telemetry and record classifier provenance - Raise connectors-manager timeout to 60s - Auto classifier honors recorded approvals for repeat actions - Apply doctor fixes in the TUI - Auto-mode classifier timeouts prompt instead of silently denying - Scope subagent completion drains to the owning session - Add the toolOverrides wire types - Set client_identifier=grok-agent-sdk - Accept both spellings of the workspace-teleport kill switch - Persist one-shot occurrence journal - Stop turns that poll the exact same tool call 16x in a row - Copy compaction checkpoint files when forking sessions - Auto-focus permission prompt from scrollback - Esc cancels the running turn in non-vim and minimal modes - List Ctrl+Z undo and redo in keyboard shortcuts - Out-of-process macOS mic capture - Show active auth mode on session-info - Install the npm binary under $GROK_HOME - Remove hover/click dead zones between dashboard items - Route startup warnings to doctor - Document [feedback.user] author identity config - Extend bang command timeout - Close combine-queued edit-hold race - Integrate relocation recovery - Expose privacy notice rollout flag - Break harness discovery ref cycle so connections can idle-evict - Shift/Alt+Enter inserts newline when editing a queued prompt - Gate project Claude permissions on folder trust - Echo response.create.event_id on response.created - Toast when session creation fails from disk full - Add shared test process lifecycle - Enable dynamic workflows by default - Add relocation transaction state machine - Add shared test sandbox - Surface auth failures on model-switch compact - Persist durable scheduler expiry - Confirm before removing extensions-modal items - Re-run compact and prompt after login when compact hit expired auth - Recap sends hosted tools under backend search
This commit is contained in:
parent
3af4d5d398
commit
a5727c5960
482 changed files with 37627 additions and 13402 deletions
|
|
@ -134,22 +134,15 @@ pub(super) fn set_coding_data_sharing(app: &mut AppView, opted_in: bool) -> Vec<
|
|||
return vec![];
|
||||
}
|
||||
}
|
||||
// ── Guard 3: an agent must exist to thread the ACP call through ──
|
||||
// Synthetic AgentId(0) when no agents (welcome banner Accept).
|
||||
let agent_id = match app.active_view {
|
||||
crate::app::app_view::ActiveView::Agent(id) => id,
|
||||
_ => match app.agents.keys().next().copied() {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
tracing::warn!(
|
||||
target: "settings",
|
||||
key = "coding_data_sharing",
|
||||
opted_in,
|
||||
"set_coding_data_sharing called with no agents — unreachable in \
|
||||
practice; returning empty (no toast: app.show_toast would no-op)",
|
||||
);
|
||||
return vec![];
|
||||
}
|
||||
},
|
||||
_ => app
|
||||
.agents
|
||||
.keys()
|
||||
.next()
|
||||
.copied()
|
||||
.unwrap_or(crate::app::agent::AgentId(0)),
|
||||
};
|
||||
|
||||
let prev = !app.coding_data_retention_opt_out;
|
||||
|
|
@ -438,14 +431,13 @@ pub(super) fn handle_coding_data_sharing_updated(
|
|||
agent_id: AgentId,
|
||||
opted_in: bool,
|
||||
) -> Vec<Effect> {
|
||||
// Re-anchor mirror to server-confirmed value (defense-in-
|
||||
// depth against server reshaping the boolean). `agent_id`
|
||||
// discarded — privacy is app-level, not per-agent.
|
||||
// Re-anchor mirror to server-confirmed value (defense-in-depth against
|
||||
// server reshaping the boolean). `agent_id` discarded — privacy is
|
||||
// app-level, not per-agent.
|
||||
set_coding_data_sharing_inner(app, opted_in);
|
||||
refresh_open_settings_modals(app);
|
||||
// Re-toast on confirmation. Without this, a slow ACP
|
||||
// round-trip would leave the user with only the
|
||||
// optimistic toast (already faded) and no
|
||||
// Re-toast on confirmation. Without this, a slow ACP round-trip would
|
||||
// leave the user with only the optimistic toast (already faded) and no
|
||||
// server-confirmed feedback.
|
||||
app.show_toast(&coding_data_sharing_toast(opted_in));
|
||||
tracing::info!(
|
||||
|
|
@ -455,7 +447,15 @@ pub(super) fn handle_coding_data_sharing_updated(
|
|||
opted_in,
|
||||
"ACP update confirmed; mirror re-anchored",
|
||||
);
|
||||
vec![]
|
||||
let mut effects = vec![];
|
||||
// Ack only after successful opt-in from the privacy banner Accept path.
|
||||
if app.privacy_banner_accept_inflight {
|
||||
app.privacy_banner_accept_inflight = false;
|
||||
if opted_in {
|
||||
effects.extend(ack_privacy_banner(app));
|
||||
}
|
||||
}
|
||||
effects
|
||||
}
|
||||
|
||||
pub(super) fn handle_coding_data_sharing_failed(
|
||||
|
|
@ -464,9 +464,8 @@ pub(super) fn handle_coding_data_sharing_failed(
|
|||
error: String,
|
||||
rollback_to_opted_in: bool,
|
||||
) -> Vec<Effect> {
|
||||
// Revert optimistic mutation: inner → refresh → toast.
|
||||
//
|
||||
// `agent_id` discarded — privacy is global.
|
||||
// Revert optimistic mutation: inner → refresh → toast. `agent_id`
|
||||
// discarded — privacy is global.
|
||||
set_coding_data_sharing_inner(app, rollback_to_opted_in);
|
||||
refresh_open_settings_modals(app);
|
||||
// Scrub long/unsafe error strings before toasting.
|
||||
|
|
@ -482,9 +481,46 @@ pub(super) fn handle_coding_data_sharing_failed(
|
|||
%error,
|
||||
"ACP update failed; reverted optimistic mutation",
|
||||
);
|
||||
// Accept failure: no ack; clear inflight so the banner stays.
|
||||
app.privacy_banner_accept_inflight = false;
|
||||
vec![]
|
||||
}
|
||||
|
||||
/// Stamp `[privacy].privacy_banner_acked` (in-memory + disk).
|
||||
pub(in crate::app::dispatch) fn ack_privacy_banner(app: &mut AppView) -> Vec<Effect> {
|
||||
let acked_at = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
|
||||
app.privacy_banner_acked = Some(acked_at.clone());
|
||||
vec![Effect::PersistPrivacyBannerAcked { acked_at }]
|
||||
}
|
||||
|
||||
/// Accept: opt-in via settings path; ack only after ACP success.
|
||||
pub(in crate::app::dispatch) fn dispatch_privacy_banner_accept(app: &mut AppView) -> Vec<Effect> {
|
||||
if app.privacy_banner_accept_inflight || !app.privacy_banner_should_show() {
|
||||
return vec![];
|
||||
}
|
||||
let effects = set_coding_data_sharing(app, true);
|
||||
// should_show guarantees opted-out + unguarded, so effects is only empty
|
||||
// if a guard regresses; leaving inflight false keeps Accept clickable.
|
||||
app.privacy_banner_accept_inflight = !effects.is_empty();
|
||||
effects
|
||||
}
|
||||
|
||||
/// Customize: ack, then open settings on coding_data_sharing
|
||||
/// (creates/switches agent when opened from welcome).
|
||||
pub(in crate::app::dispatch) fn dispatch_privacy_banner_customize(
|
||||
app: &mut AppView,
|
||||
) -> Vec<Effect> {
|
||||
if app.privacy_banner_accept_inflight || !app.privacy_banner_should_show() {
|
||||
return vec![];
|
||||
}
|
||||
let mut effects = ack_privacy_banner(app);
|
||||
effects.extend(super::settings::ui::dispatch_open_settings(
|
||||
app,
|
||||
Some("coding_data_sharing"),
|
||||
));
|
||||
effects
|
||||
}
|
||||
|
||||
pub(super) fn handle_context_info_complete(
|
||||
app: &mut AppView,
|
||||
agent_id: AgentId,
|
||||
|
|
|
|||
Loading…
Reference in a new issue