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.
109 lines
4.7 KiB
Diff
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(),
|