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
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "xai-grok-pager-bin"
|
||||
version = "0.2.109"
|
||||
version = "0.2.110"
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
authors = ["xAI"]
|
||||
|
|
|
|||
|
|
@ -338,13 +338,15 @@ fn print_leader_descriptor(d: &LeaderDescriptor) {
|
|||
eprintln!(" PID {pid} ({state}) -- {sock}");
|
||||
}
|
||||
fn leader_descriptor_json(d: &LeaderDescriptor) -> serde_json::Value {
|
||||
serde_json::json!(
|
||||
{ "pid" : leader_pid(d), "pidFromLock" : d.pid_from_lock, "pidLive" : d.live_info
|
||||
.as_ref().map(| li | li.pid), "classification" : format!("{:?}", d
|
||||
.classification), "socketPath" : d.socket_path.as_deref().map(| p | p.display()
|
||||
.to_string()), "lockPath" : d.lock_path.as_deref().map(| p | p.display()
|
||||
.to_string()), "wsUrlSuffix" : d.ws_url_suffix, }
|
||||
)
|
||||
serde_json::json!({
|
||||
"pid": leader_pid(d),
|
||||
"pidFromLock": d.pid_from_lock,
|
||||
"pidLive": d.live_info.as_ref().map(|li| li.pid),
|
||||
"classification": format!("{:?}", d.classification),
|
||||
"socketPath": d.socket_path.as_deref().map(|p| p.display().to_string()),
|
||||
"lockPath": d.lock_path.as_deref().map(|p| p.display().to_string()),
|
||||
"wsUrlSuffix": d.ws_url_suffix,
|
||||
})
|
||||
}
|
||||
fn leader_info_json(
|
||||
d: &LeaderDescriptor,
|
||||
|
|
@ -588,10 +590,15 @@ fn render_workspace_payload(payload: &ControlPayload, json: bool) {
|
|||
return;
|
||||
};
|
||||
if json {
|
||||
let value = serde_json::json!(
|
||||
{ "state" : state, "hubUrl" : hub_url, "cwd" : cwd, "uptimeMs" : uptime_ms,
|
||||
"activeToolCalls" : active_tool_calls, "sessions" : sessions, "pid" : pid, }
|
||||
);
|
||||
let value = serde_json::json!({
|
||||
"state": state,
|
||||
"hubUrl": hub_url,
|
||||
"cwd": cwd,
|
||||
"uptimeMs": uptime_ms,
|
||||
"activeToolCalls": active_tool_calls,
|
||||
"sessions": sessions,
|
||||
"pid": pid,
|
||||
});
|
||||
println!("{}", serde_json::to_string(&value).unwrap_or_default());
|
||||
return;
|
||||
}
|
||||
|
|
@ -858,17 +865,22 @@ fn replay_load_json(sid: &str, cached: &CachedSession) -> Option<String> {
|
|||
return Some(verbatim.clone());
|
||||
}
|
||||
let cwd = cached.cwd.as_deref()?;
|
||||
let mut params = serde_json::json!({ "sessionId" : sid, "cwd" : cwd, });
|
||||
let mut params = serde_json::json!({
|
||||
"sessionId": sid,
|
||||
"cwd": cwd,
|
||||
});
|
||||
if let Some(ref mcp_raw) = cached.mcp_servers_json
|
||||
&& let Ok(mcp_val) = serde_json::from_str::<serde_json::Value>(mcp_raw)
|
||||
{
|
||||
params["mcpServers"] = mcp_val;
|
||||
}
|
||||
Some(
|
||||
serde_json::json!(
|
||||
{ "jsonrpc" : "2.0", "id" : REPLAY_LOAD_REQUEST_ID, "method" :
|
||||
"session/load", "params" : params, }
|
||||
)
|
||||
serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": REPLAY_LOAD_REQUEST_ID,
|
||||
"method": "session/load",
|
||||
"params": params,
|
||||
})
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
|
@ -908,24 +920,23 @@ async fn replay_acp_state_after_reconnect(
|
|||
let mut restored: Vec<String> = Vec::new();
|
||||
for (sid, cached) in &state.sessions {
|
||||
let Some(load_json) = replay_load_json(sid, cached) else {
|
||||
tracing::warn!(
|
||||
session_id = % sid, "replay: no way to rebuild session/load; skipping"
|
||||
);
|
||||
tracing::warn!(session_id = %sid, "replay: no way to rebuild session/load; skipping");
|
||||
continue;
|
||||
};
|
||||
match replay_request_until_response(tx, rx, stdout, &load_json, "session/load").await {
|
||||
ReplayOutcome::ResponseOk => {
|
||||
tracing::info!(session_id = % sid, "replay: session restored");
|
||||
tracing::info!(session_id = %sid, "replay: session restored");
|
||||
restored.push(sid.clone());
|
||||
}
|
||||
ReplayOutcome::ResponseErr => {
|
||||
tracing::warn!(
|
||||
session_id = % sid, "replay: session/load was rejected by new leader"
|
||||
session_id = %sid,
|
||||
"replay: session/load was rejected by new leader"
|
||||
);
|
||||
}
|
||||
ReplayOutcome::Failed => {
|
||||
tracing::warn!(
|
||||
session_id = % sid,
|
||||
session_id = %sid,
|
||||
"replay: transport failure during session/load; aborting remaining replays"
|
||||
);
|
||||
break;
|
||||
|
|
@ -1022,9 +1033,7 @@ async fn run_agent_command(
|
|||
match std::env::current_dir() {
|
||||
Ok(cwd) => xai_grok_shell::agent::folder_trust::grant_folder_trust(&cwd),
|
||||
Err(e) => {
|
||||
tracing::warn!(
|
||||
error = % e, "--trust: failed to resolve cwd; folder not trusted"
|
||||
)
|
||||
tracing::warn!(error = %e, "--trust: failed to resolve cwd; folder not trusted")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1191,11 +1200,18 @@ async fn run_agent_command(
|
|||
let mut stdin_lines = xai_acp_lib::spawn_stdin_line_reader();
|
||||
loop {
|
||||
tokio::select! {
|
||||
biased; _ = cancel_stdin.cancelled() => break, maybe_line =
|
||||
stdin_lines.recv() => { let Some(line) = maybe_line else {
|
||||
break }; forward_stdio_line_to_leader(line, &
|
||||
leader_tx_stdin, & replay_state_stdin, & cancel_stdin,).
|
||||
await; }
|
||||
biased;
|
||||
_ = cancel_stdin.cancelled() => break,
|
||||
maybe_line = stdin_lines.recv() => {
|
||||
let Some(line) = maybe_line else { break };
|
||||
forward_stdio_line_to_leader(
|
||||
line,
|
||||
&leader_tx_stdin,
|
||||
&replay_state_stdin,
|
||||
&cancel_stdin,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1245,7 +1261,7 @@ async fn run_agent_command(
|
|||
reconnector.notify_connected();
|
||||
let params = match replayed_session_id {
|
||||
Some(ref sid) => {
|
||||
serde_json::json!({ "sessionId" : sid }).to_string()
|
||||
serde_json::json!({ "sessionId": sid }).to_string()
|
||||
}
|
||||
None => "{}".to_string(),
|
||||
};
|
||||
|
|
@ -1258,7 +1274,7 @@ async fn run_agent_command(
|
|||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(error = % e, "Failed to reconnect (stdio)");
|
||||
tracing::error!(error = %e, "Failed to reconnect (stdio)");
|
||||
cancel_stdout.cancel();
|
||||
break;
|
||||
}
|
||||
|
|
@ -1268,7 +1284,8 @@ async fn run_agent_command(
|
|||
}
|
||||
});
|
||||
tokio::select! {
|
||||
_ = stdin_task => {} _ = stdout_task => {}
|
||||
_ = stdin_task => {}
|
||||
_ = stdout_task => {}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
|
@ -1293,9 +1310,7 @@ async fn run_agent_command(
|
|||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
error = % e, "Failed to reconnect (headless)"
|
||||
);
|
||||
tracing::error!(error = %e, "Failed to reconnect (headless)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1640,6 +1655,9 @@ fn main() {
|
|||
if let Some(code) = xai_grok_pager::app::mermaid_worker::maybe_run_render_subprocess() {
|
||||
std::process::exit(code);
|
||||
}
|
||||
if let Some(code) = xai_grok_pager::voice::maybe_run_capture_subprocess() {
|
||||
std::process::exit(code);
|
||||
}
|
||||
let args = PagerArgs::parse_cli();
|
||||
if dispatch_version_if_requested(&args) || dispatch_doctor_if_requested(&args) {
|
||||
return;
|
||||
|
|
@ -1785,10 +1803,10 @@ async fn async_main(args: PagerArgs) -> Result<()> {
|
|||
match command {
|
||||
Command::Version { json } => {
|
||||
if json {
|
||||
let payload = serde_json::json!(
|
||||
{ "currentVersion" : env!("VERSION_WITH_COMMIT"), "channel" :
|
||||
xai_grok_update::channel_name().unwrap_or("unknown"), }
|
||||
);
|
||||
let payload = serde_json::json!({
|
||||
"currentVersion": env!("VERSION_WITH_COMMIT"),
|
||||
"channel": xai_grok_update::channel_name().unwrap_or("unknown"),
|
||||
});
|
||||
println!("{}", serde_json::to_string(&payload)?);
|
||||
} else {
|
||||
write_version(
|
||||
|
|
@ -2263,9 +2281,7 @@ async fn signal_leaders_to_relaunch(installed_version: &str) {
|
|||
{
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
tracing::debug!(
|
||||
error = % e, "Could not connect to leader to signal relaunch"
|
||||
);
|
||||
tracing::debug!(error = %e, "Could not connect to leader to signal relaunch");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
|
@ -2287,17 +2303,14 @@ async fn signal_leaders_to_relaunch(installed_version: &str) {
|
|||
eprintln!(" ↻ Relaunching shared session (leader {from_version} → {to_version})…");
|
||||
}
|
||||
Ok(Ok(xai_grok_shell::leader::ControlPayload::RelaunchDeclined { reason })) => {
|
||||
tracing::debug!(% reason, "Leader declined relaunch");
|
||||
tracing::debug!(%reason, "Leader declined relaunch");
|
||||
}
|
||||
Ok(Ok(_)) => {}
|
||||
Ok(Err(e)) => {
|
||||
tracing::debug!(error = % e.message, "Leader relaunch control error");
|
||||
tracing::debug!(error = %e.message, "Leader relaunch control error");
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::debug!(
|
||||
error = % e,
|
||||
"Leader relaunch ack not received (leader may be exiting)"
|
||||
);
|
||||
tracing::debug!(error = %e, "Leader relaunch ack not received (leader may be exiting)");
|
||||
}
|
||||
}
|
||||
client.cancel();
|
||||
|
|
@ -2818,10 +2831,11 @@ mod tests {
|
|||
assert_eq!(load2_json["id"].as_str(), Some(REPLAY_LOAD_REQUEST_ID));
|
||||
response_tx
|
||||
.send(
|
||||
serde_json::json!(
|
||||
{ "jsonrpc" : "2.0", "id" : REPLAY_LOAD_REQUEST_ID, "result" : {}
|
||||
}
|
||||
)
|
||||
serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": REPLAY_LOAD_REQUEST_ID,
|
||||
"result": {}
|
||||
})
|
||||
.to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
|
|
@ -2967,8 +2981,8 @@ mod tests {
|
|||
response_tx
|
||||
.send(
|
||||
format!(
|
||||
r#"{{"jsonrpc":"2.0","method":"session/update","params":{{"sessionId":"s9","n":{i}}}}}"#
|
||||
),
|
||||
r#"{{"jsonrpc":"2.0","method":"session/update","params":{{"sessionId":"s9","n":{i}}}}}"#
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
@ -3071,10 +3085,11 @@ mod tests {
|
|||
);
|
||||
response_tx
|
||||
.send(
|
||||
serde_json::json!(
|
||||
{ "jsonrpc" : "2.0", "id" : REPLAY_LOAD_REQUEST_ID, "result" : {}
|
||||
}
|
||||
)
|
||||
serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": REPLAY_LOAD_REQUEST_ID,
|
||||
"result": {}
|
||||
})
|
||||
.to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
|||
Loading…
Reference in a new issue