diff --git a/patches/0003-Add-remote_control-config-section-for-the-rc-glance-.patch b/patches/0003-Add-remote_control-config-section-for-the-rc-glance-.patch new file mode 100644 index 0000000..bfcfd25 --- /dev/null +++ b/patches/0003-Add-remote_control-config-section-for-the-rc-glance-.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: iceBear67 +Date: Sat, 15 Aug 2026 06:39:14 +0000 +Subject: [PATCH] Add [remote_control] config section for the /rc glance bridge + + +diff --git a/crates/codegen/xai-grok-shell/src/agent/config.rs b/crates/codegen/xai-grok-shell/src/agent/config.rs +index 3dd50b3217936911d6858e4c9c169d7609e1a0fd..f39d1bd460a4635dd4767afe92622ab9b04952a1 100644 +--- a/crates/codegen/xai-grok-shell/src/agent/config.rs ++++ b/crates/codegen/xai-grok-shell/src/agent/config.rs +@@ -1014,6 +1014,79 @@ pub struct CliConfig { + #[serde(skip_serializing_if = "Option::is_none")] + pub session_picker_grouped: Option, + } ++/// `[remote_control]` section: the `/rc` bridge to a grok-glance server. ++/// ++/// `/rc` mirrors the session you are already in to glance over ACP -- it does not ++/// restart it, switch it to headless, or hand it over. Both ends stay live and ++/// either can drive the session. ++/// ++/// Every field has an env override, which is how the API key is normally supplied: ++/// a bearer token in a plaintext config file is a poor default. ++#[derive(Clone, Debug, Default, Serialize, Deserialize)] ++#[serde(default)] ++pub struct RemoteControlConfig { ++ /// Glance WebSocket endpoint, e.g. `wss://glance.example.com/api/acp/agent`. ++ /// Env `GROK_RC_URL`. ++ #[serde(skip_serializing_if = "Option::is_none")] ++ pub url: Option, ++ /// Bearer token presented on the WebSocket upgrade. Env `GROK_RC_API_KEY`. ++ #[serde(skip_serializing_if = "Option::is_none")] ++ pub api_key: Option, ++ /// Connect at session start instead of waiting for `/rc`. Env `GROK_RC_AUTO_START`. ++ #[serde(skip_serializing_if = "Option::is_none")] ++ pub auto_start: Option, ++ /// Session updates retained for replay when glance (re)connects. ++ /// See [`RemoteControlConfig::DEFAULT_REPLAY_BUFFER`]. ++ #[serde(skip_serializing_if = "Option::is_none")] ++ pub replay_buffer: Option, ++} ++impl RemoteControlConfig { ++ /// Bounded so a long session cannot grow the bridge without limit; large ++ /// enough that a browser attaching mid-session still sees useful history. ++ pub const DEFAULT_REPLAY_BUFFER: usize = 2048; ++ /// Env wins over config, and an empty value counts as unset -- an exported ++ /// but blank `GROK_RC_URL` should not mask a working config entry. ++ fn env_override(key: &str) -> Option { ++ std::env::var(key) ++ .ok() ++ .map(|v| v.trim().to_owned()) ++ .filter(|v| !v.is_empty()) ++ } ++ pub fn resolved_url(&self) -> Option { ++ Self::env_override("GROK_RC_URL").or_else(|| { ++ self.url ++ .as_deref() ++ .map(str::trim) ++ .filter(|v| !v.is_empty()) ++ .map(str::to_owned) ++ }) ++ } ++ pub fn resolved_api_key(&self) -> Option { ++ Self::env_override("GROK_RC_API_KEY").or_else(|| { ++ self.api_key ++ .as_deref() ++ .map(str::trim) ++ .filter(|v| !v.is_empty()) ++ .map(str::to_owned) ++ }) ++ } ++ pub fn auto_start_enabled(&self) -> bool { ++ Self::env_override("GROK_RC_AUTO_START") ++ .map(|v| matches!(v.to_ascii_lowercase().as_str(), "1" | "true" | "yes" | "on")) ++ .or(self.auto_start) ++ .unwrap_or(false) ++ } ++ pub fn replay_buffer_len(&self) -> usize { ++ self.replay_buffer ++ .filter(|n| *n > 0) ++ .unwrap_or(Self::DEFAULT_REPLAY_BUFFER) ++ } ++ /// Both a URL and a key are required; `/rc` reports which one is missing ++ /// rather than dialing an endpoint that will reject it. ++ pub fn is_configured(&self) -> bool { ++ self.resolved_url().is_some() && self.resolved_api_key().is_some() ++ } ++} + #[derive(Clone, Debug, Default, Serialize, Deserialize)] + #[serde(default)] + pub struct DiagnosticsConfig { +@@ -1348,6 +1421,9 @@ pub struct Config { + pub paths: PathsConfig, + #[serde(default, skip_serializing)] + pub cli: CliConfig, ++ /// `[remote_control]` section: the `/rc` bridge to grok-glance. ++ #[serde(default, skip_serializing)] ++ pub remote_control: RemoteControlConfig, + #[serde(default, skip_serializing)] + pub models: ModelsConfig, + #[serde(default, skip_serializing)] +@@ -1759,6 +1835,7 @@ impl Default for Config { + feedback: FeedbackConfig::default(), + paths: PathsConfig::default(), + cli: CliConfig::default(), ++ remote_control: RemoteControlConfig::default(), + models: ModelsConfig::default(), + harness: HarnessConfig::default(), + relay: RelayConfig::default(),