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}