spreadsheet_mcp/
model.rs

1use crate::caps::BackendCaps;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Default)]
7#[serde(transparent)]
8pub struct WorkbookId(pub String);
9
10impl WorkbookId {
11    pub fn as_str(&self) -> &str {
12        &self.0
13    }
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
17pub struct WorkbookDescriptor {
18    pub workbook_id: WorkbookId,
19    pub short_id: String,
20    pub slug: String,
21    pub folder: Option<String>,
22    pub path: String,
23    pub bytes: u64,
24    pub last_modified: Option<String>,
25    pub caps: BackendCaps,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
29pub struct WorkbookListResponse {
30    pub workbooks: Vec<WorkbookDescriptor>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
34pub struct WorkbookDescription {
35    pub workbook_id: WorkbookId,
36    pub short_id: String,
37    pub slug: String,
38    pub path: String,
39    pub bytes: u64,
40    pub sheet_count: usize,
41    pub defined_names: usize,
42    pub tables: usize,
43    pub macros_present: bool,
44    pub last_modified: Option<String>,
45    pub caps: BackendCaps,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
49pub struct WorkbookSummaryResponse {
50    pub workbook_id: WorkbookId,
51    pub workbook_short_id: String,
52    pub slug: String,
53    pub sheet_count: usize,
54    pub total_cells: u64,
55    pub total_formulas: u64,
56    pub breakdown: WorkbookBreakdown,
57    pub region_counts: RegionCountSummary,
58    pub region_counts_truncated: bool,
59    pub key_named_ranges: Vec<NamedRangeDescriptor>,
60    pub suggested_entry_points: Vec<EntryPoint>,
61    pub entry_points_truncated: bool,
62    pub notes: Vec<String>,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
66pub struct WorkbookBreakdown {
67    pub data_sheets: u32,
68    pub calculator_sheets: u32,
69    pub parameter_sheets: u32,
70    pub metadata_sheets: u32,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
74pub struct RegionCountSummary {
75    pub data: u32,
76    pub parameters: u32,
77    pub outputs: u32,
78    pub calculator: u32,
79    pub metadata: u32,
80    pub other: u32,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
84pub struct EntryPoint {
85    pub sheet_name: String,
86    pub region_id: Option<u32>,
87    pub bounds: Option<String>,
88    pub rationale: String,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
92pub struct SheetSummary {
93    pub name: String,
94    pub visible: bool,
95    pub row_count: u32,
96    pub column_count: u32,
97    pub non_empty_cells: u32,
98    pub formula_cells: u32,
99    pub cached_values: u32,
100    pub classification: SheetClassification,
101    pub style_tags: Vec<String>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
105#[serde(rename_all = "snake_case")]
106pub enum SheetClassification {
107    Data,
108    Calculator,
109    Mixed,
110    Metadata,
111    Empty,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115pub struct SheetListResponse {
116    pub workbook_id: WorkbookId,
117    pub workbook_short_id: String,
118    pub sheets: Vec<SheetSummary>,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
122pub struct SheetOverviewResponse {
123    pub workbook_id: WorkbookId,
124    pub workbook_short_id: String,
125    pub sheet_name: String,
126    pub narrative: String,
127    pub regions: Vec<SheetRegion>,
128    pub detected_regions: Vec<DetectedRegion>,
129    pub detected_region_count: u32,
130    pub detected_regions_truncated: bool,
131    pub key_ranges: Vec<String>,
132    pub formula_ratio: f32,
133    pub notable_features: Vec<String>,
134    pub notes: Vec<String>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
138pub struct SheetRegion {
139    pub kind: RegionKind,
140    pub address: String,
141    pub description: String,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
145pub enum RegionKind {
146    #[serde(rename = "likely_table")]
147    Table,
148    #[serde(rename = "likely_data")]
149    Data,
150    #[serde(rename = "likely_parameters")]
151    Parameters,
152    #[serde(rename = "likely_outputs")]
153    Outputs,
154    #[serde(rename = "likely_calculator")]
155    Calculator,
156    #[serde(rename = "likely_metadata")]
157    Metadata,
158    #[serde(rename = "likely_styles")]
159    Styles,
160    #[serde(rename = "likely_comments")]
161    Comments,
162    #[serde(rename = "unknown")]
163    Other,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
167pub struct DetectedRegion {
168    pub id: u32,
169    pub bounds: String,
170    pub header_row: Option<u32>,
171    pub headers: Vec<String>,
172    pub header_count: u32,
173    pub headers_truncated: bool,
174    pub row_count: u32,
175    pub classification: RegionKind,
176    pub region_kind: Option<RegionKind>,
177    pub confidence: f32,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
181pub struct SheetPageResponse {
182    pub workbook_id: WorkbookId,
183    pub workbook_short_id: String,
184    pub sheet_name: String,
185    pub rows: Vec<RowSnapshot>,
186    pub has_more: bool,
187    pub next_start_row: Option<u32>,
188    pub header_row: Option<RowSnapshot>,
189    pub compact: Option<SheetPageCompact>,
190    pub values_only: Option<SheetPageValues>,
191    pub format: SheetPageFormat,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
195pub struct RowSnapshot {
196    pub row_index: u32,
197    pub cells: Vec<CellSnapshot>,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
201pub struct CellSnapshot {
202    pub address: String,
203    pub value: Option<CellValue>,
204    pub formula: Option<String>,
205    pub cached_value: Option<CellValue>,
206    pub number_format: Option<String>,
207    pub style_tags: Vec<String>,
208    pub notes: Vec<String>,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
212#[serde(tag = "kind", content = "value")]
213pub enum CellValue {
214    Text(String),
215    Number(f64),
216    Bool(bool),
217    Error(String),
218    Date(String),
219}
220
221#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
222#[serde(rename_all = "snake_case")]
223#[derive(Default)]
224pub enum SheetPageFormat {
225    #[default]
226    Full,
227    Compact,
228    ValuesOnly,
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
232pub struct SheetPageCompact {
233    pub headers: Vec<String>,
234    pub header_row: Vec<Option<CellValue>>,
235    pub rows: Vec<Vec<Option<CellValue>>>,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
239pub struct SheetPageValues {
240    pub rows: Vec<Vec<Option<CellValue>>>,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
244pub struct SheetStatisticsResponse {
245    pub workbook_id: WorkbookId,
246    pub workbook_short_id: String,
247    pub sheet_name: String,
248    pub row_count: u32,
249    pub column_count: u32,
250    pub density: f32,
251    pub numeric_columns: Vec<ColumnSummary>,
252    pub text_columns: Vec<ColumnSummary>,
253    pub null_counts: BTreeMap<String, u32>,
254    pub duplicate_warnings: Vec<String>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
258pub struct ColumnSummary {
259    pub header: Option<String>,
260    pub column: String,
261    pub samples: Vec<CellValue>,
262    pub min: Option<f64>,
263    pub max: Option<f64>,
264    pub mean: Option<f64>,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
268pub struct SheetFormulaMapResponse {
269    pub workbook_id: WorkbookId,
270    pub workbook_short_id: String,
271    pub sheet_name: String,
272    pub groups: Vec<FormulaGroup>,
273    pub truncated: bool,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
277pub struct FormulaGroup {
278    pub fingerprint: String,
279    pub addresses: Vec<String>,
280    pub formula: String,
281    pub is_array: bool,
282    pub is_shared: bool,
283    pub is_volatile: bool,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
287pub struct FormulaTraceResponse {
288    pub workbook_id: WorkbookId,
289    pub workbook_short_id: String,
290    pub sheet_name: String,
291    pub origin: String,
292    pub direction: TraceDirection,
293    pub layers: Vec<TraceLayer>,
294    pub next_cursor: Option<TraceCursor>,
295    pub notes: Vec<String>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
299pub struct FormulaTraceEdge {
300    pub from: String,
301    pub to: String,
302    pub formula: Option<String>,
303    pub note: Option<String>,
304}
305
306#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
307pub struct TraceLayer {
308    pub depth: u32,
309    pub summary: TraceLayerSummary,
310    pub highlights: TraceLayerHighlights,
311    pub edges: Vec<FormulaTraceEdge>,
312    pub has_more: bool,
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
316pub struct TraceLayerSummary {
317    pub total_nodes: usize,
318    pub formula_nodes: usize,
319    pub value_nodes: usize,
320    pub blank_nodes: usize,
321    pub external_nodes: usize,
322    pub unique_formula_groups: usize,
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
326pub struct TraceLayerHighlights {
327    pub top_ranges: Vec<TraceRangeHighlight>,
328    pub top_formula_groups: Vec<TraceFormulaGroupHighlight>,
329    pub notable_cells: Vec<TraceCellHighlight>,
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
333pub struct TraceRangeHighlight {
334    pub start: String,
335    pub end: String,
336    pub count: usize,
337    pub literals: usize,
338    pub formulas: usize,
339    pub blanks: usize,
340    pub sample_values: Vec<CellValue>,
341    pub sample_formulas: Vec<String>,
342    pub sample_addresses: Vec<String>,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
346pub struct TraceFormulaGroupHighlight {
347    pub fingerprint: String,
348    pub formula: String,
349    pub count: usize,
350    pub sample_addresses: Vec<String>,
351}
352
353#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
354pub struct TraceCellHighlight {
355    pub address: String,
356    pub kind: TraceCellKind,
357    pub value: Option<CellValue>,
358    pub formula: Option<String>,
359}
360
361#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)]
362#[serde(rename_all = "snake_case")]
363pub enum TraceCellKind {
364    Formula,
365    Literal,
366    Blank,
367    External,
368}
369
370#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
371pub struct TraceCursor {
372    pub depth: u32,
373    pub offset: usize,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
377#[serde(rename_all = "snake_case")]
378pub enum TraceDirection {
379    Precedents,
380    Dependents,
381}
382
383#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
384pub struct NamedRangeDescriptor {
385    pub name: String,
386    pub scope: Option<String>,
387    pub refers_to: String,
388    pub kind: NamedItemKind,
389    pub sheet_name: Option<String>,
390    pub comment: Option<String>,
391}
392
393#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
394#[serde(rename_all = "snake_case")]
395pub enum NamedItemKind {
396    NamedRange,
397    Table,
398    Formula,
399    Unknown,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
403pub struct NamedRangesResponse {
404    pub workbook_id: WorkbookId,
405    pub workbook_short_id: String,
406    pub items: Vec<NamedRangeDescriptor>,
407}
408
409#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
410pub struct FindFormulaMatch {
411    pub address: String,
412    pub sheet_name: String,
413    pub formula: String,
414    pub cached_value: Option<CellValue>,
415    pub context: Vec<RowSnapshot>,
416}
417
418#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
419pub struct FindFormulaResponse {
420    pub workbook_id: WorkbookId,
421    pub workbook_short_id: String,
422    pub matches: Vec<FindFormulaMatch>,
423    pub truncated: bool,
424    pub next_offset: Option<u32>,
425}
426
427#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
428pub struct VolatileScanEntry {
429    pub address: String,
430    pub sheet_name: String,
431    pub function: String,
432    pub note: Option<String>,
433}
434
435#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
436pub struct VolatileScanResponse {
437    pub workbook_id: WorkbookId,
438    pub workbook_short_id: String,
439    pub items: Vec<VolatileScanEntry>,
440    pub truncated: bool,
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
444pub struct StyleDescriptor {
445    pub font: Option<FontDescriptor>,
446    pub fill: Option<FillDescriptor>,
447    pub borders: Option<BordersDescriptor>,
448    pub alignment: Option<AlignmentDescriptor>,
449    pub number_format: Option<String>,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
453pub struct FontDescriptor {
454    pub name: Option<String>,
455    pub size: Option<f64>,
456    pub bold: Option<bool>,
457    pub italic: Option<bool>,
458    pub underline: Option<String>,
459    pub strikethrough: Option<bool>,
460    pub color: Option<String>,
461}
462
463#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
464#[serde(tag = "kind", rename_all = "snake_case")]
465pub enum FillDescriptor {
466    Pattern(PatternFillDescriptor),
467    Gradient(GradientFillDescriptor),
468}
469
470#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
471pub struct PatternFillDescriptor {
472    pub pattern_type: Option<String>,
473    pub foreground_color: Option<String>,
474    pub background_color: Option<String>,
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
478pub struct GradientFillDescriptor {
479    pub degree: Option<f64>,
480    pub stops: Vec<GradientStopDescriptor>,
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
484pub struct GradientStopDescriptor {
485    pub position: f64,
486    pub color: String,
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
490pub struct BordersDescriptor {
491    pub left: Option<BorderSideDescriptor>,
492    pub right: Option<BorderSideDescriptor>,
493    pub top: Option<BorderSideDescriptor>,
494    pub bottom: Option<BorderSideDescriptor>,
495    pub diagonal: Option<BorderSideDescriptor>,
496    pub vertical: Option<BorderSideDescriptor>,
497    pub horizontal: Option<BorderSideDescriptor>,
498    pub diagonal_up: Option<bool>,
499    pub diagonal_down: Option<bool>,
500}
501
502#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
503pub struct BorderSideDescriptor {
504    pub style: Option<String>,
505    pub color: Option<String>,
506}
507
508#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
509pub struct AlignmentDescriptor {
510    pub horizontal: Option<String>,
511    pub vertical: Option<String>,
512    pub wrap_text: Option<bool>,
513    pub text_rotation: Option<u32>,
514}
515
516// Patch variants for write tools (Phase 2+). Double-option fields distinguish:
517// - missing field => no change (merge mode)
518// - null => clear to default
519// - value => set/merge that value
520#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
521pub struct StylePatch {
522    #[serde(default)]
523    pub font: Option<Option<FontPatch>>,
524    #[serde(default)]
525    pub fill: Option<Option<FillPatch>>,
526    #[serde(default)]
527    pub borders: Option<Option<BordersPatch>>,
528    #[serde(default)]
529    pub alignment: Option<Option<AlignmentPatch>>,
530    #[serde(default)]
531    pub number_format: Option<Option<String>>,
532}
533
534#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
535pub struct FontPatch {
536    #[serde(default)]
537    pub name: Option<Option<String>>,
538    #[serde(default)]
539    pub size: Option<Option<f64>>,
540    #[serde(default)]
541    pub bold: Option<Option<bool>>,
542    #[serde(default)]
543    pub italic: Option<Option<bool>>,
544    #[serde(default)]
545    pub underline: Option<Option<String>>,
546    #[serde(default)]
547    pub strikethrough: Option<Option<bool>>,
548    #[serde(default)]
549    pub color: Option<Option<String>>,
550}
551
552#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
553#[serde(tag = "kind", rename_all = "snake_case")]
554pub enum FillPatch {
555    Pattern(PatternFillPatch),
556    Gradient(GradientFillPatch),
557}
558
559#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
560pub struct PatternFillPatch {
561    #[serde(default)]
562    pub pattern_type: Option<Option<String>>,
563    #[serde(default)]
564    pub foreground_color: Option<Option<String>>,
565    #[serde(default)]
566    pub background_color: Option<Option<String>>,
567}
568
569#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
570pub struct GradientFillPatch {
571    #[serde(default)]
572    pub degree: Option<Option<f64>>,
573    #[serde(default)]
574    pub stops: Option<Vec<GradientStopPatch>>,
575}
576
577#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
578pub struct GradientStopPatch {
579    pub position: f64,
580    pub color: String,
581}
582
583#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
584pub struct BordersPatch {
585    #[serde(default)]
586    pub left: Option<Option<BorderSidePatch>>,
587    #[serde(default)]
588    pub right: Option<Option<BorderSidePatch>>,
589    #[serde(default)]
590    pub top: Option<Option<BorderSidePatch>>,
591    #[serde(default)]
592    pub bottom: Option<Option<BorderSidePatch>>,
593    #[serde(default)]
594    pub diagonal: Option<Option<BorderSidePatch>>,
595    #[serde(default)]
596    pub vertical: Option<Option<BorderSidePatch>>,
597    #[serde(default)]
598    pub horizontal: Option<Option<BorderSidePatch>>,
599    #[serde(default)]
600    pub diagonal_up: Option<Option<bool>>,
601    #[serde(default)]
602    pub diagonal_down: Option<Option<bool>>,
603}
604
605#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
606pub struct BorderSidePatch {
607    #[serde(default)]
608    pub style: Option<Option<String>>,
609    #[serde(default)]
610    pub color: Option<Option<String>>,
611}
612
613#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
614pub struct AlignmentPatch {
615    #[serde(default)]
616    pub horizontal: Option<Option<String>>,
617    #[serde(default)]
618    pub vertical: Option<Option<String>>,
619    #[serde(default)]
620    pub wrap_text: Option<Option<bool>>,
621    #[serde(default)]
622    pub text_rotation: Option<Option<u32>>,
623}
624
625#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
626pub struct SheetStylesResponse {
627    pub workbook_id: WorkbookId,
628    pub workbook_short_id: String,
629    pub sheet_name: String,
630    pub styles: Vec<StyleSummary>,
631    pub conditional_rules: Vec<String>,
632    pub total_styles: u32,
633    pub styles_truncated: bool,
634}
635
636#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
637pub struct StyleSummary {
638    pub style_id: String,
639    pub occurrences: u32,
640    pub tags: Vec<String>,
641    pub example_cells: Vec<String>,
642    pub descriptor: Option<StyleDescriptor>,
643    pub cell_ranges: Vec<String>,
644    pub ranges_truncated: bool,
645}
646
647#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
648pub struct WorkbookStyleSummaryResponse {
649    pub workbook_id: WorkbookId,
650    pub workbook_short_id: String,
651    pub theme: Option<ThemeSummary>,
652    pub inferred_default_style_id: Option<String>,
653    pub inferred_default_font: Option<FontDescriptor>,
654    pub styles: Vec<WorkbookStyleUsage>,
655    pub total_styles: u32,
656    pub styles_truncated: bool,
657    pub conditional_formats: Vec<ConditionalFormatSummary>,
658    pub conditional_formats_truncated: bool,
659    pub scan_truncated: bool,
660    pub notes: Vec<String>,
661}
662
663#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
664pub struct WorkbookStyleUsage {
665    pub style_id: String,
666    pub occurrences: u32,
667    pub tags: Vec<String>,
668    pub example_cells: Vec<String>,
669    pub descriptor: Option<StyleDescriptor>,
670}
671
672#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
673pub struct ThemeSummary {
674    pub name: Option<String>,
675    pub colors: BTreeMap<String, String>,
676    pub font_scheme: ThemeFontSchemeSummary,
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
680pub struct ThemeFontSchemeSummary {
681    pub major_latin: Option<String>,
682    pub major_east_asian: Option<String>,
683    pub major_complex_script: Option<String>,
684    pub minor_latin: Option<String>,
685    pub minor_east_asian: Option<String>,
686    pub minor_complex_script: Option<String>,
687}
688
689#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
690pub struct ConditionalFormatSummary {
691    pub sheet_name: String,
692    pub range: String,
693    pub rule_types: Vec<String>,
694    pub rule_count: u32,
695}
696
697#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
698pub struct ManifestStubResponse {
699    pub workbook_id: WorkbookId,
700    pub workbook_short_id: String,
701    pub slug: String,
702    pub sheets: Vec<ManifestSheetStub>,
703}
704
705#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
706pub struct ManifestSheetStub {
707    pub sheet_name: String,
708    pub classification: SheetClassification,
709    pub candidate_expectations: Vec<String>,
710    pub notes: Vec<String>,
711}
712
713#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
714#[serde(rename_all = "snake_case")]
715pub enum FindMode {
716    #[default]
717    Value,
718    Label,
719}
720
721#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
722#[serde(rename_all = "snake_case")]
723pub enum LabelDirection {
724    Right,
725    Below,
726    Any,
727}
728
729#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
730pub struct FindValueMatch {
731    pub address: String,
732    pub sheet_name: String,
733    pub value: Option<CellValue>,
734    pub row_context: Option<RowContext>,
735    pub neighbors: Option<NeighborValues>,
736    pub label_hit: Option<LabelHit>,
737}
738
739#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
740pub struct RowContext {
741    pub headers: Vec<String>,
742    pub values: Vec<Option<CellValue>>,
743}
744
745#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
746pub struct NeighborValues {
747    pub left: Option<CellValue>,
748    pub right: Option<CellValue>,
749    pub up: Option<CellValue>,
750    pub down: Option<CellValue>,
751}
752
753#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
754pub struct LabelHit {
755    pub label_address: String,
756    pub label: String,
757}
758
759#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
760pub struct FindValueResponse {
761    pub workbook_id: WorkbookId,
762    pub workbook_short_id: String,
763    pub matches: Vec<FindValueMatch>,
764    pub truncated: bool,
765}
766
767pub type TableRow = BTreeMap<String, Option<CellValue>>;
768
769#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
770pub struct ReadTableResponse {
771    pub workbook_id: WorkbookId,
772    pub workbook_short_id: String,
773    pub sheet_name: String,
774    pub table_name: Option<String>,
775    pub headers: Vec<String>,
776    pub rows: Vec<TableRow>,
777    pub total_rows: u32,
778    pub has_more: bool,
779}
780
781#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
782pub struct ColumnTypeSummary {
783    pub name: String,
784    pub inferred_type: String,
785    pub nulls: u32,
786    pub distinct: u32,
787    pub top_values: Vec<String>,
788    pub min: Option<f64>,
789    pub max: Option<f64>,
790    pub mean: Option<f64>,
791}
792
793#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
794pub struct TableProfileResponse {
795    pub workbook_id: WorkbookId,
796    pub workbook_short_id: String,
797    pub sheet_name: String,
798    pub table_name: Option<String>,
799    pub headers: Vec<String>,
800    pub column_types: Vec<ColumnTypeSummary>,
801    pub row_count: u32,
802    pub samples: Vec<TableRow>,
803    pub notes: Vec<String>,
804}
805
806#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
807pub struct RangeValuesResponse {
808    pub workbook_id: WorkbookId,
809    pub workbook_short_id: String,
810    pub sheet_name: String,
811    pub values: Vec<RangeValuesEntry>,
812}
813
814#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
815pub struct RangeValuesEntry {
816    pub range: String,
817    pub rows: Vec<Vec<Option<CellValue>>>,
818}
819
820#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
821pub struct CloseWorkbookResponse {
822    pub workbook_id: WorkbookId,
823    pub message: String,
824}
825
826#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
827pub struct VbaProjectSummaryResponse {
828    pub workbook_id: WorkbookId,
829    pub workbook_short_id: String,
830    pub has_vba: bool,
831    pub code_page: Option<u16>,
832    pub sys_kind: Option<String>,
833    pub modules: Vec<VbaModuleDescriptor>,
834    pub modules_truncated: bool,
835    pub references: Vec<VbaReferenceDescriptor>,
836    pub references_truncated: bool,
837    pub notes: Vec<String>,
838}
839
840#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
841pub struct VbaModuleDescriptor {
842    pub name: String,
843    pub stream_name: String,
844    pub doc_string: String,
845    pub text_offset: u64,
846    pub help_context: u32,
847    pub module_type: String,
848    pub read_only: bool,
849    pub private: bool,
850}
851
852#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
853pub struct VbaReferenceDescriptor {
854    pub kind: String,
855    pub debug: String,
856}
857
858#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
859pub struct VbaModuleSourceResponse {
860    pub workbook_id: WorkbookId,
861    pub workbook_short_id: String,
862    pub module_name: String,
863    pub offset_lines: u32,
864    pub limit_lines: u32,
865    pub total_lines: u32,
866    pub truncated: bool,
867    pub source: String,
868}