grok-build-upstream-mirror/crates/codegen/xai-grok-pager/src/tutorial_docs.rs

149 lines
4.5 KiB
Rust
Raw Normal View History

Synced from monorepo Synced from monorepo Changes: - Workspace server: report `/ready` as failed with dwell on hub connect failure - Refresh OIDC token for the Grok agent in the shell - ACP terminal output recorder - Cross-platform provider auth commands in the shell - Default `/resume` to Grok sessions with a hint for hidden external sessions - Resume sessions by title with `--resume` - Limit app-builder archive size - Data-driven tag labels for slash commands - Doctor fixes for tmux - Custom provider gateways and subprocess environment policy in the shell - `/tutorial` — opt-in onboarding tour of Grok Build - Soft and required CLI version checks in the shell - Privacy banner env overrides survive live settings updates - Add remote flag to override the image-edit model - Return profile fields from auth info even when the access token is expired - Add edit control on queued prompt rows - Keep fail-closed policy when clearing orphans with no team - Setting to disable the Ctrl+Space/F8 voice shortcut - Pass `--raw` to pw-record so Linux dictation works on older PipeWire - Validate git URLs when adding marketplace entries - Stop shipping stale tool-doc parameter and tool names - Re-point dashboard attach after `/fork` only when the parent was attached - Surface Grok Computer media-generation results as file-path chunks - Clear web background-task tray on kill and keep the task description - Show privacy upsell banner in agent view until acted on - Add tools-server client callback surface - Protect persistent global hook sources Source-Revision: 95d84f443eddcbed6cbfd6eed22e2eafe6b3939d
2026-07-23 17:12:33 +00:00
//! Onboarding tutorial content (embedded markdown).
//!
//! Short, curated topics shown by the `/tutorial` overlay (strictly opt-in —
//! nothing auto-shows). Deliberately separate from [`crate::docs`] (the full how-to
//! guides): these pages are bite-size intros that point at the guides for
//! depth.
/// A compile-time tutorial topic. All fields are `&'static str`.
#[derive(Debug)]
pub struct TutorialTopic {
/// Row title in the topic list.
pub title: &'static str,
/// Short right-column blurb in the topic list.
pub blurb: &'static str,
/// Embedded markdown page content.
pub content: &'static str,
/// Title of the primary how-to guide this page's "Go deeper" points at
/// (must match a [`crate::docs`] title); `d` opens it in the overlay.
pub go_deeper: Option<&'static str>,
}
macro_rules! topic {
($file:literal, $title:literal, $blurb:literal, $go_deeper:expr) => {
TutorialTopic {
title: $title,
blurb: $blurb,
content: include_str!(concat!("../docs/tutorial/", $file)),
go_deeper: $go_deeper,
}
};
}
/// The tutorial topics, in display order. Ordered as a linear flow (the
/// topic screen's `→` advances through them): what carries over from other
/// tools, send a prompt, feed it context, learn the screen, then the
/// bigger features.
pub static TUTORIAL_TOPICS: &[TutorialTopic] = &[
topic!(
"01-coming-from-another-tool.md",
"Coming from Claude, Cursor, or Codex?",
"your settings, rules & skills carry over",
Some("Project Rules (AGENTS.md)")
),
topic!(
"02-first-prompt.md",
"Your First Prompt",
"send, queue, cancel",
Some("Getting Started")
),
topic!(
"03-attach-and-paste.md",
"Attach Files, Images & Paste",
"@files, line ranges, screenshots",
Some("Getting Started")
),
topic!(
"04-navigation.md",
"Finding Your Way Around",
"focus, scrollback, panes",
Some("Keyboard Shortcuts")
),
topic!(
"05-slash-commands.md",
"Slash Commands",
"/help /model /resume and Ctrl+P",
Some("Slash Commands")
),
topic!(
"06-worktrees.md",
"Parallel Work: Worktrees",
"isolated sessions on one repo",
Some("Session Management")
),
topic!(
"07-plan-and-permissions.md",
"Plan Mode & Permissions",
"review the approach before it acts",
Some("Plan Mode")
),
topic!(
"08-make-it-yours.md",
"Make It Yours",
"just ask — AGENTS.md, memory, themes",
Some("Project Rules (AGENTS.md)")
),
topic!(
"09-where-next.md",
"Where to Go Next",
"guides, feedback, and good habits",
None
),
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn topics_are_valid() {
for t in TUTORIAL_TOPICS {
assert!(!t.title.is_empty(), "topic has empty title");
assert!(!t.blurb.is_empty(), "topic {} has empty blurb", t.title);
assert!(!t.content.is_empty(), "topic {} is empty", t.title);
assert!(
t.content.starts_with('#'),
"topic {} should start with a markdown header",
t.title
);
}
}
#[test]
fn go_deeper_titles_resolve_to_real_guides() {
// `d` on a topic page opens this guide; a typo'd title would turn
// the shortcut into a silent no-op.
for t in TUTORIAL_TOPICS {
if let Some(title) = t.go_deeper {
assert!(
crate::docs::find_doc(title).is_some(),
"topic {}: go_deeper {title:?} matches no how-to guide",
t.title
);
}
}
}
#[test]
fn topics_have_unique_titles() {
let mut seen = std::collections::HashSet::new();
for t in TUTORIAL_TOPICS {
assert!(seen.insert(t.title), "duplicate topic title: {}", t.title);
}
}
#[test]
fn topics_stay_bite_size() {
// The tutorial promises quick reads — keep each page short. Bump this
// limit only after re-checking a page still reads in under a minute.
for t in TUTORIAL_TOPICS {
let lines = t.content.lines().count();
assert!(
lines <= 50,
"topic {} is {} lines; keep tutorial pages bite-size (≤50)",
t.title,
lines
);
}
}
}