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:
2026-07-17 23:45:05 -04:00
parent fa75eb139a
commit 5e4e24db99
120 changed files with 301 additions and 11327 deletions
+1 -155
View File
@@ -1897,13 +1897,6 @@ fn tool_call_to_block(tc: &acp::ToolCall, session_cwd: Option<&Path>) -> RenderB
}
RenderBlock::ToolCall(ToolCallBlock::UseTool(block))
}
_ if matches!(
extract_raw_field(tc, "variant").as_deref(),
Some("ImageGen") | Some("ImageToVideo") | Some("ReferenceToVideo") | Some("ImageEdit")
) =>
{
media_gen_block(tc, success)
}
_ if tc.title.starts_with("Memory search:") => {
let query = tc
.title
@@ -2007,45 +2000,6 @@ fn tool_call_title(tc: &acp::ToolCall) -> Cow<'_, str> {
Cow::Borrowed(&tc.title)
}
}
/// Build the media block from the typed `raw_output` path.
fn media_gen_block(tc: &acp::ToolCall, success: bool) -> RenderBlock {
let mut block = OtherToolCallBlock::new(tool_call_title(tc), String::new());
if !success {
let err = content_text(tc);
block.error = Some(if err.is_empty() { "Failed".into() } else { err });
} else if let Some((path, is_video)) = media_gen_ref(tc) {
block = block.with_media_ref(path, is_video);
} else if let Some(text) = media_gen_text(tc) {
block.set_output_text(text);
}
RenderBlock::ToolCall(ToolCallBlock::Other(block))
}
/// Plain-text body of a media-variant tool that returned `ToolOutput::Text`
/// rather than a media file (the free / X Basic SuperGrok-upsell short-circuit).
/// `None` for real media outputs — including ZDR upload-only results — so their
/// typed rendering is untouched.
fn media_gen_text(tc: &acp::ToolCall) -> Option<String> {
match serde_json::from_value::<ToolOutput>(tc.raw_output.clone()?).ok()? {
ToolOutput::Text(t) => (!t.text.is_empty()).then_some(t.text),
_ => None,
}
}
/// Local `(path, is_video)` from typed `raw_output`.
///
/// Returns `None` when `raw_output` is missing/unparseable, not a media
/// variant, or has no openable local file (ZDR `uploaded_url` / empty path).
fn media_gen_ref(tc: &acp::ToolCall) -> Option<(std::path::PathBuf, bool)> {
let (media, is_video) =
match serde_json::from_value::<ToolOutput>(tc.raw_output.clone()?).ok()? {
ToolOutput::ImageGen(m) | ToolOutput::ImageEdit(m) => (m, false),
ToolOutput::ImageToVideo(m) | ToolOutput::ReferenceToVideo(m) => (m, true),
_ => return None,
};
if media.uploaded_url.is_some() || media.path.as_os_str().is_empty() {
return None;
}
Some((media.path, is_video))
}
/// Extract text content from a ContentBlock.
fn extract_text_from_content(content: &acp::ContentBlock) -> String {
match content {
@@ -5536,7 +5490,7 @@ mod tests {
}
#[test]
fn build_and_parse_tools_meta_round_trip() {
let names = vec!["scheduler_create".to_string(), "image_gen".to_string()];
let names = vec!["scheduler_create".to_string(), "web_search".to_string()];
let wire = serde_json::json!({ "tools" : names });
assert_eq!(parse_tools_meta(wire.as_object()), Some(names));
}
@@ -6421,112 +6375,4 @@ mod tests {
);
}
}
/// Every video ToolInput variant must route through `media_gen_block` so
/// `[Open Video]` uses the typed `MediaGenOutput.path` (not a regex scrape
/// of the JSON prompt text — fragile on Windows with %-encoded session dirs).
#[test]
fn video_tool_variants_use_typed_path_not_generic_scrape() {
use crate::scrollback::block::BlockContent;
let dir = tempfile::tempdir().unwrap();
let video_path = dir.path().join("1.mp4");
std::fs::write(&video_path, b"fake-mp4").unwrap();
let cases: &[(&str, ToolOutput)] = &[
(
"ImageToVideo",
ToolOutput::ImageToVideo(kigi_tools::types::output::MediaGenOutput::new(
video_path.clone(),
)),
),
(
"ReferenceToVideo",
ToolOutput::ReferenceToVideo(kigi_tools::types::output::MediaGenOutput::new(
video_path.clone(),
)),
),
];
for (variant, output) in cases {
let tc = acp::ToolCall::new(
acp::ToolCallId::new(Arc::from(format!("media-{variant}"))),
variant.to_string(),
)
.kind(acp::ToolKind::Other)
.status(acp::ToolCallStatus::Completed)
.content(vec![])
.raw_input(Some(serde_json::json!({ "variant" : variant })))
.raw_output(serde_json::to_value(output).ok())
.locations(vec![]);
let block = tool_call_to_block(&tc, None);
let open_path = block
.inline_open_button()
.map(|(p, is_video)| {
assert!(is_video, "{variant}: expected video open button");
p
})
.or_else(|| block.video_references().first().map(|r| r.path.clone()))
.unwrap_or_else(|| panic!("{variant}: missing media ref / open button"));
assert_eq!(
open_path, video_path,
"{variant}: open path must be the typed MediaGenOutput.path"
);
}
}
#[test]
fn media_gen_ref_skips_uploaded_only_video() {
let output = ToolOutput::ImageToVideo(kigi_tools::types::output::MediaGenOutput::uploaded(
"https://bucket.example/videos/x.mp4".into(),
));
let tc = acp::ToolCall::new(
acp::ToolCallId::new(Arc::from("zdr-upload")),
"image_to_video",
)
.kind(acp::ToolKind::Other)
.status(acp::ToolCallStatus::Completed)
.content(vec![])
.raw_input(Some(serde_json::json!({ "variant" : "ImageToVideo" })))
.raw_output(serde_json::to_value(output).ok())
.locations(vec![]);
assert!(
media_gen_ref(&tc).is_none(),
"uploaded_url-only media must not claim a local open path"
);
}
/// A tier-restricted (free / X Basic) imagine call short-circuits with the
/// SuperGrok upsell as `ToolOutput::Text` on a `Completed` status. The media
/// renderer has no file to open, so it must surface the upsell text in the
/// card body (not a bare title) and must NOT mark the card as an error.
#[test]
fn tier_restricted_media_shows_upsell_text_not_error() {
let upsell = "Image generation is a SuperGrok feature. Upgrade at \
https://grok.com/supergrok?referrer=grok-build";
let output = ToolOutput::Text(kigi_tools::types::output::TextOutput::from(upsell));
let tc = acp::ToolCall::new(
acp::ToolCallId::new(Arc::from("tier-restricted-img")),
"image_gen",
)
.kind(acp::ToolKind::Other)
.status(acp::ToolCallStatus::Completed)
.content(vec![acp::ToolCallContent::Content(acp::Content::new(
acp::ContentBlock::Text(acp::TextContent::new(upsell)),
))])
.raw_input(Some(serde_json::json!({ "variant" : "ImageGen" })))
.raw_output(serde_json::to_value(output).ok())
.locations(vec![]);
let RenderBlock::ToolCall(ToolCallBlock::Other(block)) = tool_call_to_block(&tc, None)
else {
panic!("expected an Other tool-call block");
};
assert!(
block.is_success(),
"the upsell is a successful result, not an error"
);
assert!(
block
.output
.as_deref()
.unwrap_or_default()
.contains("SuperGrok"),
"upsell text must be shown in the card body, got: {:?}",
block.output
);
}
}