Skip to main content

hammer/
ops.rs

1//! Hammer's operations, typed. Each function runs one operation, as [`crate::call`] would. A plugin may
2//! call only those its manifest's `[permissions]` ask for: each function's documentation names what it needs.
3//!
4//! Generated from api/operations.json by kotlin/codegen: regenerate rather than edit.
5#![allow(clippy::all, unused_imports)]
6
7use serde::{Deserialize, Serialize};
8use std::collections::BTreeMap;
9
10/// A value this kit doesn't know, from a later Hammer, reads as [`Access::Unknown`].
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum Access {
13    #[default]
14    #[serde(rename = "read")]
15    Read,
16    #[serde(rename = "write")]
17    Write,
18    #[serde(rename = "destructive")]
19    Destructive,
20    /// A value this kit doesn't know. Hammer rejects it as an input.
21    #[serde(other)]
22    Unknown,
23}
24
25#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
26#[serde(default)]
27pub struct AccountStatus {
28    pub server: Option<String>,
29    pub ssl: Option<bool>,
30    pub email: Option<String>,
31    #[serde(rename = "loggedIn")]
32    pub logged_in: bool,
33    /// Null unless checked.
34    #[serde(rename = "tokenValid")]
35    pub token_valid: Option<bool>,
36}
37
38#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
39#[serde(default)]
40pub struct Activity {
41    pub days: Vec<DayWords>,
42    /// Lifetime totals, not limited to the range.
43    pub devices: Vec<DeviceWords>,
44}
45
46#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
47#[serde(default)]
48pub struct Appearance {
49    #[serde(rename = "entryId")]
50    pub entry_id: i32,
51    pub name: String,
52    pub r#type: EntryKind,
53    #[serde(rename = "sceneCount")]
54    pub scene_count: i32,
55}
56
57#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
58#[serde(default)]
59pub struct ArchivedScene {
60    pub id: i32,
61    pub name: String,
62}
63
64#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
65#[serde(default)]
66pub struct ArchivedScenes {
67    pub scenes: Vec<ArchivedScene>,
68}
69
70#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
71#[serde(default)]
72pub struct Backup {
73    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
74    pub date: String,
75}
76
77#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
78#[serde(default)]
79pub struct Backups {
80    pub backups: Vec<Backup>,
81}
82
83/// A value this kit doesn't know, from a later Hammer, reads as [`Cadence::Unknown`].
84#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
85pub enum Cadence {
86    #[default]
87    #[serde(rename = "day")]
88    Day,
89    #[serde(rename = "week")]
90    Week,
91    /// A value this kit doesn't know. Hammer rejects it as an input.
92    #[serde(other)]
93    Unknown,
94}
95
96#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
97#[serde(default)]
98pub struct ChapterWords {
99    pub id: i32,
100    pub name: String,
101    pub words: i32,
102}
103
104/// A value this kit doesn't know, from a later Hammer, reads as [`ConflictChoice::Unknown`].
105#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
106pub enum ConflictChoice {
107    #[default]
108    #[serde(rename = "abort")]
109    Abort,
110    #[serde(rename = "local")]
111    Local,
112    #[serde(rename = "server")]
113    Server,
114    /// A value this kit doesn't know. Hammer rejects it as an input.
115    #[serde(other)]
116    Unknown,
117}
118
119#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
120#[serde(default)]
121pub struct DayWords {
122    /// An ISO 8601 date, such as `2026-03-01`.
123    pub date: String,
124    pub words: i32,
125}
126
127#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
128#[serde(default)]
129pub struct DeviceWords {
130    pub device: String,
131    pub words: i32,
132}
133
134#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
135#[serde(default)]
136pub struct DraftApplied {
137    #[serde(rename = "sceneId")]
138    pub scene_id: i32,
139    /// The draft holding the text it replaced; null when the text was unchanged.
140    #[serde(rename = "previousDraftId")]
141    pub previous_draft_id: Option<i32>,
142    #[serde(rename = "wordCount")]
143    pub word_count: i32,
144}
145
146#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
147#[serde(default)]
148pub struct DraftInfo {
149    pub id: i32,
150    pub name: String,
151    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
152    pub created: String,
153}
154
155#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
156#[serde(default)]
157pub struct DraftText {
158    pub id: i32,
159    #[serde(rename = "sceneId")]
160    pub scene_id: i32,
161    pub name: String,
162    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
163    pub created: String,
164    pub markdown: String,
165}
166
167#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
168#[serde(default)]
169pub struct Drafts {
170    pub drafts: Vec<DraftInfo>,
171}
172
173/// A value this kit doesn't know, from a later Hammer, reads as [`EntityKind::Unknown`].
174#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
175pub enum EntityKind {
176    #[default]
177    #[serde(rename = "scene")]
178    Scene,
179    #[serde(rename = "note")]
180    Note,
181    #[serde(rename = "entry")]
182    Entry,
183    #[serde(rename = "timeline")]
184    Timeline,
185    /// A value this kit doesn't know. Hammer rejects it as an input.
186    #[serde(other)]
187    Unknown,
188}
189
190#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
191#[serde(default)]
192pub struct Entries {
193    pub entries: Vec<EntrySummary>,
194}
195
196#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
197#[serde(default)]
198pub struct Entry {
199    pub id: i32,
200    pub name: String,
201    pub r#type: EntryKind,
202    pub text: String,
203    pub tags: Vec<String>,
204    pub aliases: Vec<String>,
205    #[serde(rename = "hasImage")]
206    pub has_image: bool,
207    /// Scene ids whose references to this entry have been confirmed.
208    #[serde(rename = "referencedBy")]
209    pub referenced_by: Vec<i32>,
210}
211
212#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
213#[serde(default)]
214pub struct EntryCount {
215    pub r#type: EntryKind,
216    pub count: i32,
217}
218
219#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
220#[serde(default)]
221pub struct EntryImage {
222    /// jpg, jpeg, png, or webp.
223    pub extension: String,
224    #[serde(with = "crate::base64::bytes")]
225    pub content: Vec<u8>,
226}
227
228/// A value this kit doesn't know, from a later Hammer, reads as [`EntryKind::Unknown`].
229#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
230pub enum EntryKind {
231    #[default]
232    #[serde(rename = "person")]
233    Person,
234    #[serde(rename = "place")]
235    Place,
236    #[serde(rename = "thing")]
237    Thing,
238    #[serde(rename = "event")]
239    Event,
240    #[serde(rename = "idea")]
241    Idea,
242    /// A value this kit doesn't know. Hammer rejects it as an input.
243    #[serde(other)]
244    Unknown,
245}
246
247#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
248#[serde(default)]
249pub struct EntrySummary {
250    pub id: i32,
251    pub name: String,
252    pub r#type: EntryKind,
253    /// Other names the entry goes by.
254    #[serde(skip_serializing_if = "Option::is_none", default)]
255    pub aliases: Option<Vec<String>>,
256}
257
258#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
259#[serde(default)]
260pub struct ExportFormat {
261    pub id: String,
262    #[serde(rename = "fileExtension")]
263    pub file_extension: String,
264    #[serde(rename = "mimeType")]
265    pub mime_type: String,
266}
267
268#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
269#[serde(default)]
270pub struct ExportFormats {
271    pub formats: Vec<ExportFormat>,
272}
273
274#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
275#[serde(default)]
276pub struct ExportedFile {
277    #[serde(rename = "fileName")]
278    pub file_name: String,
279    #[serde(rename = "mimeType")]
280    pub mime_type: String,
281    #[serde(with = "crate::base64::bytes")]
282    pub content: Vec<u8>,
283}
284
285#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
286#[serde(default)]
287pub struct Idea {
288    pub id: String,
289    pub title: Option<String>,
290    pub content: String,
291    pub tags: Vec<String>,
292    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
293    pub created: String,
294    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
295    pub updated: String,
296    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
297    pub promoted: Option<String>,
298    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
299    pub archived: Option<String>,
300}
301
302#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
303#[serde(default)]
304pub struct Ideas {
305    pub ideas: Vec<Idea>,
306}
307
308/// A value this kit doesn't know, from a later Hammer, reads as [`ImportFileFormat::Unknown`].
309#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
310pub enum ImportFileFormat {
311    #[default]
312    #[serde(rename = "markdown")]
313    Markdown,
314    #[serde(rename = "rtf")]
315    Rtf,
316    /// A value this kit doesn't know. Hammer rejects it as an input.
317    #[serde(other)]
318    Unknown,
319}
320
321/// A value this kit doesn't know, from a later Hammer, reads as [`MarkdownSplit::Unknown`].
322#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
323pub enum MarkdownSplit {
324    #[default]
325    #[serde(rename = "auto")]
326    Auto,
327    #[serde(rename = "h1")]
328    H1,
329    #[serde(rename = "h2")]
330    H2,
331    #[serde(rename = "pattern")]
332    Pattern,
333    /// A value this kit doesn't know. Hammer rejects it as an input.
334    #[serde(other)]
335    Unknown,
336}
337
338#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
339#[serde(default)]
340pub struct Note {
341    pub id: i32,
342    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
343    pub created: String,
344    pub tags: Vec<String>,
345    pub content: String,
346}
347
348#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
349#[serde(default)]
350pub struct Notes {
351    pub notes: Vec<Note>,
352}
353
354#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
355#[serde(default)]
356pub struct OperationDescriptor {
357    pub name: String,
358    pub description: String,
359    pub access: Access,
360    pub scope: OperationScope,
361    pub input: BTreeMap<String, serde_json::Value>,
362    pub output: BTreeMap<String, serde_json::Value>,
363}
364
365#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
366#[serde(default)]
367pub struct OperationList {
368    pub operations: Vec<OperationDescriptor>,
369}
370
371/// A value this kit doesn't know, from a later Hammer, reads as [`OperationScope::Unknown`].
372#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
373pub enum OperationScope {
374    #[default]
375    #[serde(rename = "content")]
376    Content,
377    #[serde(rename = "account")]
378    Account,
379    /// A value this kit doesn't know. Hammer rejects it as an input.
380    #[serde(other)]
381    Unknown,
382}
383
384#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
385#[serde(default)]
386pub struct PagedScene {
387    pub id: i32,
388    pub name: String,
389    /// Names of the groups containing the scene, outermost first.
390    pub path: Vec<String>,
391    pub markdown: String,
392    #[serde(rename = "wordCount")]
393    pub word_count: i32,
394    pub meta: SceneMeta,
395}
396
397#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
398#[serde(default)]
399pub struct ProjectImported {
400    pub name: String,
401    pub scenes: i32,
402}
403
404#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
405#[serde(default)]
406pub struct ProjectInfo {
407    pub name: String,
408    #[serde(rename = "projectId")]
409    pub project_id: String,
410    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
411    pub created: Option<String>,
412    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
413    #[serde(rename = "lastAccessed")]
414    pub last_accessed: Option<String>,
415    #[serde(rename = "authorName")]
416    pub author_name: Option<String>,
417    pub language: Option<String>,
418    pub tags: Vec<String>,
419    #[serde(rename = "wordCountGoal")]
420    pub word_count_goal: Option<WordGoal>,
421    #[serde(rename = "wordCount")]
422    pub word_count: Option<i32>,
423    #[serde(rename = "sceneCount")]
424    pub scene_count: Option<i32>,
425    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
426    #[serde(rename = "lastEdited")]
427    pub last_edited: Option<String>,
428}
429
430#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
431#[serde(default)]
432pub struct ProjectList {
433    pub projects: Vec<ProjectSummary>,
434}
435
436#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
437#[serde(default)]
438pub struct ProjectName {
439    pub name: String,
440}
441
442#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
443#[serde(default)]
444pub struct ProjectStats {
445    #[serde(rename = "totalWords")]
446    pub total_words: i32,
447    #[serde(rename = "sceneCount")]
448    pub scene_count: i32,
449    /// Top-level scenes and groups, in story order.
450    pub chapters: Vec<ChapterWords>,
451    #[serde(rename = "longestScene")]
452    pub longest_scene: Option<SceneWords>,
453    #[serde(rename = "shortestSceneWords")]
454    pub shortest_scene_words: i32,
455    #[serde(rename = "medianSceneWords")]
456    pub median_scene_words: i32,
457    #[serde(rename = "noteCount")]
458    pub note_count: i32,
459    #[serde(rename = "timelineEventCount")]
460    pub timeline_event_count: i32,
461    #[serde(rename = "entryCounts")]
462    pub entry_counts: Vec<EntryCount>,
463    /// People appearing in the most scenes.
464    #[serde(rename = "topAppearances")]
465    pub top_appearances: Vec<Appearance>,
466    #[serde(rename = "wordCountGoal")]
467    pub word_count_goal: Option<WordGoal>,
468    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
469    #[serde(rename = "lastEdited")]
470    pub last_edited: Option<String>,
471    #[serde(rename = "lastEditedScene")]
472    pub last_edited_scene: Option<SceneRef>,
473}
474
475#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
476#[serde(default)]
477pub struct ProjectSummary {
478    pub name: String,
479    #[serde(rename = "projectId")]
480    pub project_id: String,
481    /// From the statistics cache; null until statistics are first calculated.
482    #[serde(rename = "wordCount")]
483    pub word_count: Option<i32>,
484    /// Null when the project's metadata can't be read. An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
485    pub created: Option<String>,
486    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
487    #[serde(rename = "lastAccessed")]
488    pub last_accessed: Option<String>,
489    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
490    #[serde(rename = "lastEdited")]
491    pub last_edited: Option<String>,
492}
493
494#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
495#[serde(default)]
496pub struct ProjectSyncResult {
497    pub name: String,
498    pub outcome: SyncOutcome,
499}
500
501#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
502#[serde(default)]
503pub struct ProjectSyncStatus {
504    pub name: String,
505    /// True once the project has synced.
506    pub linked: bool,
507    /// Null when never synced. An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
508    #[serde(rename = "lastSync")]
509    pub last_sync: Option<String>,
510    #[serde(rename = "pendingChanges")]
511    pub pending_changes: i32,
512}
513
514/// A value this kit doesn't know, from a later Hammer, reads as [`RtfSplit::Unknown`].
515#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
516pub enum RtfSplit {
517    #[default]
518    #[serde(rename = "formatting")]
519    Formatting,
520    #[serde(rename = "pattern")]
521    Pattern,
522    #[serde(rename = "single")]
523    Single,
524    /// A value this kit doesn't know. Hammer rejects it as an input.
525    #[serde(other)]
526    Unknown,
527}
528
529#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
530#[serde(default)]
531pub struct SceneItemRef {
532    pub id: i32,
533    pub name: String,
534    pub kind: SceneKind,
535}
536
537/// A value this kit doesn't know, from a later Hammer, reads as [`SceneKind::Unknown`].
538#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
539pub enum SceneKind {
540    #[default]
541    #[serde(rename = "scene")]
542    Scene,
543    #[serde(rename = "group")]
544    Group,
545    /// A value this kit doesn't know. Hammer rejects it as an input.
546    #[serde(other)]
547    Unknown,
548}
549
550#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
551#[serde(default)]
552pub struct SceneMeta {
553    pub outline: String,
554    pub notes: String,
555    pub tags: Vec<String>,
556    #[serde(rename = "currentDraft")]
557    pub current_draft: String,
558    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
559    pub created: Option<String>,
560    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
561    #[serde(rename = "lastEdited")]
562    pub last_edited: Option<String>,
563    /// Entry ids confirmed as in the scene.
564    pub references: Vec<i32>,
565    /// Entry ids the writer dismissed, which name matching no longer adds.
566    #[serde(rename = "dismissedReferences")]
567    pub dismissed_references: Vec<i32>,
568}
569
570#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
571#[serde(default)]
572pub struct SceneNode {
573    pub id: i32,
574    pub name: String,
575    pub kind: SceneKind,
576    #[serde(rename = "wordCount")]
577    pub word_count: i32,
578    pub children: Vec<SceneNode>,
579}
580
581#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
582#[serde(default)]
583pub struct ScenePage {
584    pub scenes: Vec<PagedScene>,
585    /// The last scene's id when more follow, to pass as after; null on the last page.
586    pub next: Option<i32>,
587}
588
589#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
590#[serde(default)]
591pub struct SceneRef {
592    pub id: i32,
593    pub name: String,
594}
595
596#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
597#[serde(default)]
598pub struct SceneText {
599    pub id: i32,
600    pub name: String,
601    pub archived: bool,
602    pub markdown: String,
603    #[serde(rename = "wordCount")]
604    pub word_count: i32,
605    pub meta: SceneMeta,
606}
607
608#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
609#[serde(default)]
610pub struct SceneTree {
611    pub nodes: Vec<SceneNode>,
612}
613
614#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
615#[serde(default)]
616pub struct SceneWordCount {
617    #[serde(rename = "wordCount")]
618    pub word_count: i32,
619}
620
621#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
622#[serde(default)]
623pub struct SceneWords {
624    pub id: i32,
625    pub name: String,
626    pub words: i32,
627}
628
629#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
630#[serde(default)]
631pub struct SceneWriteResult {
632    /// The new draft, in draft mode.
633    #[serde(rename = "draftId")]
634    pub draft_id: Option<i32>,
635    /// In live mode, the draft holding the text it replaced; null when the text was unchanged.
636    #[serde(rename = "previousDraftId")]
637    pub previous_draft_id: Option<i32>,
638    #[serde(rename = "wordCount")]
639    pub word_count: i32,
640}
641
642/// A value this kit doesn't know, from a later Hammer, reads as [`SearchFilter::Unknown`].
643#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
644pub enum SearchFilter {
645    #[default]
646    #[serde(rename = "all")]
647    All,
648    #[serde(rename = "scenes")]
649    Scenes,
650    #[serde(rename = "notes")]
651    Notes,
652    #[serde(rename = "encyclopedia")]
653    Encyclopedia,
654    #[serde(rename = "timeline")]
655    Timeline,
656    /// A value this kit doesn't know. Hammer rejects it as an input.
657    #[serde(other)]
658    Unknown,
659}
660
661#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
662#[serde(default)]
663pub struct SearchHit {
664    pub kind: EntityKind,
665    pub id: i32,
666    pub title: String,
667    pub snippet: String,
668    /// The match's range within [snippet].
669    #[serde(rename = "matchStart")]
670    pub match_start: i32,
671    #[serde(rename = "matchEnd")]
672    pub match_end: i32,
673}
674
675#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
676#[serde(default)]
677pub struct SearchResults {
678    pub results: Vec<SearchHit>,
679}
680
681#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
682#[serde(default)]
683pub struct Session {
684    pub device: String,
685    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
686    #[serde(rename = "startedAt")]
687    pub started_at: String,
688    /// An ISO 8601 instant, such as `2026-03-01T09:30:00Z`.
689    #[serde(rename = "endedAt")]
690    pub ended_at: String,
691    pub words: i32,
692}
693
694#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
695#[serde(default)]
696pub struct Sessions {
697    pub sessions: Vec<Session>,
698}
699
700/// A value this kit doesn't know, from a later Hammer, reads as [`SyncOutcome::Unknown`].
701#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
702pub enum SyncOutcome {
703    #[default]
704    #[serde(rename = "success")]
705    Success,
706    #[serde(rename = "unchanged")]
707    Unchanged,
708    #[serde(rename = "needs_resolution")]
709    NeedsResolution,
710    #[serde(rename = "failed")]
711    Failed,
712    #[serde(rename = "skipped")]
713    Skipped,
714    /// A value this kit doesn't know. Hammer rejects it as an input.
715    #[serde(other)]
716    Unknown,
717}
718
719#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
720#[serde(default)]
721pub struct SyncRunResult {
722    #[serde(rename = "accountSynced")]
723    pub account_synced: bool,
724    #[serde(rename = "ideasSynced")]
725    pub ideas_synced: bool,
726    pub projects: Vec<ProjectSyncResult>,
727    pub log: Vec<String>,
728}
729
730#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
731#[serde(default)]
732pub struct SyncStatus {
733    pub projects: Vec<ProjectSyncStatus>,
734}
735
736#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
737#[serde(default)]
738pub struct TagCount {
739    pub tag: String,
740    pub count: i32,
741}
742
743#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
744#[serde(default)]
745pub struct TaggedEntities {
746    pub entities: Vec<TaggedEntity>,
747}
748
749#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
750#[serde(default)]
751pub struct TaggedEntity {
752    pub kind: EntityKind,
753    pub id: i32,
754}
755
756#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
757#[serde(default)]
758pub struct Tags {
759    pub tags: Vec<TagCount>,
760}
761
762#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
763#[serde(default)]
764pub struct Timeline {
765    pub events: Vec<TimelineEntry>,
766}
767
768#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
769#[serde(default)]
770pub struct TimelineEntry {
771    pub id: i32,
772    pub order: i32,
773    /// Free text; timelines are not bound to a calendar.
774    pub date: Option<String>,
775    pub content: String,
776    pub tags: Vec<String>,
777}
778
779#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
780#[serde(default)]
781pub struct WordGoal {
782    pub cadence: Cadence,
783    pub count: i32,
784}
785
786/// A value this kit doesn't know, from a later Hammer, reads as [`WriteMode::Unknown`].
787#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
788pub enum WriteMode {
789    #[default]
790    #[serde(rename = "draft")]
791    Draft,
792    #[serde(rename = "live")]
793    Live,
794    /// A value this kit doesn't know. Hammer rejects it as an input.
795    #[serde(other)]
796    Unknown,
797}
798
799/// The optional inputs of [`search`]; leave any out with `..Default::default()`.
800#[derive(Debug, Clone, Default, PartialEq, Serialize)]
801pub struct SearchOptions {
802    #[serde(skip_serializing_if = "Option::is_none")]
803    pub filter: Option<SearchFilter>,
804}
805
806/// Search a project's scenes, notes, encyclopedia, and timeline. #tag in the query filters by tag.
807///
808/// Needs `search` or `content:read` in the manifest's `[permissions]`.
809pub fn search(project: &str, query: &str, options: SearchOptions) -> crate::Result<SearchResults> {
810    #[derive(Serialize)]
811    struct Input<'a> {
812        project: &'a str,
813        query: &'a str,
814        #[serde(flatten)]
815        options: SearchOptions,
816    }
817    crate::call("search", &Input { project, query, options })
818}
819
820/// The `account` operations.
821pub mod account {
822    use super::*;
823
824    /// Log in to a sync server with an existing account. Accounts are created in the app.
825    ///
826    /// Needs `account.login` or `account:write` in the manifest's `[permissions]`.
827    pub fn login(url: &str, email: &str, password: &str) -> crate::Result<AccountStatus> {
828        #[derive(Serialize)]
829        struct Input<'a> {
830            url: &'a str,
831            email: &'a str,
832            password: &'a str,
833        }
834        crate::call("account.login", &Input { url, email, password })
835    }
836
837    /// Forget the sync server and every project's sync state for it, as removing the server in Settings does.
838    ///
839    /// Needs `account.logout` or `account:write` in the manifest's `[permissions]`.
840    pub fn logout() -> crate::Result<AccountStatus> {
841        #[derive(Serialize)]
842        struct Input {
843        }
844        crate::call("account.logout", &Input {  })
845    }
846
847    /// The optional inputs of [`status`]; leave any out with `..Default::default()`.
848    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
849    pub struct AccountStatusOptions {
850        /// Ask the server whether the stored token is still good; needs the network.
851        #[serde(skip_serializing_if = "Option::is_none")]
852        pub check: Option<bool>,
853    }
854
855    /// The sync server and account this install uses, and optionally whether the server still accepts it.
856    ///
857    /// Needs `account.status` or `account:read` in the manifest's `[permissions]`.
858    pub fn status(options: AccountStatusOptions) -> crate::Result<AccountStatus> {
859        #[derive(Serialize)]
860        struct Input {
861            #[serde(flatten)]
862            options: AccountStatusOptions,
863        }
864        crate::call("account.status", &Input { options })
865    }
866
867}
868
869/// The `backup` operations.
870pub mod backup {
871    use super::*;
872
873    /// Back up a project's saved files.
874    ///
875    /// Needs `backup.create` or `content:write` in the manifest's `[permissions]`.
876    pub fn create(project: &str) -> crate::Result<Backup> {
877        #[derive(Serialize)]
878        struct Input<'a> {
879            project: &'a str,
880        }
881        crate::call("backup.create", &Input { project })
882    }
883
884    /// A project's backups, oldest first.
885    ///
886    /// Needs `backup.list` or `content:read` in the manifest's `[permissions]`.
887    pub fn list(project: &str) -> crate::Result<Backups> {
888        #[derive(Serialize)]
889        struct Input<'a> {
890            project: &'a str,
891        }
892        crate::call("backup.list", &Input { project })
893    }
894
895}
896
897/// The `draft` operations.
898pub mod draft {
899    use super::*;
900
901    /// Replace a scene's text with one of its drafts, saving the replaced text as a draft first.
902    ///
903    /// Needs `draft.apply` or `content:write` in the manifest's `[permissions]`.
904    pub fn apply(project: &str, id: i32) -> crate::Result<DraftApplied> {
905        #[derive(Serialize)]
906        struct Input<'a> {
907            project: &'a str,
908            id: i32,
909        }
910        crate::call("draft.apply", &Input { project, id })
911    }
912
913    /// Save a scene's current text as a named draft.
914    ///
915    /// Needs `draft.create` or `content:write` in the manifest's `[permissions]`.
916    pub fn create(project: &str, scene_id: i32, name: &str) -> crate::Result<DraftInfo> {
917        #[derive(Serialize)]
918        struct Input<'a> {
919            project: &'a str,
920            #[serde(rename = "sceneId")]
921            scene_id: i32,
922            name: &'a str,
923        }
924        crate::call("draft.create", &Input { project, scene_id, name })
925    }
926
927    /// Delete a draft for good.
928    ///
929    /// Needs `draft.delete` (by name) in the manifest's `[permissions]`.
930    pub fn delete(project: &str, id: i32) -> crate::Result<DraftInfo> {
931        #[derive(Serialize)]
932        struct Input<'a> {
933            project: &'a str,
934            id: i32,
935        }
936        crate::call("draft.delete", &Input { project, id })
937    }
938
939    /// A scene's saved drafts, oldest first.
940    ///
941    /// Needs `draft.list` or `content:read` in the manifest's `[permissions]`.
942    pub fn list(project: &str, scene_id: i32) -> crate::Result<Drafts> {
943        #[derive(Serialize)]
944        struct Input<'a> {
945            project: &'a str,
946            #[serde(rename = "sceneId")]
947            scene_id: i32,
948        }
949        crate::call("draft.list", &Input { project, scene_id })
950    }
951
952    /// A draft's markdown.
953    ///
954    /// Needs `draft.read` or `content:read` in the manifest's `[permissions]`.
955    pub fn read(project: &str, id: i32) -> crate::Result<DraftText> {
956        #[derive(Serialize)]
957        struct Input<'a> {
958            project: &'a str,
959            id: i32,
960        }
961        crate::call("draft.read", &Input { project, id })
962    }
963
964}
965
966/// The `entry` operations.
967pub mod entry {
968    use super::*;
969
970    /// The optional inputs of [`create`]; leave any out with `..Default::default()`.
971    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
972    pub struct EntryCreateOptions {
973        #[serde(skip_serializing_if = "Option::is_none")]
974        pub tags: Option<Vec<String>>,
975        /// Other names the entry goes by, matched in scenes like its name.
976        #[serde(skip_serializing_if = "Option::is_none")]
977        pub aliases: Option<Vec<String>>,
978    }
979
980    /// Add an encyclopedia entry to a project.
981    ///
982    /// Needs `entry.create` or `content:write` in the manifest's `[permissions]`.
983    pub fn create(project: &str, name: &str, r#type: EntryKind, text: &str, options: EntryCreateOptions) -> crate::Result<Entry> {
984        #[derive(Serialize)]
985        struct Input<'a> {
986            project: &'a str,
987            name: &'a str,
988            r#type: EntryKind,
989            text: &'a str,
990            #[serde(flatten)]
991            options: EntryCreateOptions,
992        }
993        crate::call("entry.create", &Input { project, name, r#type, text, options })
994    }
995
996    /// Delete an encyclopedia entry, and its image, for good.
997    ///
998    /// Needs `entry.delete` (by name) in the manifest's `[permissions]`.
999    pub fn delete(project: &str, id: i32) -> crate::Result<EntrySummary> {
1000        #[derive(Serialize)]
1001        struct Input<'a> {
1002            project: &'a str,
1003            id: i32,
1004        }
1005        crate::call("entry.delete", &Input { project, id })
1006    }
1007
1008    /// The optional inputs of [`list`]; leave any out with `..Default::default()`.
1009    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1010    pub struct EntryListOptions {
1011        #[serde(skip_serializing_if = "Option::is_none")]
1012        pub r#type: Option<EntryKind>,
1013        #[serde(skip_serializing_if = "Option::is_none")]
1014        pub tag: Option<String>,
1015    }
1016
1017    /// A project's encyclopedia entries, with their aliases, optionally only one type or those with a tag.
1018    ///
1019    /// Needs `entry.list` or `content:read` in the manifest's `[permissions]`.
1020    pub fn list(project: &str, options: EntryListOptions) -> crate::Result<Entries> {
1021        #[derive(Serialize)]
1022        struct Input<'a> {
1023            project: &'a str,
1024            #[serde(flatten)]
1025            options: EntryListOptions,
1026        }
1027        crate::call("entry.list", &Input { project, options })
1028    }
1029
1030    /// An encyclopedia entry, with the scenes confirmed to reference it.
1031    ///
1032    /// Needs `entry.read` or `content:read` in the manifest's `[permissions]`.
1033    pub fn read(project: &str, id: i32) -> crate::Result<Entry> {
1034        #[derive(Serialize)]
1035        struct Input<'a> {
1036            project: &'a str,
1037            id: i32,
1038        }
1039        crate::call("entry.read", &Input { project, id })
1040    }
1041
1042    /// The optional inputs of [`update`]; leave any out with `..Default::default()`.
1043    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1044    pub struct EntryUpdateOptions {
1045        #[serde(skip_serializing_if = "Option::is_none")]
1046        pub name: Option<String>,
1047        #[serde(skip_serializing_if = "Option::is_none")]
1048        pub tags: Option<Vec<String>>,
1049        #[serde(skip_serializing_if = "Option::is_none")]
1050        pub aliases: Option<Vec<String>>,
1051    }
1052
1053    /// Replace an encyclopedia entry's text, and its name, tags, or aliases when given.
1054    ///
1055    /// Needs `entry.update` or `content:write` in the manifest's `[permissions]`.
1056    pub fn update(project: &str, id: i32, text: &str, options: EntryUpdateOptions) -> crate::Result<Entry> {
1057        #[derive(Serialize)]
1058        struct Input<'a> {
1059            project: &'a str,
1060            id: i32,
1061            text: &'a str,
1062            #[serde(flatten)]
1063            options: EntryUpdateOptions,
1064        }
1065        crate::call("entry.update", &Input { project, id, text, options })
1066    }
1067
1068    /// The `entry.image` operations.
1069    pub mod image {
1070        use super::*;
1071
1072        /// An encyclopedia entry's image.
1073        ///
1074        /// Needs `entry.image.get` or `content:read` in the manifest's `[permissions]`.
1075        pub fn get(project: &str, id: i32) -> crate::Result<EntryImage> {
1076            #[derive(Serialize)]
1077            struct Input<'a> {
1078                project: &'a str,
1079                id: i32,
1080            }
1081            crate::call("entry.image.get", &Input { project, id })
1082        }
1083
1084        /// Remove an encyclopedia entry's image.
1085        ///
1086        /// Needs `entry.image.remove` or `content:write` in the manifest's `[permissions]`.
1087        pub fn remove(project: &str, id: i32) -> crate::Result<Entry> {
1088            #[derive(Serialize)]
1089            struct Input<'a> {
1090                project: &'a str,
1091                id: i32,
1092            }
1093            crate::call("entry.image.remove", &Input { project, id })
1094        }
1095
1096        /// Set an encyclopedia entry's image, replacing any it has. The extension is jpg, jpeg, png, or webp, and must match the image.
1097        ///
1098        /// Needs `entry.image.set` or `content:write` in the manifest's `[permissions]`.
1099        pub fn set(project: &str, id: i32, extension: &str, content: &[u8]) -> crate::Result<Entry> {
1100            #[derive(Serialize)]
1101            struct Input<'a> {
1102                project: &'a str,
1103                id: i32,
1104                extension: &'a str,
1105                #[serde(serialize_with = "crate::base64::serialize")]
1106                content: &'a [u8],
1107            }
1108            crate::call("entry.image.set", &Input { project, id, extension, content })
1109        }
1110
1111    }
1112
1113}
1114
1115/// The `export` operations.
1116pub mod export {
1117    use super::*;
1118
1119    /// The formats project.export can produce.
1120    ///
1121    /// Needs `export.formats` or `content:read` in the manifest's `[permissions]`.
1122    pub fn formats() -> crate::Result<ExportFormats> {
1123        #[derive(Serialize)]
1124        struct Input {
1125        }
1126        crate::call("export.formats", &Input {  })
1127    }
1128
1129}
1130
1131/// The `idea` operations.
1132pub mod idea {
1133    use super::*;
1134
1135    /// Archive a story idea.
1136    ///
1137    /// Needs `idea.archive` or `content:write` in the manifest's `[permissions]`.
1138    pub fn archive(id: &str) -> crate::Result<Idea> {
1139        #[derive(Serialize)]
1140        struct Input<'a> {
1141            id: &'a str,
1142        }
1143        crate::call("idea.archive", &Input { id })
1144    }
1145
1146    /// The optional inputs of [`create`]; leave any out with `..Default::default()`.
1147    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1148    pub struct IdeaCreateOptions {
1149        #[serde(skip_serializing_if = "Option::is_none")]
1150        pub title: Option<String>,
1151        #[serde(skip_serializing_if = "Option::is_none")]
1152        pub tags: Option<Vec<String>>,
1153    }
1154
1155    /// Add a story idea.
1156    ///
1157    /// Needs `idea.create` or `content:write` in the manifest's `[permissions]`.
1158    pub fn create(content: &str, options: IdeaCreateOptions) -> crate::Result<Idea> {
1159        #[derive(Serialize)]
1160        struct Input<'a> {
1161            content: &'a str,
1162            #[serde(flatten)]
1163            options: IdeaCreateOptions,
1164        }
1165        crate::call("idea.create", &Input { content, options })
1166    }
1167
1168    /// Delete a story idea for good.
1169    ///
1170    /// Needs `idea.delete` (by name) in the manifest's `[permissions]`.
1171    pub fn delete(id: &str) -> crate::Result<Idea> {
1172        #[derive(Serialize)]
1173        struct Input<'a> {
1174            id: &'a str,
1175        }
1176        crate::call("idea.delete", &Input { id })
1177    }
1178
1179    /// The optional inputs of [`list`]; leave any out with `..Default::default()`.
1180    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1181    pub struct IdeaListOptions {
1182        /// True for only archived ideas, false for only active ones; omitted for both.
1183        #[serde(skip_serializing_if = "Option::is_none")]
1184        pub archived: Option<bool>,
1185    }
1186
1187    /// Story ideas, which belong to the account rather than a project.
1188    ///
1189    /// Needs `idea.list` or `content:read` in the manifest's `[permissions]`.
1190    pub fn list(options: IdeaListOptions) -> crate::Result<Ideas> {
1191        #[derive(Serialize)]
1192        struct Input {
1193            #[serde(flatten)]
1194            options: IdeaListOptions,
1195        }
1196        crate::call("idea.list", &Input { options })
1197    }
1198
1199    /// Return an archived story idea to the active ones.
1200    ///
1201    /// Needs `idea.unarchive` or `content:write` in the manifest's `[permissions]`.
1202    pub fn unarchive(id: &str) -> crate::Result<Idea> {
1203        #[derive(Serialize)]
1204        struct Input<'a> {
1205            id: &'a str,
1206        }
1207        crate::call("idea.unarchive", &Input { id })
1208    }
1209
1210    /// The optional inputs of [`update`]; leave any out with `..Default::default()`.
1211    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1212    pub struct IdeaUpdateOptions {
1213        /// Left out, unchanged; empty, cleared.
1214        #[serde(skip_serializing_if = "Option::is_none")]
1215        pub title: Option<String>,
1216        #[serde(skip_serializing_if = "Option::is_none")]
1217        pub tags: Option<Vec<String>>,
1218    }
1219
1220    /// Replace a story idea's text, and its title or tags when given. An empty title clears it.
1221    ///
1222    /// Needs `idea.update` or `content:write` in the manifest's `[permissions]`.
1223    pub fn update(id: &str, content: &str, options: IdeaUpdateOptions) -> crate::Result<Idea> {
1224        #[derive(Serialize)]
1225        struct Input<'a> {
1226            id: &'a str,
1227            content: &'a str,
1228            #[serde(flatten)]
1229            options: IdeaUpdateOptions,
1230        }
1231        crate::call("idea.update", &Input { id, content, options })
1232    }
1233
1234}
1235
1236/// The `note` operations.
1237pub mod note {
1238    use super::*;
1239
1240    /// The optional inputs of [`create`]; leave any out with `..Default::default()`.
1241    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1242    pub struct NoteCreateOptions {
1243        #[serde(skip_serializing_if = "Option::is_none")]
1244        pub tags: Option<Vec<String>>,
1245    }
1246
1247    /// Add a note to a project.
1248    ///
1249    /// Needs `note.create` or `content:write` in the manifest's `[permissions]`.
1250    pub fn create(project: &str, content: &str, options: NoteCreateOptions) -> crate::Result<Note> {
1251        #[derive(Serialize)]
1252        struct Input<'a> {
1253            project: &'a str,
1254            content: &'a str,
1255            #[serde(flatten)]
1256            options: NoteCreateOptions,
1257        }
1258        crate::call("note.create", &Input { project, content, options })
1259    }
1260
1261    /// Delete a note for good.
1262    ///
1263    /// Needs `note.delete` (by name) in the manifest's `[permissions]`.
1264    pub fn delete(project: &str, id: i32) -> crate::Result<Note> {
1265        #[derive(Serialize)]
1266        struct Input<'a> {
1267            project: &'a str,
1268            id: i32,
1269        }
1270        crate::call("note.delete", &Input { project, id })
1271    }
1272
1273    /// The optional inputs of [`list`]; leave any out with `..Default::default()`.
1274    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1275    pub struct NoteListOptions {
1276        #[serde(skip_serializing_if = "Option::is_none")]
1277        pub tag: Option<String>,
1278    }
1279
1280    /// A project's notes, optionally only those with a tag.
1281    ///
1282    /// Needs `note.list` or `content:read` in the manifest's `[permissions]`.
1283    pub fn list(project: &str, options: NoteListOptions) -> crate::Result<Notes> {
1284        #[derive(Serialize)]
1285        struct Input<'a> {
1286            project: &'a str,
1287            #[serde(flatten)]
1288            options: NoteListOptions,
1289        }
1290        crate::call("note.list", &Input { project, options })
1291    }
1292
1293    /// One note.
1294    ///
1295    /// Needs `note.read` or `content:read` in the manifest's `[permissions]`.
1296    pub fn read(project: &str, id: i32) -> crate::Result<Note> {
1297        #[derive(Serialize)]
1298        struct Input<'a> {
1299            project: &'a str,
1300            id: i32,
1301        }
1302        crate::call("note.read", &Input { project, id })
1303    }
1304
1305    /// The optional inputs of [`update`]; leave any out with `..Default::default()`.
1306    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1307    pub struct NoteUpdateOptions {
1308        /// Left out, the tags stay as they are.
1309        #[serde(skip_serializing_if = "Option::is_none")]
1310        pub tags: Option<Vec<String>>,
1311    }
1312
1313    /// Replace a note's text, and its tags when given.
1314    ///
1315    /// Needs `note.update` or `content:write` in the manifest's `[permissions]`.
1316    pub fn update(project: &str, id: i32, content: &str, options: NoteUpdateOptions) -> crate::Result<Note> {
1317        #[derive(Serialize)]
1318        struct Input<'a> {
1319            project: &'a str,
1320            id: i32,
1321            content: &'a str,
1322            #[serde(flatten)]
1323            options: NoteUpdateOptions,
1324        }
1325        crate::call("note.update", &Input { project, id, content, options })
1326    }
1327
1328}
1329
1330/// The `ops` operations.
1331pub mod ops {
1332    use super::*;
1333
1334    /// Every operation you may call, with JSON schemas for its input and output.
1335    ///
1336    /// Needs `ops.list` or `content:read` in the manifest's `[permissions]`.
1337    pub fn list() -> crate::Result<OperationList> {
1338        #[derive(Serialize)]
1339        struct Input {
1340        }
1341        crate::call("ops.list", &Input {  })
1342    }
1343
1344}
1345
1346/// The `project` operations.
1347pub mod project {
1348    use super::*;
1349
1350    /// Create an empty project.
1351    ///
1352    /// Needs `project.create` or `content:write` in the manifest's `[permissions]`.
1353    pub fn create(name: &str) -> crate::Result<ProjectName> {
1354        #[derive(Serialize)]
1355        struct Input<'a> {
1356            name: &'a str,
1357        }
1358        crate::call("project.create", &Input { name })
1359    }
1360
1361    /// Delete a project, and everything in it, for good. It must not be open in Hammer.
1362    ///
1363    /// Needs `project.delete` (by name) in the manifest's `[permissions]`.
1364    pub fn delete(project: &str) -> crate::Result<ProjectName> {
1365        #[derive(Serialize)]
1366        struct Input<'a> {
1367            project: &'a str,
1368        }
1369        crate::call("project.delete", &Input { project })
1370    }
1371
1372    /// The optional inputs of [`export`]; leave any out with `..Default::default()`.
1373    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1374    pub struct ProjectExportOptions {
1375        /// Limits the export to these scenes; omitted exports the whole story.
1376        #[serde(rename = "sceneIds")]
1377        #[serde(skip_serializing_if = "Option::is_none")]
1378        pub scene_ids: Option<Vec<i32>>,
1379        #[serde(rename = "treatTopLevelAsChapters")]
1380        #[serde(skip_serializing_if = "Option::is_none")]
1381        pub treat_top_level_as_chapters: Option<bool>,
1382    }
1383
1384    /// Export a project, or some of its scenes, in one of the formats from export.formats.
1385    ///
1386    /// Needs `project.export` or `content:read` in the manifest's `[permissions]`.
1387    pub fn export(project: &str, format: &str, options: ProjectExportOptions) -> crate::Result<ExportedFile> {
1388        #[derive(Serialize)]
1389        struct Input<'a> {
1390            project: &'a str,
1391            format: &'a str,
1392            #[serde(flatten)]
1393            options: ProjectExportOptions,
1394        }
1395        crate::call("project.export", &Input { project, format, options })
1396    }
1397
1398    /// The optional inputs of [`import`]; leave any out with `..Default::default()`.
1399    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1400    pub struct ProjectImportOptions {
1401        /// Left out, the title the file gives itself.
1402        #[serde(skip_serializing_if = "Option::is_none")]
1403        pub name: Option<String>,
1404        #[serde(rename = "markdownSplit")]
1405        #[serde(skip_serializing_if = "Option::is_none")]
1406        pub markdown_split: Option<MarkdownSplit>,
1407        #[serde(rename = "rtfSplit")]
1408        #[serde(skip_serializing_if = "Option::is_none")]
1409        pub rtf_split: Option<RtfSplit>,
1410        /// A regular expression for the lines that start a chapter; left out, chapter, part, prologue, and epilogue.
1411        #[serde(rename = "chapterPattern")]
1412        #[serde(skip_serializing_if = "Option::is_none")]
1413        pub chapter_pattern: Option<String>,
1414        /// Put each chapter's scenes in a group.
1415        #[serde(rename = "chapterGroups")]
1416        #[serde(skip_serializing_if = "Option::is_none")]
1417        pub chapter_groups: Option<bool>,
1418    }
1419
1420    /// Create a project from a Markdown or RTF manuscript, split into scenes by its headings or a chapter pattern.
1421    ///
1422    /// Needs `project.import` or `content:write` in the manifest's `[permissions]`.
1423    pub fn import(format: ImportFileFormat, content: &[u8], options: ProjectImportOptions) -> crate::Result<ProjectImported> {
1424        #[derive(Serialize)]
1425        struct Input<'a> {
1426            format: ImportFileFormat,
1427            #[serde(serialize_with = "crate::base64::serialize")]
1428            content: &'a [u8],
1429            #[serde(flatten)]
1430            options: ProjectImportOptions,
1431        }
1432        crate::call("project.import", &Input { format, content, options })
1433    }
1434
1435    /// A project's details: author, language, tags, word count goal, cached totals, and sync linkage.
1436    ///
1437    /// Needs `project.info` or `content:read` in the manifest's `[permissions]`.
1438    pub fn info(project: &str) -> crate::Result<ProjectInfo> {
1439        #[derive(Serialize)]
1440        struct Input<'a> {
1441            project: &'a str,
1442        }
1443        crate::call("project.info", &Input { project })
1444    }
1445
1446    /// List every project with its word count and when it was last edited.
1447    ///
1448    /// Needs `project.list` or `content:read` in the manifest's `[permissions]`.
1449    pub fn list() -> crate::Result<ProjectList> {
1450        #[derive(Serialize)]
1451        struct Input {
1452        }
1453        crate::call("project.list", &Input {  })
1454    }
1455
1456    /// Rename a project. It must not be open in Hammer.
1457    ///
1458    /// Needs `project.rename` or `content:write` in the manifest's `[permissions]`.
1459    pub fn rename(project: &str, name: &str) -> crate::Result<ProjectName> {
1460        #[derive(Serialize)]
1461        struct Input<'a> {
1462            project: &'a str,
1463            name: &'a str,
1464        }
1465        crate::call("project.rename", &Input { project, name })
1466    }
1467
1468}
1469
1470/// The `scene` operations.
1471pub mod scene {
1472    use super::*;
1473
1474    /// Add markdown to the end of a scene's text, as a new paragraph.
1475    ///
1476    /// Needs `scene.append` or `content:write` in the manifest's `[permissions]`.
1477    pub fn append(project: &str, id: i32, markdown: &str) -> crate::Result<SceneWordCount> {
1478        #[derive(Serialize)]
1479        struct Input<'a> {
1480            project: &'a str,
1481            id: i32,
1482            markdown: &'a str,
1483        }
1484        crate::call("scene.append", &Input { project, id, markdown })
1485    }
1486
1487    /// Archive a scene: take it out of the story, keeping its text, drafts, and notes.
1488    ///
1489    /// Needs `scene.archive` or `content:write` in the manifest's `[permissions]`.
1490    pub fn archive(project: &str, id: i32) -> crate::Result<SceneItemRef> {
1491        #[derive(Serialize)]
1492        struct Input<'a> {
1493            project: &'a str,
1494            id: i32,
1495        }
1496        crate::call("scene.archive", &Input { project, id })
1497    }
1498
1499    /// A project's archived scenes.
1500    ///
1501    /// Needs `scene.archived` or `content:read` in the manifest's `[permissions]`.
1502    pub fn archived(project: &str) -> crate::Result<ArchivedScenes> {
1503        #[derive(Serialize)]
1504        struct Input<'a> {
1505            project: &'a str,
1506        }
1507        crate::call("scene.archived", &Input { project })
1508    }
1509
1510    /// The optional inputs of [`create`]; leave any out with `..Default::default()`.
1511    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1512    pub struct SceneCreateOptions {
1513        #[serde(skip_serializing_if = "Option::is_none")]
1514        pub kind: Option<SceneKind>,
1515        /// The group to create it in; left out, the top level.
1516        #[serde(rename = "parentId")]
1517        #[serde(skip_serializing_if = "Option::is_none")]
1518        pub parent_id: Option<i32>,
1519        /// Its position among its siblings; left out, the end.
1520        #[serde(skip_serializing_if = "Option::is_none")]
1521        pub index: Option<i32>,
1522    }
1523
1524    /// Create an empty scene or group, at the end of its parent unless an index is given.
1525    ///
1526    /// Needs `scene.create` or `content:write` in the manifest's `[permissions]`.
1527    pub fn create(project: &str, name: &str, options: SceneCreateOptions) -> crate::Result<SceneItemRef> {
1528        #[derive(Serialize)]
1529        struct Input<'a> {
1530            project: &'a str,
1531            name: &'a str,
1532            #[serde(flatten)]
1533            options: SceneCreateOptions,
1534        }
1535        crate::call("scene.create", &Input { project, name, options })
1536    }
1537
1538    /// Delete a scene, archived or not, or an empty group, for good.
1539    ///
1540    /// Needs `scene.delete` (by name) in the manifest's `[permissions]`.
1541    pub fn delete(project: &str, id: i32) -> crate::Result<SceneItemRef> {
1542        #[derive(Serialize)]
1543        struct Input<'a> {
1544            project: &'a str,
1545            id: i32,
1546        }
1547        crate::call("scene.delete", &Input { project, id })
1548    }
1549
1550    /// The optional inputs of [`r#move`]; leave any out with `..Default::default()`.
1551    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1552    pub struct SceneMoveOptions {
1553        /// The group to move into; left out, the top level.
1554        #[serde(rename = "parentId")]
1555        #[serde(skip_serializing_if = "Option::is_none")]
1556        pub parent_id: Option<i32>,
1557    }
1558
1559    /// Move a scene or group to a position within a group, or the top level when parentId is left out. index is its position there after the move.
1560    ///
1561    /// Needs `scene.move` or `content:write` in the manifest's `[permissions]`.
1562    pub fn r#move(project: &str, id: i32, index: i32, options: SceneMoveOptions) -> crate::Result<SceneItemRef> {
1563        #[derive(Serialize)]
1564        struct Input<'a> {
1565            project: &'a str,
1566            id: i32,
1567            index: i32,
1568            #[serde(flatten)]
1569            options: SceneMoveOptions,
1570        }
1571        crate::call("scene.move", &Input { project, id, index, options })
1572    }
1573
1574    /// A scene's markdown, including unsaved edits, with its outline, notes, and tags.
1575    ///
1576    /// Needs `scene.read` or `content:read` in the manifest's `[permissions]`.
1577    pub fn read(project: &str, id: i32) -> crate::Result<SceneText> {
1578        #[derive(Serialize)]
1579        struct Input<'a> {
1580            project: &'a str,
1581            id: i32,
1582        }
1583        crate::call("scene.read", &Input { project, id })
1584    }
1585
1586    /// Rename a scene or group.
1587    ///
1588    /// Needs `scene.rename` or `content:write` in the manifest's `[permissions]`.
1589    pub fn rename(project: &str, id: i32, name: &str) -> crate::Result<SceneItemRef> {
1590        #[derive(Serialize)]
1591        struct Input<'a> {
1592            project: &'a str,
1593            id: i32,
1594            name: &'a str,
1595        }
1596        crate::call("scene.rename", &Input { project, id, name })
1597    }
1598
1599    /// A project's scenes and groups in story order, with word counts.
1600    ///
1601    /// Needs `scene.tree` or `content:read` in the manifest's `[permissions]`.
1602    pub fn tree(project: &str) -> crate::Result<SceneTree> {
1603        #[derive(Serialize)]
1604        struct Input<'a> {
1605            project: &'a str,
1606        }
1607        crate::call("scene.tree", &Input { project })
1608    }
1609
1610    /// Return an archived scene to the story, at the end of the top level.
1611    ///
1612    /// Needs `scene.unarchive` or `content:write` in the manifest's `[permissions]`.
1613    pub fn unarchive(project: &str, id: i32) -> crate::Result<SceneItemRef> {
1614        #[derive(Serialize)]
1615        struct Input<'a> {
1616            project: &'a str,
1617            id: i32,
1618        }
1619        crate::call("scene.unarchive", &Input { project, id })
1620    }
1621
1622    /// The optional inputs of [`write`]; leave any out with `..Default::default()`.
1623    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1624    pub struct SceneWriteOptions {
1625        /// The new draft's name, in draft mode only.
1626        #[serde(rename = "draftName")]
1627        #[serde(skip_serializing_if = "Option::is_none")]
1628        pub draft_name: Option<String>,
1629    }
1630
1631    /// Replace a scene's text with markdown. Mode draft saves it as a new draft of the scene and leaves the scene alone. Mode live replaces the scene's text, saving the old text as a draft first.
1632    ///
1633    /// Needs `scene.write` or `content:write` in the manifest's `[permissions]`.
1634    pub fn write(project: &str, id: i32, mode: WriteMode, markdown: &str, options: SceneWriteOptions) -> crate::Result<SceneWriteResult> {
1635        #[derive(Serialize)]
1636        struct Input<'a> {
1637            project: &'a str,
1638            id: i32,
1639            mode: WriteMode,
1640            markdown: &'a str,
1641            #[serde(flatten)]
1642            options: SceneWriteOptions,
1643        }
1644        crate::call("scene.write", &Input { project, id, mode, markdown, options })
1645    }
1646
1647    /// The `scene.meta` operations.
1648    pub mod meta {
1649        use super::*;
1650
1651        /// A scene's outline, notes, tags, and references: the entries confirmed as in it, and those dismissed.
1652        ///
1653        /// Needs `scene.meta.read` or `content:read` in the manifest's `[permissions]`.
1654        pub fn read(project: &str, id: i32) -> crate::Result<SceneMeta> {
1655            #[derive(Serialize)]
1656            struct Input<'a> {
1657                project: &'a str,
1658                id: i32,
1659            }
1660            crate::call("scene.meta.read", &Input { project, id })
1661        }
1662
1663        /// The optional inputs of [`write`]; leave any out with `..Default::default()`.
1664        #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1665        pub struct SceneMetaWriteOptions {
1666            #[serde(skip_serializing_if = "Option::is_none")]
1667            pub outline: Option<String>,
1668            #[serde(skip_serializing_if = "Option::is_none")]
1669            pub notes: Option<String>,
1670            #[serde(skip_serializing_if = "Option::is_none")]
1671            pub tags: Option<Vec<String>>,
1672        }
1673
1674        /// Change a scene's outline, notes, or tags. Fields left out keep their value.
1675        ///
1676        /// Needs `scene.meta.write` or `content:write` in the manifest's `[permissions]`.
1677        pub fn write(project: &str, id: i32, options: SceneMetaWriteOptions) -> crate::Result<SceneMeta> {
1678            #[derive(Serialize)]
1679            struct Input<'a> {
1680                project: &'a str,
1681                id: i32,
1682                #[serde(flatten)]
1683                options: SceneMetaWriteOptions,
1684            }
1685            crate::call("scene.meta.write", &Input { project, id, options })
1686        }
1687
1688    }
1689
1690    /// The `scene.read` operations.
1691    pub mod read {
1692        use super::*;
1693
1694        /// The optional inputs of [`many`]; leave any out with `..Default::default()`.
1695        #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1696        pub struct SceneReadManyOptions {
1697            /// A group whose scenes, at any depth, to read.
1698            #[serde(skip_serializing_if = "Option::is_none")]
1699            pub group: Option<i32>,
1700            #[serde(skip_serializing_if = "Option::is_none")]
1701            pub ids: Option<Vec<i32>>,
1702            /// The previous page's next.
1703            #[serde(skip_serializing_if = "Option::is_none")]
1704            pub after: Option<i32>,
1705            #[serde(rename = "maxWords")]
1706            #[serde(skip_serializing_if = "Option::is_none")]
1707            pub max_words: Option<i32>,
1708        }
1709
1710        /// Scenes in story order with their markdown, metadata, and the groups they sit in, a page of about maxWords, counting outlines and notes, at a time: every scene, a group's, or those in ids. Archived scenes are left out. Pass next as after for the following page; it is null on the last.
1711        ///
1712        /// Needs `scene.read.many` or `content:read` in the manifest's `[permissions]`.
1713        pub fn many(project: &str, options: SceneReadManyOptions) -> crate::Result<ScenePage> {
1714            #[derive(Serialize)]
1715            struct Input<'a> {
1716                project: &'a str,
1717                #[serde(flatten)]
1718                options: SceneReadManyOptions,
1719            }
1720            crate::call("scene.read.many", &Input { project, options })
1721        }
1722
1723    }
1724
1725    /// The `scene.references` operations.
1726    pub mod references {
1727        use super::*;
1728
1729        /// The optional inputs of [`set`]; leave any out with `..Default::default()`.
1730        #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1731        pub struct SceneReferencesSetOptions {
1732            #[serde(skip_serializing_if = "Option::is_none")]
1733            pub confirm: Option<Vec<i32>>,
1734            #[serde(skip_serializing_if = "Option::is_none")]
1735            pub dismiss: Option<Vec<i32>>,
1736            #[serde(skip_serializing_if = "Option::is_none")]
1737            pub clear: Option<Vec<i32>>,
1738        }
1739
1740        /// Change which entries a scene references. confirm marks entries as in the scene, and un-dismisses them; dismiss marks entries as only mentioned, so name matching stops adding them; clear forgets entries either way, so a later match can add them again.
1741        ///
1742        /// Needs `scene.references.set` or `content:write` in the manifest's `[permissions]`.
1743        pub fn set(project: &str, id: i32, options: SceneReferencesSetOptions) -> crate::Result<SceneMeta> {
1744            #[derive(Serialize)]
1745            struct Input<'a> {
1746                project: &'a str,
1747                id: i32,
1748                #[serde(flatten)]
1749                options: SceneReferencesSetOptions,
1750            }
1751            crate::call("scene.references.set", &Input { project, id, options })
1752        }
1753
1754    }
1755
1756}
1757
1758/// The `stats` operations.
1759pub mod stats {
1760    use super::*;
1761
1762    /// The optional inputs of [`activity`]; leave any out with `..Default::default()`.
1763    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1764    pub struct StatsActivityOptions {
1765        /// First day included, in the device's time zone; omitted for no lower bound. An ISO 8601 date, such as `2026-03-01`.
1766        #[serde(skip_serializing_if = "Option::is_none")]
1767        pub from: Option<String>,
1768        /// Last day included; omitted for no upper bound. An ISO 8601 date, such as `2026-03-01`.
1769        #[serde(skip_serializing_if = "Option::is_none")]
1770        pub to: Option<String>,
1771    }
1772
1773    /// Words written per day over a date range, plus lifetime words per device.
1774    ///
1775    /// Needs `stats.activity` or `content:read` in the manifest's `[permissions]`.
1776    pub fn activity(project: &str, options: StatsActivityOptions) -> crate::Result<Activity> {
1777        #[derive(Serialize)]
1778        struct Input<'a> {
1779            project: &'a str,
1780            #[serde(flatten)]
1781            options: StatsActivityOptions,
1782        }
1783        crate::call("stats.activity", &Input { project, options })
1784    }
1785
1786    /// The optional inputs of [`project`]; leave any out with `..Default::default()`.
1787    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1788    pub struct StatsProjectOptions {
1789        /// Recalculate even when the cached statistics are current.
1790        #[serde(skip_serializing_if = "Option::is_none")]
1791        pub recalculate: Option<bool>,
1792    }
1793
1794    /// A project's statistics, as its Home screen shows them.
1795    ///
1796    /// Needs `stats.project` or `content:read` in the manifest's `[permissions]`.
1797    pub fn project(project: &str, options: StatsProjectOptions) -> crate::Result<ProjectStats> {
1798        #[derive(Serialize)]
1799        struct Input<'a> {
1800            project: &'a str,
1801            #[serde(flatten)]
1802            options: StatsProjectOptions,
1803        }
1804        crate::call("stats.project", &Input { project, options })
1805    }
1806
1807    /// The optional inputs of [`sessions`]; leave any out with `..Default::default()`.
1808    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1809    pub struct StatsSessionsOptions {
1810        /// First day included, in the device's time zone; omitted for no lower bound. An ISO 8601 date, such as `2026-03-01`.
1811        #[serde(skip_serializing_if = "Option::is_none")]
1812        pub from: Option<String>,
1813        /// Last day included; omitted for no upper bound. An ISO 8601 date, such as `2026-03-01`.
1814        #[serde(skip_serializing_if = "Option::is_none")]
1815        pub to: Option<String>,
1816    }
1817
1818    /// Writing sessions over a date range, from every device.
1819    ///
1820    /// Needs `stats.sessions` or `content:read` in the manifest's `[permissions]`.
1821    pub fn sessions(project: &str, options: StatsSessionsOptions) -> crate::Result<Sessions> {
1822        #[derive(Serialize)]
1823        struct Input<'a> {
1824            project: &'a str,
1825            #[serde(flatten)]
1826            options: StatsSessionsOptions,
1827        }
1828        crate::call("stats.sessions", &Input { project, options })
1829    }
1830
1831}
1832
1833/// The `sync` operations.
1834pub mod sync {
1835    use super::*;
1836
1837    /// The optional inputs of [`run`]; leave any out with `..Default::default()`.
1838    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1839    pub struct SyncRunOptions {
1840        /// Sync only this project; account changes and ideas still sync.
1841        #[serde(skip_serializing_if = "Option::is_none")]
1842        pub project: Option<String>,
1843        #[serde(rename = "onConflict")]
1844        #[serde(skip_serializing_if = "Option::is_none")]
1845        pub on_conflict: Option<ConflictChoice>,
1846    }
1847
1848    /// Sync the account and every linked project with the server, as Sync all does. A project with a conflict is left for the app.
1849    ///
1850    /// Needs `sync.run` or `account:write` in the manifest's `[permissions]`.
1851    pub fn run(options: SyncRunOptions) -> crate::Result<SyncRunResult> {
1852        #[derive(Serialize)]
1853        struct Input {
1854            #[serde(flatten)]
1855            options: SyncRunOptions,
1856        }
1857        crate::call("sync.run", &Input { options })
1858    }
1859
1860    /// Each project's link to the sync server, its last sync, and how many of its changes are waiting to sync.
1861    ///
1862    /// Needs `sync.status` or `account:read` in the manifest's `[permissions]`.
1863    pub fn status() -> crate::Result<SyncStatus> {
1864        #[derive(Serialize)]
1865        struct Input {
1866        }
1867        crate::call("sync.status", &Input {  })
1868    }
1869
1870}
1871
1872/// The `tag` operations.
1873pub mod tag {
1874    use super::*;
1875
1876    /// Every scene, note, entry, and timeline event carrying a tag.
1877    ///
1878    /// Needs `tag.find` or `content:read` in the manifest's `[permissions]`.
1879    pub fn find(project: &str, tag: &str) -> crate::Result<TaggedEntities> {
1880        #[derive(Serialize)]
1881        struct Input<'a> {
1882            project: &'a str,
1883            tag: &'a str,
1884        }
1885        crate::call("tag.find", &Input { project, tag })
1886    }
1887
1888    /// The optional inputs of [`list`]; leave any out with `..Default::default()`.
1889    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1890    pub struct TagListOptions {
1891        #[serde(skip_serializing_if = "Option::is_none")]
1892        pub kind: Option<EntityKind>,
1893        #[serde(skip_serializing_if = "Option::is_none")]
1894        pub limit: Option<i32>,
1895    }
1896
1897    /// The tags used in a project, most used first, optionally counting one kind of entity.
1898    ///
1899    /// Needs `tag.list` or `content:read` in the manifest's `[permissions]`.
1900    pub fn list(project: &str, options: TagListOptions) -> crate::Result<Tags> {
1901        #[derive(Serialize)]
1902        struct Input<'a> {
1903            project: &'a str,
1904            #[serde(flatten)]
1905            options: TagListOptions,
1906        }
1907        crate::call("tag.list", &Input { project, options })
1908    }
1909
1910}
1911
1912/// The `timeline` operations.
1913pub mod timeline {
1914    use super::*;
1915
1916    /// The optional inputs of [`create`]; leave any out with `..Default::default()`.
1917    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1918    pub struct TimelineCreateOptions {
1919        /// Free text, such as "Day 3" or "Spring, 1802".
1920        #[serde(skip_serializing_if = "Option::is_none")]
1921        pub date: Option<String>,
1922        #[serde(skip_serializing_if = "Option::is_none")]
1923        pub tags: Option<Vec<String>>,
1924        /// Its position in the timeline; left out, the end.
1925        #[serde(skip_serializing_if = "Option::is_none")]
1926        pub index: Option<i32>,
1927    }
1928
1929    /// Add an event to a project's timeline, at the end unless an index is given.
1930    ///
1931    /// Needs `timeline.create` or `content:write` in the manifest's `[permissions]`.
1932    pub fn create(project: &str, content: &str, options: TimelineCreateOptions) -> crate::Result<TimelineEntry> {
1933        #[derive(Serialize)]
1934        struct Input<'a> {
1935            project: &'a str,
1936            content: &'a str,
1937            #[serde(flatten)]
1938            options: TimelineCreateOptions,
1939        }
1940        crate::call("timeline.create", &Input { project, content, options })
1941    }
1942
1943    /// Delete a timeline event for good.
1944    ///
1945    /// Needs `timeline.delete` (by name) in the manifest's `[permissions]`.
1946    pub fn delete(project: &str, id: i32) -> crate::Result<TimelineEntry> {
1947        #[derive(Serialize)]
1948        struct Input<'a> {
1949            project: &'a str,
1950            id: i32,
1951        }
1952        crate::call("timeline.delete", &Input { project, id })
1953    }
1954
1955    /// A project's timeline events in order.
1956    ///
1957    /// Needs `timeline.list` or `content:read` in the manifest's `[permissions]`.
1958    pub fn list(project: &str) -> crate::Result<Timeline> {
1959        #[derive(Serialize)]
1960        struct Input<'a> {
1961            project: &'a str,
1962        }
1963        crate::call("timeline.list", &Input { project })
1964    }
1965
1966    /// Move a timeline event to a position; index is its position after the move.
1967    ///
1968    /// Needs `timeline.move` or `content:write` in the manifest's `[permissions]`.
1969    pub fn r#move(project: &str, id: i32, index: i32) -> crate::Result<TimelineEntry> {
1970        #[derive(Serialize)]
1971        struct Input<'a> {
1972            project: &'a str,
1973            id: i32,
1974            index: i32,
1975        }
1976        crate::call("timeline.move", &Input { project, id, index })
1977    }
1978
1979    /// One timeline event.
1980    ///
1981    /// Needs `timeline.read` or `content:read` in the manifest's `[permissions]`.
1982    pub fn read(project: &str, id: i32) -> crate::Result<TimelineEntry> {
1983        #[derive(Serialize)]
1984        struct Input<'a> {
1985            project: &'a str,
1986            id: i32,
1987        }
1988        crate::call("timeline.read", &Input { project, id })
1989    }
1990
1991    /// The optional inputs of [`update`]; leave any out with `..Default::default()`.
1992    #[derive(Debug, Clone, Default, PartialEq, Serialize)]
1993    pub struct TimelineUpdateOptions {
1994        /// Left out, unchanged; empty, cleared.
1995        #[serde(skip_serializing_if = "Option::is_none")]
1996        pub date: Option<String>,
1997        #[serde(skip_serializing_if = "Option::is_none")]
1998        pub tags: Option<Vec<String>>,
1999    }
2000
2001    /// Replace a timeline event's text, and its date or tags when given. An empty date clears it.
2002    ///
2003    /// Needs `timeline.update` or `content:write` in the manifest's `[permissions]`.
2004    pub fn update(project: &str, id: i32, content: &str, options: TimelineUpdateOptions) -> crate::Result<TimelineEntry> {
2005        #[derive(Serialize)]
2006        struct Input<'a> {
2007            project: &'a str,
2008            id: i32,
2009            content: &'a str,
2010            #[serde(flatten)]
2011            options: TimelineUpdateOptions,
2012        }
2013        crate::call("timeline.update", &Input { project, id, content, options })
2014    }
2015
2016}