M2 audit: excise managed connectors and xAI media-gen tools

Managed connectors (grok.com MCP admin) removed root-and-branch:
- The managed-MCP fetch/injection pipeline is gone, including the whole
  kigi-shell-session-support crate (managed-config fetch client, gateway
  tool catalog + dispatch, header injection, refresh task), reactive
  managed re-auth, mcp_doctor's grok.com-source discovery, and the
  [managed_mcps] config surface.
- TUI: the 'Managed by grok.com' section, connectors URL/deep-link,
  Action::OpenManagedConnectors, and session_team_id are gone. Local MCP
  management (list/toggle/add/remove/auth/tools) is fully intact.
- Kept as LOCAL policy: managed-settings.json MCP allow/deny enforcement,
  the multi-source local MCP merge, folder-trust gating. PluginOrigin
  Project/User labels kept (they tag locally discovered plugin dirs).

imagine/media-gen tools (xAI image/video generation) removed:
- image_gen, image_edit, video_gen, image_to_video, reference_to_video
  implementations, registrations, ToolKind/ToolInput/Output variants
  (serde-safe), config plumbing end to end, ZDR video machinery,
  /imagine + /imagine-video commands and guidance text, the bundled
  imagine skill (added to legacy cleanup so user installs delete it),
  and the media-gen render path.
