Synced from monorepo
Changes: - grok-shell: request workspaces:read/write OAuth2 scopes - security: fix SSRF bypass via HTTP redirect in hook runner - fix(grok-build): enterprise STT WSS URL + API-key voice bearer - Harden identity-change purge and sync-marker invariants - sandbox + workspace-server: delete the legacy ready-file arm - Show billing URL when browser cannot open - fix(pager): show folder-trust UI in minimal mode - fix(pager): drain task_backgrounded before no-wait headless exit - grok-agent-sdk: stop SDK-spawned agents from staging self-updates they can never adopt - Split settings_modal into directory module - Delegate VS Code SSH file links - grok-shell: release the workspace session binding when a session is removed - keep skills reachable when their name collides with a client builtin - Preserve semantic link targets
This commit is contained in:
parent
c68e39f604
commit
8adf9013a0
117 changed files with 16998 additions and 14540 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "xai-grok-pager-bin"
|
||||
version = "0.1.220-alpha.4"
|
||||
version = "0.2.101"
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
authors = ["xAI"]
|
||||
|
|
@ -92,6 +92,5 @@ default-bazel = [
|
|||
"sandbox-enforce",
|
||||
]
|
||||
jemalloc = ["dep:tikv-jemallocator", "dep:tikv-jemalloc-sys", "dep:tikv-jemalloc-ctl"]
|
||||
# Forward the sandbox-enforcement feature to the library.
|
||||
sandbox-enforce = ["xai-grok-pager/sandbox-enforce"]
|
||||
release-dist = ["xai-grok-pager/release-dist"]
|
||||
|
|
|
|||
|
|
@ -200,6 +200,11 @@ async fn run_setup_command(json: bool) {
|
|||
"Your team doesn't have a managed configuration yet. A team admin can set one up at console.x.ai."
|
||||
);
|
||||
}
|
||||
SetupOutcome::Skipped => {
|
||||
eprintln!(
|
||||
"Managed configuration was not applied this run (another process held the apply lock, or the credential changed during the fetch). Run `grok setup` again."
|
||||
);
|
||||
}
|
||||
SetupOutcome::Failed(e) => {
|
||||
eprintln!("Couldn't apply managed configuration. {e}");
|
||||
std::process::exit(1);
|
||||
|
|
@ -1081,9 +1086,16 @@ async fn run_agent_command(
|
|||
leader_eligible,
|
||||
);
|
||||
tracing::info!(use_leader, ?policy_disable_reason, "leader mode resolved");
|
||||
if stdio_direct_update_eligible(is_stdio, use_leader)
|
||||
&& should_check_for_updates(no_auto_update)
|
||||
{
|
||||
let managed_install = is_managed_install(
|
||||
std::env::current_exe().ok(),
|
||||
&xai_grok_shell::util::grok_home::grok_home(),
|
||||
);
|
||||
if stdio_auto_update_enabled(
|
||||
is_stdio,
|
||||
use_leader,
|
||||
should_check_for_updates(no_auto_update),
|
||||
managed_install,
|
||||
) {
|
||||
let update_config = update_config.clone();
|
||||
tokio::spawn(async move {
|
||||
auto_update::run_update_if_available(
|
||||
|
|
@ -1094,6 +1106,8 @@ async fn run_agent_command(
|
|||
.await
|
||||
.ok();
|
||||
});
|
||||
} else if is_stdio && !use_leader && !managed_install {
|
||||
tracing::debug!("stdio auto-update skipped: not the managed install");
|
||||
}
|
||||
if use_leader {
|
||||
if !agent_args.plugin_dirs.is_empty() {
|
||||
|
|
@ -2082,8 +2096,8 @@ fn build_update_config() -> UpdateConfig {
|
|||
}
|
||||
config
|
||||
}
|
||||
/// Centralized gate for all auto-update checks. Add new suppression
|
||||
/// rules here — not at each call site.
|
||||
/// Central gate for auto-update checks; add new suppression rules here,
|
||||
/// not at call sites.
|
||||
fn should_check_for_updates(no_auto_update_flag: bool) -> bool {
|
||||
if cfg!(debug_assertions) {
|
||||
return false;
|
||||
|
|
@ -2091,21 +2105,35 @@ fn should_check_for_updates(no_auto_update_flag: bool) -> bool {
|
|||
if no_auto_update_flag {
|
||||
return false;
|
||||
}
|
||||
if std::env::var_os("GROK_DISABLE_AUTOUPDATER").is_some() {
|
||||
!std::env::var_os("GROK_DISABLE_AUTOUPDATER")
|
||||
.is_some_and(|v| env_flag_enabled(&v.to_string_lossy()))
|
||||
}
|
||||
/// Gate for the stdio agent's background auto-update: only the direct stdio
|
||||
/// agent, from the managed install. Other modes update in `run_agent_command`.
|
||||
fn stdio_auto_update_enabled(
|
||||
is_stdio: bool,
|
||||
use_leader: bool,
|
||||
updates_enabled: bool,
|
||||
managed_install: bool,
|
||||
) -> bool {
|
||||
is_stdio && !use_leader && updates_enabled && managed_install
|
||||
}
|
||||
/// True when `exe` is the binary `<grok_home>/bin/grok` resolves to, the
|
||||
/// install that adopts a staged update on respawn. Both sides are
|
||||
/// canonicalized; any failure reports unmanaged and skips the update. The
|
||||
/// npm shim hardcodes `~/.grok`, so a custom `GROK_HOME` skips here too.
|
||||
fn is_managed_install(exe: Option<std::path::PathBuf>, grok_home: &std::path::Path) -> bool {
|
||||
if grok_home.as_os_str().is_empty() {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
/// Mode-gate for the direct stdio agent's background auto-update.
|
||||
///
|
||||
/// Only the *direct* stdio agent is newly eligible: every other agent mode
|
||||
/// already self-updates at the top of `run_agent_command`, and a leader-backed
|
||||
/// stdio process is a thin bridge whose updates are owned by the leader
|
||||
/// (`LeaderAutoUpdateConfig`). Update suppression (`--no-auto-update`,
|
||||
/// `GROK_DISABLE_AUTOUPDATER`, debug builds) is layered on separately via
|
||||
/// [`should_check_for_updates`].
|
||||
fn stdio_direct_update_eligible(is_stdio: bool, use_leader: bool) -> bool {
|
||||
is_stdio && !use_leader
|
||||
let Some(exe) = exe else {
|
||||
return false;
|
||||
};
|
||||
let managed = xai_grok_config::grok_application_in(grok_home);
|
||||
match (dunce::canonicalize(&exe), dunce::canonicalize(&managed)) {
|
||||
(Ok(exe), Ok(managed)) => exe == managed,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
/// Map the mutually-exclusive channel flags to a channel name. clap enforces
|
||||
/// that at most one is set, so the order is irrelevant.
|
||||
|
|
@ -2380,27 +2408,55 @@ mod tests {
|
|||
xai_grok_shell::heap_profile::dump_to_path(dump.path()).expect("shell dump");
|
||||
dump.assert_nonempty_dump();
|
||||
}
|
||||
/// Only the direct (non-leader) stdio agent is newly eligible for the
|
||||
/// background auto-update. Leader-backed stdio defers to the leader's own
|
||||
/// updater, and non-stdio modes already update at the top of
|
||||
/// `run_agent_command`.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn stdio_direct_update_eligible_only_for_non_leader_stdio() {
|
||||
fn is_managed_install_matches_only_the_bin_grok_target() {
|
||||
let home =
|
||||
std::env::temp_dir().join(format!("grok-pager-managed-install-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&home);
|
||||
std::fs::create_dir_all(home.join("bin")).unwrap();
|
||||
std::fs::create_dir_all(home.join("downloads")).unwrap();
|
||||
assert!(!is_managed_install(
|
||||
Some(home.join("bin").join("grok")),
|
||||
&home
|
||||
));
|
||||
assert!(!is_managed_install(None, &home));
|
||||
assert!(!is_managed_install(
|
||||
Some(home.join("bin").join("grok")),
|
||||
std::path::Path::new("")
|
||||
));
|
||||
let target = home.join("downloads").join("grok-1.2.3");
|
||||
std::fs::write(&target, b"binary").unwrap();
|
||||
std::os::unix::fs::symlink(&target, home.join("bin").join("grok")).unwrap();
|
||||
assert!(is_managed_install(
|
||||
Some(home.join("bin").join("grok")),
|
||||
&home
|
||||
));
|
||||
assert!(is_managed_install(Some(target.clone()), &home));
|
||||
let pinned = home.join("bin").join("grok-9.9.9");
|
||||
std::fs::write(&pinned, b"binary").unwrap();
|
||||
assert!(!is_managed_install(Some(pinned), &home));
|
||||
let _ = std::fs::remove_dir_all(&home);
|
||||
}
|
||||
/// Pins the gate composition; a dropped conjunct fails its named case.
|
||||
#[test]
|
||||
fn stdio_auto_update_requires_direct_stdio_enabled_and_managed() {
|
||||
assert!(stdio_auto_update_enabled(true, false, true, true));
|
||||
assert!(
|
||||
stdio_direct_update_eligible(true, false),
|
||||
"direct stdio agent should be eligible",
|
||||
!stdio_auto_update_enabled(true, true, true, true),
|
||||
"leader bridge"
|
||||
);
|
||||
assert!(
|
||||
!stdio_direct_update_eligible(true, true),
|
||||
"leader-backed stdio defers to the leader's updater",
|
||||
!stdio_auto_update_enabled(false, false, true, true),
|
||||
"non-stdio"
|
||||
);
|
||||
assert!(
|
||||
!stdio_direct_update_eligible(false, false),
|
||||
"non-stdio modes update at the top of run_agent_command",
|
||||
!stdio_auto_update_enabled(true, false, false, true),
|
||||
"updates off"
|
||||
);
|
||||
assert!(
|
||||
!stdio_direct_update_eligible(false, true),
|
||||
"non-stdio leader path is not stdio-eligible",
|
||||
!stdio_auto_update_enabled(true, false, true, false),
|
||||
"pinned binary"
|
||||
);
|
||||
}
|
||||
use clap::Parser as _;
|
||||
|
|
|
|||
Loading…
Reference in a new issue