Files
newgrok/patches/0003-Add-remote_control-config-section-for-the-rc-glance-.patch
T
iceBear67 a968ad297c
CI / test (push) Canceled after 0s
CI / grok-linux-amd64 (push) Canceled after 0s
CI / grok-windows-amd64 (push) Canceled after 0s
CI / grok-macos-arm64 (push) Canceled after 0s
CI / release (push) Canceled after 0s
Update upstream to 5163763
Forward-port the six local patches onto the two new monorepo syncs
(SOURCE_REV e6a67a54 -> 84ae1223). Resolved 0001 against the runtime
full_version() injection and 0005 against the Option-wrapped
UserPromptSubmit hook payload.
2026-08-16 03:22:31 +00:00

109 lines
4.7 KiB
Diff

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 2a2ab0491b226cee84fd968869a2daaff707f9a7..be842a31d205db6bc88ac8f46c0af8e2cecbb4ef 100644
--- a/crates/codegen/xai-grok-shell/src/agent/config.rs
+++ b/crates/codegen/xai-grok-shell/src/agent/config.rs
@@ -1023,6 +1023,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 {
@@ -1361,6 +1434,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)]
@@ -1767,6 +1843,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(),