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
This commit is contained in:
parent
a5727c5960
commit
69f0ba880a
286 changed files with 22939 additions and 9624 deletions
149
crates/codegen/xai-grok-pager/src/tutorial_docs.rs
Normal file
149
crates/codegen/xai-grok-pager/src/tutorial_docs.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
//! 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue