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
|
|
@ -13,10 +13,11 @@
|
|||
//! Run with:
|
||||
//! `cargo test -p xai-grok-pager --test pty_auto_mode -- --ignored --nocapture`
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use xai_grok_pager_pty_harness::{PtyHarness, pager_binary};
|
||||
use xai_grok_test_support::TestSandbox;
|
||||
|
||||
const ROWS: u16 = 40;
|
||||
const COLS: u16 = 120;
|
||||
|
|
@ -48,9 +49,13 @@ fn dirs_next_home() -> Option<PathBuf> {
|
|||
/// Sandbox HOME + optional auth.json seed (no secrets logged), with the
|
||||
/// auto-permission-mode feature gate pinned explicitly via `gate_on` so each
|
||||
/// test is self-contained and deterministic regardless of the runner's shell.
|
||||
fn prepare_sandbox(home: &Path, gate_on: bool) -> Vec<(String, String)> {
|
||||
let grok = home.join(".grok");
|
||||
let _ = std::fs::create_dir_all(&grok);
|
||||
fn prepare_sandbox(sandbox: &mut TestSandbox, gate_on: bool) -> Vec<(String, String)> {
|
||||
// Remove rather than empty the fake API key so seeded OIDC remains authoritative.
|
||||
sandbox.remove_env("XAI_API_KEY");
|
||||
|
||||
let home = sandbox.home();
|
||||
let grok = sandbox.grok_home();
|
||||
let _ = std::fs::create_dir_all(grok);
|
||||
if let Some(src) = auth_json_source() {
|
||||
let dest = grok.join("auth.json");
|
||||
if let Err(e) = std::fs::copy(&src, &dest) {
|
||||
|
|
@ -68,8 +73,6 @@ fn prepare_sandbox(home: &Path, gate_on: bool) -> Vec<(String, String)> {
|
|||
|
||||
let home_s = home.display().to_string();
|
||||
let mut env = vec![
|
||||
("HOME".into(), home_s.clone()),
|
||||
("GROK_HOME".into(), grok.display().to_string()),
|
||||
("XDG_CONFIG_HOME".into(), format!("{home_s}/.config")),
|
||||
("XDG_DATA_HOME".into(), format!("{home_s}/.local/share")),
|
||||
("XDG_CACHE_HOME".into(), format!("{home_s}/.cache")),
|
||||
|
|
@ -78,7 +81,6 @@ fn prepare_sandbox(home: &Path, gate_on: bool) -> Vec<(String, String)> {
|
|||
("NO_COLOR".into(), "0".into()),
|
||||
("TERM_PROGRAM".into(), "".into()),
|
||||
("TMUX".into(), "".into()),
|
||||
// Do not set XAI_API_KEY — prefer OIDC entry in auth.json (pty_e2e pattern).
|
||||
];
|
||||
// Pin the feature gate explicitly so the cycle is deterministic regardless
|
||||
// of the developer's shell. `GROK_AUTO_PERMISSION_MODE` is the highest gate
|
||||
|
|
@ -115,15 +117,16 @@ fn pty_shift_tab_cycles_to_auto_mode_banner() {
|
|||
Ok(b) => b,
|
||||
Err(e) => panic!("resolve pager binary via harness env: {e:#}"),
|
||||
};
|
||||
let tmp = tempfile::tempdir().expect("temp HOME");
|
||||
let env_owned = prepare_sandbox(tmp.path(), true);
|
||||
let mut sandbox = TestSandbox::new();
|
||||
let env_owned = prepare_sandbox(&mut sandbox, true);
|
||||
let env_refs: Vec<(&str, &str)> = env_owned
|
||||
.iter()
|
||||
.map(|(k, v)| (k.as_str(), v.as_str()))
|
||||
.collect();
|
||||
|
||||
let mut harness = PtyHarness::new(&binary, ROWS, COLS, &[], &env_refs)
|
||||
.expect("spawn pager in PTY (xai-grok-pager-pty-harness)");
|
||||
let mut harness =
|
||||
PtyHarness::new_in_sandbox(&binary, ROWS, COLS, &[], &sandbox, &env_refs, None)
|
||||
.expect("spawn pager in PTY (xai-grok-pager-pty-harness)");
|
||||
|
||||
// Drain startup; welcome or agent chrome.
|
||||
let _ = harness.wait_for_text(WELCOME_SCREEN_SENTINEL, WELCOME_TIMEOUT);
|
||||
|
|
@ -145,8 +148,9 @@ fn pty_shift_tab_cycles_to_auto_mode_banner() {
|
|||
see the permission_auto_mode SessionActor wire tests for coverage."
|
||||
);
|
||||
// Still prove we exercised PtyHarness spawn (not a no-op).
|
||||
let running = harness.is_running().expect("poll pager liveness");
|
||||
assert!(
|
||||
harness.is_running() || !early.is_empty(),
|
||||
running || !early.is_empty(),
|
||||
"pager must have produced output even on login screen"
|
||||
);
|
||||
let _ = harness.inject_keys(b"\x11"); // ctrl+q if bound
|
||||
|
|
@ -199,15 +203,16 @@ fn pty_shift_tab_skips_auto_when_gate_off() {
|
|||
Ok(b) => b,
|
||||
Err(e) => panic!("resolve pager binary via harness env: {e:#}"),
|
||||
};
|
||||
let tmp = tempfile::tempdir().expect("temp HOME");
|
||||
let env_owned = prepare_sandbox(tmp.path(), false);
|
||||
let mut sandbox = TestSandbox::new();
|
||||
let env_owned = prepare_sandbox(&mut sandbox, false);
|
||||
let env_refs: Vec<(&str, &str)> = env_owned
|
||||
.iter()
|
||||
.map(|(k, v)| (k.as_str(), v.as_str()))
|
||||
.collect();
|
||||
|
||||
let mut harness = PtyHarness::new(&binary, ROWS, COLS, &[], &env_refs)
|
||||
.expect("spawn pager in PTY (xai-grok-pager-pty-harness)");
|
||||
let mut harness =
|
||||
PtyHarness::new_in_sandbox(&binary, ROWS, COLS, &[], &sandbox, &env_refs, None)
|
||||
.expect("spawn pager in PTY (xai-grok-pager-pty-harness)");
|
||||
|
||||
let _ = harness.wait_for_text(WELCOME_SCREEN_SENTINEL, WELCOME_TIMEOUT);
|
||||
let early = harness.screen_contents();
|
||||
|
|
@ -219,8 +224,9 @@ fn pty_shift_tab_skips_auto_when_gate_off() {
|
|||
eprintln!(
|
||||
"pty_auto_mode(gate off): login/device-auth screen blocked cycle; env auth limit"
|
||||
);
|
||||
let running = harness.is_running().expect("poll pager liveness");
|
||||
assert!(
|
||||
harness.is_running() || !early.is_empty(),
|
||||
running || !early.is_empty(),
|
||||
"pager must have produced output even on login screen"
|
||||
);
|
||||
let _ = harness.inject_keys(b"\x11");
|
||||
|
|
|
|||
Loading…
Reference in a new issue