Skip to main content

wire/
guide.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! How far the person has got through the first-run guide, kept per
7//! city (`crates/wire/spec/Guide.lean` ยง8-68): the record a page reads with `Query::Guide`
8//! and writes whole with `Command::PutGuide`, beside `preference`, which
9//! is the same kind of record for the person's own settings.
10//!
11//! What this records is where the person went, not what is configured:
12//! whether a step is done is read from the configuration and the doctor
13//! each time, and a step opened or skipped here is never drawn as done.
14
15use serde::{Deserialize, Serialize};
16
17/// The guide's progress in one city: where it reopens, whether the
18/// person has left it, and each optional step seen or put off.
19///
20/// The provider step has no mark: it is the one step that must be done,
21/// and only the city's saved endpoint and `main` model say whether it is.
22/// Every field defaults, so a city nobody has guided reads as a guide at
23/// its start.
24#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
25#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
26pub struct GuideProgress {
27    /// The step the guide opens at next; absent until the person moved.
28    #[serde(default, skip_serializing_if = "Option::is_none")]
29    pub at: Option<GuideStep>,
30    #[serde(default)]
31    pub state: GuideState,
32    /// Step 2, the dependencies the doctor reads.
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub dependencies: Option<GuideMark>,
35    /// Step 3, the texts and the names.
36    #[serde(default, skip_serializing_if = "Option::is_none")]
37    pub texts: Option<GuideMark>,
38    /// Step 4, importing a skill.
39    #[serde(default, skip_serializing_if = "Option::is_none")]
40    pub skills: Option<GuideMark>,
41    /// Step 5, connecting a tool server.
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub mcp: Option<GuideMark>,
44}
45
46/// The five steps, in the order the guide gives them.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
50pub enum GuideStep {
51    Provider,
52    Dependencies,
53    Texts,
54    Skills,
55    Mcp,
56}
57
58/// Whether opening the city still offers the guide.
59#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
60#[serde(rename_all = "snake_case")]
61#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
62pub enum GuideState {
63    /// The guide is offered when the city opens.
64    #[default]
65    Open,
66    /// The person left it: the city opens on the conversation, and the
67    /// guide opens from the settings.
68    Left,
69}
70
71/// What the person did with one optional step. A step with no mark has
72/// not been looked at.
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
74#[serde(rename_all = "snake_case")]
75#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
76pub enum GuideMark {
77    Seen,
78    Skipped,
79}