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:
grokkybara[bot] 2026-07-18 19:48:28 +01:00
commit 7cfcb20d2b
292 changed files with 23315 additions and 9209 deletions

View file

@ -1,4 +1,4 @@
use std::ops::Range;
use std::ops::{Deref, Range};
use std::sync::Arc;
use unicode_segmentation::{GraphemeCursor, UnicodeSegmentation as _};
@ -32,6 +32,35 @@ pub enum EditCommand {
DeleteToLineEnd,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum EditCommandCategory {
Insert,
Navigation,
Delete,
Kill,
}
impl EditCommand {
pub(crate) fn category(self) -> EditCommandCategory {
match self {
Self::Insert(_) => EditCommandCategory::Insert,
Self::MoveGraphemeLeft
| Self::MoveGraphemeRight
| Self::MoveWordLeft(_)
| Self::MoveWordRight(_)
| Self::MoveLogicalLineStart
| Self::MoveLogicalLineEnd => EditCommandCategory::Navigation,
Self::DeleteGraphemeBackward | Self::DeleteGraphemeForward => {
EditCommandCategory::Delete
}
Self::DeleteWordBackward(_)
| Self::DeleteWordForward(_)
| Self::DeleteToLineStart
| Self::DeleteToLineEnd => EditCommandCategory::Kill,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EditDelta {
pub replaced_byte_range: Range<usize>,
@ -155,6 +184,14 @@ impl PartialEq for EditBuffer {
impl Eq for EditBuffer {}
impl Deref for EditBuffer {
type Target = str;
fn deref(&self) -> &Self::Target {
self.text()
}
}
impl EditBuffer {
pub fn new() -> Self {
Self::default()
@ -210,14 +247,14 @@ impl EditBuffer {
#[must_use]
pub fn insert_str(&mut self, text: &str) -> EditOutcome {
let plan = self.plan_replace_byte_range(self.cursor_byte..self.cursor_byte, text, &[]);
self.apply_valid_plan(&plan)
self.apply_validated_plan(&plan)
}
/// Edit-result cursors keep right affinity when adjacent text merges into one grapheme.
#[must_use]
pub fn replace_byte_range(&mut self, range: Range<usize>, replacement: &str) -> EditOutcome {
let plan = self.plan_replace_byte_range(range, replacement, &[]);
self.apply_valid_plan(&plan)
self.apply_validated_plan(&plan)
}
pub fn plan_replace_byte_range(
@ -380,13 +417,13 @@ impl EditBuffer {
pub fn apply_plan(&mut self, plan: &EditPlan) -> Result<EditOutcome, ApplyEditPlanError> {
self.validate_plan(plan)?;
Ok(self.apply_valid_plan(plan))
Ok(self.apply_validated_plan(plan))
}
#[must_use]
pub fn apply(&mut self, command: EditCommand) -> EditOutcome {
let plan = self.plan_command(command, &[]);
self.apply_valid_plan(&plan)
self.apply_validated_plan(&plan)
}
fn make_plan(
@ -408,7 +445,7 @@ impl EditBuffer {
}
}
fn validate_plan(&self, plan: &EditPlan) -> Result<(), ApplyEditPlanError> {
pub(crate) fn validate_plan(&self, plan: &EditPlan) -> Result<(), ApplyEditPlanError> {
if !Arc::ptr_eq(&plan.source_identity, &self.identity)
|| plan.source_generation != self.generation
{
@ -447,7 +484,7 @@ impl EditBuffer {
Ok(())
}
fn apply_valid_plan(&mut self, plan: &EditPlan) -> EditOutcome {
pub(crate) fn apply_validated_plan(&mut self, plan: &EditPlan) -> EditOutcome {
let old_cursor = self.cursor_byte;
let text_changed = plan.removed_text != plan.replacement;
let inserted_len = plan.replacement.len();

View file

@ -4,6 +4,7 @@ use super::{EditCommand, WordStyle};
pub fn classify_key_event(event: &KeyEvent) -> Option<EditCommand> {
match event {
// Some terminals encode Ctrl-B/Ctrl-F as bare C0 characters.
KeyEvent {
code: KeyCode::Char('\u{0002}'),
modifiers: KeyModifiers::NONE,
@ -21,20 +22,21 @@ pub fn classify_key_event(event: &KeyEvent) -> Option<EditCommand> {
} if *modifiers == (KeyModifiers::CONTROL | KeyModifiers::ALT) => {
Some(EditCommand::DeleteWordBackward(WordStyle::Small))
}
// Kitty protocol loss can surface Backspace as raw BS or DEL; modifiers are unreliable.
KeyEvent {
code: KeyCode::Backspace | KeyCode::Char('\u{0008}' | '\u{007f}'),
code: KeyCode::Char('\u{0008}' | '\u{007f}'),
..
} => Some(EditCommand::DeleteGraphemeBackward),
KeyEvent {
code: KeyCode::Backspace,
modifiers,
..
} => Some(backspace_command(*modifiers)),
KeyEvent {
code: KeyCode::Delete,
modifiers: KeyModifiers::ALT | KeyModifiers::CONTROL,
modifiers,
..
} => Some(EditCommand::DeleteWordForward(WordStyle::Small)),
KeyEvent {
code: KeyCode::Delete,
..
} => Some(EditCommand::DeleteGraphemeForward),
} => Some(delete_command(*modifiers)),
KeyEvent {
code: KeyCode::Char('w'),
modifiers: KeyModifiers::CONTROL,
@ -44,14 +46,18 @@ pub fn classify_key_event(event: &KeyEvent) -> Option<EditCommand> {
)),
KeyEvent {
code: KeyCode::Left,
modifiers: KeyModifiers::ALT | KeyModifiers::CONTROL,
modifiers,
..
} => Some(EditCommand::MoveWordLeft(WordStyle::Small)),
} if modifiers.intersects(KeyModifiers::ALT | KeyModifiers::CONTROL) => {
Some(EditCommand::MoveWordLeft(WordStyle::Small))
}
KeyEvent {
code: KeyCode::Right,
modifiers: KeyModifiers::ALT | KeyModifiers::CONTROL,
modifiers,
..
} => Some(EditCommand::MoveWordRight(WordStyle::Small)),
} if modifiers.intersects(KeyModifiers::ALT | KeyModifiers::CONTROL) => {
Some(EditCommand::MoveWordRight(WordStyle::Small))
}
KeyEvent {
code: KeyCode::Char('a'),
modifiers: KeyModifiers::CONTROL,
@ -114,9 +120,11 @@ pub fn classify_key_event(event: &KeyEvent) -> Option<EditCommand> {
} => Some(EditCommand::DeleteGraphemeForward),
KeyEvent {
code: KeyCode::Char('d'),
modifiers: KeyModifiers::ALT | KeyModifiers::SUPER,
modifiers,
..
} => Some(EditCommand::DeleteWordForward(WordStyle::Small)),
} if modifiers.intersects(KeyModifiers::ALT | KeyModifiers::SUPER) => {
Some(EditCommand::DeleteWordForward(WordStyle::Small))
}
KeyEvent {
code: KeyCode::Char(character),
modifiers: KeyModifiers::NONE | KeyModifiers::SHIFT,
@ -149,6 +157,7 @@ fn shifted_char(character: char) -> char {
}
fn backspace_command(modifiers: KeyModifiers) -> EditCommand {
// Backspace preserves exact historical chords; extra modifiers fall back to grapheme delete.
match modifiers {
KeyModifiers::ALT | KeyModifiers::CONTROL => {
EditCommand::DeleteWordBackward(WordStyle::Small)
@ -157,3 +166,12 @@ fn backspace_command(modifiers: KeyModifiers) -> EditCommand {
_ => EditCommand::DeleteGraphemeBackward,
}
}
fn delete_command(modifiers: KeyModifiers) -> EditCommand {
// Delete accepts Shift in addition to a word modifier because enhanced protocols retain it.
if modifiers.intersects(KeyModifiers::ALT | KeyModifiers::CONTROL | KeyModifiers::SUPER) {
EditCommand::DeleteWordForward(WordStyle::Small)
} else {
EditCommand::DeleteGraphemeForward
}
}

View file

@ -168,6 +168,7 @@ fn lifecycle_and_host_owned_keys_remain_unclassified() {
key(KeyCode::Esc, KeyModifiers::NONE),
key(KeyCode::Enter, KeyModifiers::NONE),
key(KeyCode::Tab, KeyModifiers::NONE),
key(KeyCode::Char('\t'), KeyModifiers::NONE),
key(KeyCode::BackTab, KeyModifiers::SHIFT),
key(KeyCode::Up, KeyModifiers::NONE),
key(KeyCode::Down, KeyModifiers::NONE),
@ -209,37 +210,37 @@ fn backspace_delete_and_raw_encodings_have_modifier_parity() {
(
KeyModifiers::SUPER,
EditCommand::DeleteToLineStart,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::CONTROL | KeyModifiers::SHIFT,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::ALT | KeyModifiers::SHIFT,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::SUPER | KeyModifiers::SHIFT,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::CONTROL | KeyModifiers::ALT,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::CONTROL | KeyModifiers::SUPER,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::ALT | KeyModifiers::SUPER,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
(
KeyModifiers::META,
@ -254,7 +255,7 @@ fn backspace_delete_and_raw_encodings_have_modifier_parity() {
(
KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SHIFT,
EditCommand::DeleteGraphemeBackward,
EditCommand::DeleteGraphemeForward,
EditCommand::DeleteWordForward(WordStyle::Small),
),
];
@ -270,11 +271,15 @@ fn backspace_delete_and_raw_encodings_have_modifier_parity() {
Some(expected_delete),
"{delete:?}"
);
assert_eq!(classify_key_event(&raw_bs), backspace_command, "{raw_bs:?}");
assert_eq!(
classify_key_event(&raw_bs),
Some(EditCommand::DeleteGraphemeBackward),
"{raw_bs:?}",
);
assert_eq!(
classify_key_event(&raw_del),
backspace_command,
"{raw_del:?}"
Some(EditCommand::DeleteGraphemeBackward),
"{raw_del:?}",
);
}
}

File diff suppressed because it is too large Load diff