Synced from monorepo
Changes: - Gate session-lifecycle heap steady state with a dhat soak - Unbreak merge lifecycle e2e after default model → grok-4.5 - Scan home-scope rules dirs at <root>/rules - Complete text-input paste and terminal parity - Gate project roles and personas - Use canonical editing in dialogs - Use canonical editing in search bars - Reject ambiguous MCP tool IDs - Harden Git operands for plugins - Simplify queue drain API - Pass RFC 9207 iss through MCP OAuth token exchange - Show leader roster when local agents map is empty - Use canonical editing in Persona views - Remove marketplace default-skills auto-install and purge old installs - Use canonical editing in extension forms - Add canonical dashboard text editing - Use canonical editing in settings - Add /summarize as a /recap alias - Restore previous agent when exiting dashboard - Use tool_choice auto for compaction - Settings toggle for snap-prompt-to-top on send - Update default models to grok-4.5 - Source login shell once for local bash (env + alias/function snapshot) - Template hardcoded param names in server-native tool descriptions - Fix System-Reminder XML tag injection in CLAUDE.md via agents_md - Fix remote workspace-server hardcoding LSP trust (repo code execution risk) - Clear orphaned tool-call updates at turn end - Suppress task wake after cancel - Send x-grok-client-identifier on direct API tool calls - Harden dashboard peek lease transitions - Host /btw side panel in live region (minimal mode) - Bound scroll presentation latency - Highlight multi-line constructs correctly in diffs and the file viewer - Block web_fetch non-public IPs; local opt-in is explicit-host only - Seed coding_data_retention_opt_out=false for OAuth e2es in pty-harness - Follow up clipboard delivery feedback - Use canonical editing in pickers - Route TextArea through canonical editor - Persistent "watching" status row; quieter turn markers - Gate sensitive edit targets - Expose agent registry counts and gate session churn on them - Default coding data sharing to opt-out until server preference applies - Wire chat attachment ids through gateway prompts - On auth refresh failure, issue retry - Forward preview provenance and computer lifecycle state - Document independent privacy controls and scope /privacy output - Strip SamplingError Display prefix on rate-limit UI copy - Stop dumping Cloudflare HTML into Retry failed - Disable in-place prompt edit (scroll jank on enter) - Strip forced ANSI color from gh pr view JSON - Plumb bash tool description onto ToolUsageCard wire
This commit is contained in:
parent
98c3b2438a
commit
7cfcb20d2b
292 changed files with 23315 additions and 9209 deletions
|
|
@ -88,7 +88,9 @@ pub(super) async fn fetch_plugin_cta_mcps(
|
|||
pub(super) fn format_acp_error(err: &acp::Error, is_api_key_auth: bool) -> String {
|
||||
if i32::from(err.code) == RATE_LIMITED_ERROR_CODE {
|
||||
let detail = err.data.as_ref().and_then(error_detail_from_data);
|
||||
return format_rate_limited_user_message(detail.as_deref(), is_api_key_auth);
|
||||
return sanitize_user_error(
|
||||
&format_rate_limited_user_message(detail.as_deref(), is_api_key_auth),
|
||||
);
|
||||
}
|
||||
if err.code == acp::ErrorCode::InvalidParams && let Some(data) = &err.data
|
||||
&& let Some(msg) = error_detail_from_data(data) && !msg.is_empty()
|
||||
|
|
@ -790,6 +792,14 @@ pub(crate) async fn persist_setting(
|
|||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
"page_flip_on_send" => {
|
||||
let SettingValue::Bool(b) = value else {
|
||||
return Err(kind_mismatch("page_flip_on_send", "Bool", &value));
|
||||
};
|
||||
xai_grok_shell::util::config::set_page_flip_on_send(b)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
"show_timeline" => {
|
||||
let SettingValue::Bool(b) = value else {
|
||||
return Err(kind_mismatch("show_timeline", "Bool", &value));
|
||||
|
|
|
|||
|
|
@ -66,11 +66,13 @@ pub(crate) fn execute(
|
|||
tracing::warn!(error = % e, "project picker: failed to set_current_dir");
|
||||
}
|
||||
}
|
||||
Effect::ScheduleClearAuthCopied => {
|
||||
Effect::ScheduleClearAuthCopyFeedback { generation } => {
|
||||
tasks
|
||||
.spawn(async {
|
||||
.spawn(async move {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||
TaskResult::AuthCopiedTimeout
|
||||
TaskResult::AuthCopyFeedbackTimeout {
|
||||
generation,
|
||||
}
|
||||
});
|
||||
}
|
||||
Effect::Logout => {
|
||||
|
|
@ -3302,7 +3304,7 @@ pub(crate) fn execute(
|
|||
}
|
||||
});
|
||||
}
|
||||
Effect::SendBtw { agent_id, session_id, question } => {
|
||||
Effect::SendBtw { agent_id, session_id, question, minimal_request_id } => {
|
||||
let tx = acp_tx.clone();
|
||||
tasks
|
||||
.spawn(async move {
|
||||
|
|
@ -3332,6 +3334,7 @@ pub(crate) fn execute(
|
|||
TaskResult::BtwResponse {
|
||||
agent_id,
|
||||
result: Ok(answer),
|
||||
minimal_request_id,
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
@ -3340,6 +3343,7 @@ pub(crate) fn execute(
|
|||
result: Err(
|
||||
sanitize_user_error(&format!("side question failed: {e}")),
|
||||
),
|
||||
minimal_request_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,26 +22,37 @@ fn format_acp_error_rate_limit_surfaces_detail_or_fallback() {
|
|||
FREE_USAGE_USER_MESSAGE, RATE_LIMITED_ERROR_CODE,
|
||||
RATE_LIMITED_USER_MESSAGE_API_KEY, RATE_LIMITED_USER_MESSAGE_OAUTH,
|
||||
};
|
||||
let cap_body = "The service is temporarily at capacity. Please retry your request shortly.";
|
||||
let capacity = acp::Error::new(RATE_LIMITED_ERROR_CODE, "Rate limited")
|
||||
.data(
|
||||
"The service is temporarily at capacity. Please retry your request shortly.",
|
||||
);
|
||||
let cap = "The service is temporarily at capacity. Please retry your request shortly.";
|
||||
assert_eq!(format_acp_error(& capacity, false), cap);
|
||||
assert_eq!(format_acp_error(& capacity, true), cap);
|
||||
.data(format!("API error (status 429 Too Many Requests): {cap_body}"));
|
||||
assert_eq!(format_acp_error(& capacity, false), cap_body);
|
||||
assert_eq!(format_acp_error(& capacity, true), cap_body);
|
||||
let rpm_body = "You are sending requests too quickly. Please slow down, or upgrade to a Grok subscription for higher limits: https://grok.com/supergrok";
|
||||
let rpm = acp::Error::new(RATE_LIMITED_ERROR_CODE, "Rate limited")
|
||||
.data(
|
||||
"You are sending requests too quickly. Please slow down, or upgrade to a Grok subscription for higher limits: https://grok.com/supergrok",
|
||||
);
|
||||
.data(format!("API error (status 429 Too Many Requests): {rpm_body}"));
|
||||
assert!(format_acp_error(& rpm, false).contains("grok.com/supergrok"));
|
||||
assert_eq!(format_acp_error(& rpm, true), RATE_LIMITED_USER_MESSAGE_API_KEY);
|
||||
let empty = acp::Error::new(RATE_LIMITED_ERROR_CODE, "Rate limited");
|
||||
assert_eq!(format_acp_error(& empty, false), RATE_LIMITED_USER_MESSAGE_OAUTH);
|
||||
assert_eq!(format_acp_error(& empty, true), RATE_LIMITED_USER_MESSAGE_API_KEY);
|
||||
let free = acp::Error::new(RATE_LIMITED_ERROR_CODE, "Rate limited")
|
||||
.data("subscription:free-usage-exhausted: You have used all your free usage.");
|
||||
.data(
|
||||
"API error (status 429 Too Many Requests): \
|
||||
subscription:free-usage-exhausted: You have used all your free usage.",
|
||||
);
|
||||
assert_eq!(format_acp_error(& free, false), FREE_USAGE_USER_MESSAGE);
|
||||
assert_eq!(format_acp_error(& free, true), FREE_USAGE_USER_MESSAGE);
|
||||
let free_wrapped = acp::Error::new(RATE_LIMITED_ERROR_CODE, "Rate limited")
|
||||
.data(
|
||||
serde_json::json!(
|
||||
{ "message" :
|
||||
"API error (status 429 Too Many Requests): \
|
||||
subscription:free-usage-exhausted: You have used all your free usage.",
|
||||
"promptUsage" : { "inputTokens" : 12, "outputTokens" : 0, "numTurns" : 1
|
||||
} }
|
||||
),
|
||||
);
|
||||
assert_eq!(format_acp_error(& free_wrapped, false), FREE_USAGE_USER_MESSAGE);
|
||||
}
|
||||
/// Non-empty token ranges ride the wire block meta as `skillTokenRanges`
|
||||
/// byte pairs; the text itself is untouched.
|
||||
|
|
@ -701,6 +712,16 @@ async fn persist_setting_type_mismatch_errors_show_timeline() {
|
|||
"error message must mention key + expected kind, got: {err}",
|
||||
);
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn persist_setting_type_mismatch_errors_page_flip_on_send() {
|
||||
use crate::settings::SettingValue;
|
||||
let r = persist_setting("page_flip_on_send", SettingValue::String("nope".into()))
|
||||
.await;
|
||||
let err = r.expect_err("page_flip_on_send with String payload must return Err");
|
||||
assert!(
|
||||
err.contains("persist_setting(page_flip_on_send) expected Bool"), "got: {err}",
|
||||
);
|
||||
}
|
||||
/// Type-mismatch for `simple_mode`.
|
||||
#[tokio::test]
|
||||
async fn persist_setting_type_mismatch_errors_simple_mode() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue