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
|
|
@ -983,6 +983,19 @@ impl SlashController {
|
|||
self.arg_suggestions(command.as_ref(), models, &input.args_query)
|
||||
}
|
||||
|
||||
fn argument_highlight_indices(&mut self, query: &str, display: &str) -> Vec<u32> {
|
||||
let token = query.split_whitespace().next_back().unwrap_or("");
|
||||
let fragment = token.rsplit(['/', '\\']).next().unwrap_or(token);
|
||||
self.matcher
|
||||
.indices_for(fragment, display)
|
||||
.or_else(|| {
|
||||
fragment
|
||||
.rsplit_once('.')
|
||||
.and_then(|(_, suffix)| self.matcher.indices_for(suffix, display))
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Generate argument suggestions for a specific command.
|
||||
fn arg_suggestions(
|
||||
&mut self,
|
||||
|
|
@ -1012,7 +1025,7 @@ impl SlashController {
|
|||
hits.into_iter()
|
||||
.map(|(idx, _)| {
|
||||
let mut row = SuggestionRow::from_arg(&items[idx]);
|
||||
row.indices = self.matcher.indices(row.display.as_str());
|
||||
row.indices = self.argument_highlight_indices(trimmed, &row.display);
|
||||
row
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -2684,6 +2697,11 @@ mod tests {
|
|||
.collect();
|
||||
assert_eq!(rows, vec![("first", true), ("second", false)]);
|
||||
|
||||
ctrl.refresh(&state, "/chain fir", 10, &models);
|
||||
let snap = state.snapshot();
|
||||
assert!(snap.open);
|
||||
assert_eq!(snap.matches[0].indices, vec![0, 1, 2]);
|
||||
|
||||
// Typing "first " triggers the phase-2 sub-menu of terminal rows.
|
||||
ctrl.refresh(&state, "/chain first ", 13, &models);
|
||||
let snap = state.snapshot();
|
||||
|
|
@ -2693,6 +2711,11 @@ mod tests {
|
|||
.map(|r| (r.display.as_str(), r.insert_text.ends_with(' ')))
|
||||
.collect();
|
||||
assert_eq!(rows, vec![("alpha", false), ("beta", false)]);
|
||||
|
||||
ctrl.refresh(&state, "/chain first al", 15, &models);
|
||||
let snap = state.snapshot();
|
||||
assert!(snap.open);
|
||||
assert_eq!(snap.matches[0].indices, vec![0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2712,6 +2735,39 @@ mod tests {
|
|||
assert!(displays.contains(&"/doctor"), "matches: {displays:?}");
|
||||
assert!(!displays.contains(&"/terminal-setup"));
|
||||
|
||||
for text in ["/doctor ", "/terminal-setup "] {
|
||||
ctrl.refresh(&state, text, text.len(), &models);
|
||||
let snapshot = state.snapshot();
|
||||
assert!(!snapshot.open, "bare args opened for {text:?}");
|
||||
assert!(snapshot.matches.is_empty(), "matches for {text:?}");
|
||||
}
|
||||
for (text, inserted, indices) in [
|
||||
("/doctor f", "fix", vec![0]),
|
||||
("/doctor fix s", "fix ssh-wrap", vec![0]),
|
||||
("/doctor fix ssh", "fix ssh-wrap", vec![0, 1, 2]),
|
||||
("/doctor fix terminal.s", "fix ssh-wrap", vec![0]),
|
||||
("/terminal-setup f", "fix", vec![0]),
|
||||
("/terminal-setup fix s", "fix ssh-wrap", vec![0]),
|
||||
] {
|
||||
ctrl.refresh(&state, text, text.len(), &models);
|
||||
let snapshot = state.snapshot();
|
||||
assert!(snapshot.open, "no matches for {text:?}");
|
||||
assert_eq!(snapshot.matches[0].insert_text, inserted);
|
||||
assert_eq!(snapshot.matches[0].indices, indices, "{text:?}");
|
||||
}
|
||||
|
||||
for text in [
|
||||
"/doctor fix ssh-wrap",
|
||||
"/doctor fix terminal.ssh-wrap",
|
||||
"/terminal-setup fix ssh-wrap",
|
||||
"/terminal-setup fix terminal.ssh-wrap",
|
||||
] {
|
||||
ctrl.refresh(&state, text, text.len(), &models);
|
||||
let snapshot = state.snapshot();
|
||||
assert!(!snapshot.open, "exact form left picker open for {text:?}");
|
||||
assert!(snapshot.matches.is_empty(), "matches for {text:?}");
|
||||
}
|
||||
|
||||
let text = "/terminal-setup";
|
||||
ctrl.refresh(&state, text, text.len(), &models);
|
||||
let snapshot = state.snapshot();
|
||||
|
|
|
|||
Loading…
Reference in a new issue