- Kept: image INPUT (paste/attach, [Image #N] meta, pdf/image fetch,
  clipboard wrap), generic media-ref rendering, and the generic tool
  401-retry machinery (tests renamed, assertions unweakened).
- deploy_app stays: it is a permanently-disabled local stub deploying
  nowhere.

121 files changed, 8 deleted. Gates: workspace check/clippy 0/0, fmt,
deny ok; suites green (tools 2554, shell 4862, tui 6608, workspace
1042). Remaining grok.com strings live only in the auth-method ids and
changelog archives (§9/M3 sweep).
This commit is contained in:
ZacharyZhang-NY committed 2026-07-17 23:45:05 -04:00
1 parent fa75eb139a
commit 5e4e24db99
120 files changed
+301 -11327

No files matched your search

@@ -84,123 +84,6 @@ impl MvpAgent {
}
})
}
fn has_managed_mcp_auth(&self) -> bool {
self.auth_manager
.current_or_expired()
.is_some_and(|a| a.is_session_auth())
}
/// Requires feature flag AND xAI authentication (OIDC or legacy WebLogin).
pub(super) fn can_fetch_managed_mcps(&self) -> bool {
let cfg = self.cfg.borrow();
cfg.managed_mcps_enabled && !cfg.managed_mcp_gateway_tools_enabled
&& self.has_managed_mcp_auth()
}
fn can_fetch_managed_mcp_gateway_tools(&self) -> bool {
self.cfg.borrow().managed_mcp_gateway_tools_enabled
&& self.has_managed_mcp_auth()
}
pub async fn get_managed_mcp_configs(
&self,
) -> Vec<crate::session::managed_mcp::ManagedMcpConfig> {
if !self.can_fetch_managed_mcps() {
return vec![];
}
let proxy_url = self.cfg.borrow().endpoints.proxy_url();
crate::session::managed_mcp::fetch_managed_mcp_configs(
&self.managed_mcp_cache,
&proxy_url,
&self.auth_manager,
)
.await
}
pub async fn get_managed_mcp_gateway_tool_catalog(
&self,
) -> Option<crate::session::managed_mcp::GatewayToolCatalog> {
if !self.can_fetch_managed_mcp_gateway_tools() {
self.managed_mcp_cache.lock().await.disable_gateway_tools();
return None;
}
self.managed_mcp_cache.lock().await.enable_gateway_tools();
let proxy_url = self.cfg.borrow().endpoints.proxy_url();
let auth_key = self
.auth_manager
.get_valid_token()
.await
.ok()
.or_else(|| self.auth_manager.current_or_expired().map(|a| a.key));
crate::session::managed_mcp::get_or_fetch_gateway_tool_catalog(
&self.managed_mcp_cache,
&proxy_url,
auth_key.as_deref(),
)
.await
}
pub fn managed_mcp_cache(
&self,
) -> &crate::session::managed_mcp::ManagedMcpStateHandle {
&self.managed_mcp_cache
}
pub(crate) fn disable_managed_gateway_tools_and_refresh_sessions(&self) {
self.disable_managed_gateway_tools_and_refresh_sessions_with_txs(
self.sessions.borrow().values().map(|handle| handle.cmd_tx.clone()).collect(),
);
}
fn disable_managed_gateway_tools_and_refresh_sessions_with_txs(
&self,
session_txs: Vec<tokio::sync::mpsc::UnboundedSender<SessionCommand>>,
) {
let cache = self.managed_mcp_cache.clone();
tokio::task::spawn_local(async move {
cache.lock().await.disable_gateway_tools();
for tx in session_txs {
let _ = tx.send(SessionCommand::RefreshMcpSearchIndex);
}
});
}
pub(crate) fn spawn_managed_gateway_tool_catalog_fetch(&self) {
let session_txs: Vec<_> = self
.sessions
.borrow()
.values()
.map(|handle| handle.cmd_tx.clone())
.collect();
if !self.can_fetch_managed_mcp_gateway_tools() {
self.disable_managed_gateway_tools_and_refresh_sessions_with_txs(
session_txs,
);
return;
}
let cache = self.managed_mcp_cache.clone();
let proxy_url = self.cfg.borrow().endpoints.proxy_url();
let auth_manager = self.auth_manager.clone();
tokio::task::spawn_local(async move {
let auth_key = auth_manager
.get_valid_token()
.await
.ok()
.or_else(|| auth_manager.current_or_expired().map(|a| a.key));
if !auth_manager
.current_or_expired()
.is_some_and(|a| a.is_session_auth())
{
cache.lock().await.disable_gateway_tools();
for tx in session_txs {
let _ = tx.send(SessionCommand::RefreshMcpSearchIndex);
}
return;
}
cache.lock().await.enable_gateway_tools();
crate::session::managed_mcp::get_or_fetch_gateway_tool_catalog(
&cache,
&proxy_url,
auth_key.as_deref(),
)
.await;
for tx in session_txs {
let _ = tx.send(SessionCommand::RefreshMcpSearchIndex);
}
});
}
/// Resolve the launch dir's project-scope trust verdict ONCE and return it
/// with its path.
///
@@ -226,15 +109,12 @@ impl MvpAgent {
/// Resolve folder trust and load launch-dir MCP configs after `initialize`
/// returns. The walks are synchronous and expensive in large monorepos; they
/// must not block the ACP response (grok-desktop sends `initialize` immediately).
pub(super) fn spawn_initialize_launch_mcp_setup(&self, fetch_managed_mcps: bool) {
pub(super) fn spawn_initialize_launch_mcp_setup(&self) {
let cwd = self.launch_cwd.clone();
let compat = self.cfg.borrow().compat_resolved;
let remote_settings = self.cfg.borrow().remote_settings.clone();
let gateway = self.gateway.clone();
let agent_mcp_state = self.agent_mcp_state.clone();
let managed_mcp_cache = self.managed_mcp_cache.clone();
let proxy_url = self.cfg.borrow().endpoints.proxy_url();
let auth_manager = self.auth_manager.clone();
tokio::task::spawn_local(async move {
let local_mcp_servers = match tokio::task::spawn_blocking(move || {
let local = crate::util::config::load_mcp_servers(&cwd, &compat);
@@ -258,27 +138,9 @@ impl MvpAgent {
}
crate::extensions::mcp::notify_servers_updated(
&gateway,
&[],
&local_mcp_servers,
)
.await;
if !fetch_managed_mcps {
return;
}
let managed = crate::session::managed_mcp::fetch_managed_mcp_configs(
&managed_mcp_cache,
&proxy_url,
&auth_manager,
)
.await;
if !managed.is_empty() {
crate::extensions::mcp::notify_servers_updated(
&gateway,
&managed,
&local_mcp_servers,
)
.await;
}
});
}
pub fn agent_mcp_state(
@@ -311,23 +173,19 @@ impl MvpAgent {
plugin_count = count, "lazily populated plugin registry snapshot"
);
}
/// Fetch managed configs, merge with client servers, return merged list + earliest expiry.
pub(super) async fn resolve_mcp_servers(
/// Merge on-disk/plugin MCP servers with client servers.
pub(super) fn resolve_mcp_servers(
&self,
client_servers: Vec<acp::McpServer>,
cwd: &std::path::Path,
) -> (Vec<acp::McpServer>, Option<chrono::DateTime<chrono::Utc>>) {
) -> Vec<acp::McpServer> {
self.ensure_plugin_registry();
let managed = self.get_managed_mcp_configs().await;
let expires_at = managed.iter().filter_map(|c| c.token_expires_at).min();
let merged = crate::session::managed_mcp::merge_managed_mcp_servers(
crate::session::managed_mcp::merge_managed_mcp_servers(
client_servers,
cwd,
&managed,
self.plugin_registry_handle.snapshot().as_deref(),
&self.cfg.borrow().compat_resolved,
);
(merged, expires_at)
)
}
/// Set the memory configuration (called from TUI after config resolution).
pub fn set_memory_config(&mut self, config: crate::config::MemoryConfig) {
@@ -760,39 +618,6 @@ impl MvpAgent {
);
(id.clone(), new_config)
}
/// Build image generation config.
///
/// Both BYOK and session (OAuth) users go direct to `api_base_url`.
/// `sampling_config.api_key` carries the OAuth bearer for session users (the
/// `api_key_provider` refreshes it per request), so IC authenticates and
/// meters Imagine usage per-user.
pub(super) fn prepare_image_gen_config(
&self,
) -> kigi_tools::implementations::grok_build::image_gen::ImageGenConfig {
use kigi_tools::implementations::grok_build::image_gen::ImageGenConfig;
let sampling_config = self.sampling_config.borrow();
let Some(ref api_key) = sampling_config.api_key else {
return ImageGenConfig::Disabled;
};
let cfg = self.cfg.borrow();
let base_url = cfg.endpoints.api_base_url.clone();
let version = cfg
.client_version
.clone()
.unwrap_or_else(|| kigi_version::VERSION.to_string());
let alpha_test_key = cfg.endpoints.alpha_test_key.clone();
let mut headers = indexmap::IndexMap::new();
headers.insert("user-agent".to_string(), format!("kigi/{version}"));
ImageGenConfig::Enabled {
api_key: api_key.clone(),
base_url,
extra_headers: headers,
image_gen_enabled: cfg.resolve_image_gen().value,
image_edit_enabled: cfg.resolve_image_edit().value,
model_override: cfg.resolve_image_gen_model_override(),
tier_restricted: false,
}
}
/// Build deploy-service config. The tool talks directly to the deployer service.
pub(super) fn prepare_app_builder_deployer_config(
&self,
@@ -800,40 +625,6 @@ impl MvpAgent {
use kigi_tools::implementations::grok_build::deploy_app::AppBuilderDeployerConfig;
AppBuilderDeployerConfig::Disabled
}
/// Build video generation config. Video tools call the xAI API directly.
pub(super) fn prepare_video_gen_config(
&self,
) -> kigi_tools::implementations::grok_build::video_gen::VideoGenConfig {
use kigi_tools::implementations::grok_build::video_gen::VideoGenConfig;
let Some(api_key) = self.sampling_config.borrow().api_key.clone() else {
return VideoGenConfig::Disabled;
};
let cfg = self.cfg.borrow();
let zdr_video_output_s3 = cfg
.disable_zdr_incompatible_tools
.then(|| cfg.zdr_video_output_s3.clone())
.flatten()
.filter(|s3| s3.is_valid());
if cfg.disable_zdr_incompatible_tools && zdr_video_output_s3.is_none() {
tracing::info!("video_gen disabled by tools.disable_zdr_incompatible_tools");
return VideoGenConfig::Disabled;
}
let base_url = cfg.endpoints.api_base_url.clone();
let version = cfg
.client_version
.clone()
.unwrap_or_else(|| kigi_version::VERSION.to_string());
let alpha_test_key = cfg.endpoints.alpha_test_key.clone();
let mut headers = indexmap::IndexMap::new();
headers.insert("user-agent".to_string(), format!("kigi/{version}"));
VideoGenConfig::Enabled {
api_key,
base_url,
extra_headers: headers,
zdr_video_output_s3: zdr_video_output_s3.map(Box::new),
tier_restricted: false,
}
}
/// Web search config (PRD F5). The Kimi search service exists only on
/// the Kimi Code subscription channel (`POST {coding_base}/search`,
/// kimi-cli `auth/platforms.py`), so this is `Enabled` only for OAuth
@@ -1016,7 +807,6 @@ impl MvpAgent {
worktree_type,
restore_code,
session_registry_local,
managed_mcp_cache: Default::default(),
agent_mcp_state: std::sync::Arc::new(
tokio::sync::Mutex::new(
crate::session::mcp_servers::McpState::new(vec![]),
@@ -1829,7 +1619,6 @@ impl MvpAgent {
persisted_goal_mode,
persisted_announcement_state,
session_meta,
managed_mcp_expires_at,
model_agent_type,
session_model_id,
session_yolo_mode,
@@ -2258,8 +2047,6 @@ impl MvpAgent {
.and_then(|entry| entry.info.max_retries);
let origin_client = self.origin_client_info_from_meta(init.meta.as_ref());
let web_search_config = self.prepare_web_search_config();
let image_gen_config = self.prepare_image_gen_config();
let video_gen_config = self.prepare_video_gen_config();
let app_builder_deployer_config = self.prepare_app_builder_deployer_config();
let web_fetch_config = self.prepare_web_fetch_config();
let write_file_enabled = self.cfg.borrow().resolve_write_file().value;
@@ -2309,7 +2096,6 @@ impl MvpAgent {
let cfg = self.cfg.borrow();
cfg.resolve_backend_tools().value
};
let managed_mcp_proxy_url = self.cfg.borrow().endpoints.proxy_url();
let init_meta = self
.initialize_request
.get()
@@ -2471,9 +2257,6 @@ impl MvpAgent {
persisted_announcement_state,
self.memory_config.clone(),
feedback_flags,
self.managed_mcp_cache.clone(),
managed_mcp_expires_at,
managed_mcp_proxy_url,
session_model_id,
session_yolo_mode,
session_auto_mode,
@@ -2482,8 +2265,6 @@ impl MvpAgent {
model_max_retries,
web_search_config,
web_fetch_config,
image_gen_config,
video_gen_config,
app_builder_deployer_config,
write_file_enabled,
goal_enabled,
@@ -2617,7 +2398,6 @@ impl MvpAgent {
self.notify_session_cwd_for_watch(std::path::Path::new(&session_info.cwd));
self.activity.register_session(&session_info.id.0, &handle);
self.sessions.borrow_mut().insert(session_info.id.clone(), handle);
self.spawn_managed_gateway_tool_catalog_fetch();
let cwd_for_maintenance = session_info.cwd.clone();
tokio::spawn(async move {
crate::session::prompt_history::truncate_if_needed_async(cwd_for_maintenance)