Add [remote_control] config section (patch 0003)

Exports the work/ commit adding the [remote_control] config section that the
/rc bridge reads: url, api_key, auto_start and replay_buffer, with
GROK_RC_URL / GROK_RC_API_KEY overriding the file.
This commit is contained in:
iceBear67
2026-08-15 09:10:07 +00:00
parent 569551fe9c
commit dd9b41e72f
@@ -0,0 +1,108 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: iceBear67 <icebear67@sfclub.cc>
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<bool>,
}
+/// `[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<String>,
+ /// Bearer token presented on the WebSocket upgrade. Env `GROK_RC_API_KEY`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub api_key: Option<String>,
+ /// 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<bool>,
+ /// 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<usize>,
+}
+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<String> {
+ std::env::var(key)
+ .ok()
+ .map(|v| v.trim().to_owned())
+ .filter(|v| !v.is_empty())
+ }
+ pub fn resolved_url(&self) -> Option<String> {
+ 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<String> {
+ 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(),