package main import "encoding/json" // --- LLM and Prompt Generation Structs --- // TriageResponse is the structure for the first-pass classification of user input. type TriageResponse struct { Category string `json:"category"` Language string `json:"language"` HasData bool `json:"has_data"` Error string `json:"error,omitempty"` } // ExtractionResult is the detailed structure extracted from user input. type ExtractionResult struct { Question string `json:"question"` Category string `json:"category"` Type string `json:"type"` InputType string `json:"input_type"` InputConfig InputConfig `json:"input_config"` Schedule []ScheduleSlot `json:"schedule"` Entries []*EntryData `json:"entries,omitempty"` Error string `json:"error,omitempty"` } // InputConfig defines the structure of a form. It can contain either // a simple list of fields or a list of groups with fields. type InputConfig struct { Fields []FormField `json:"fields,omitempty"` Groups []FormGroup `json:"groups,omitempty"` } // FormGroup represents a group of fields in a form. type FormGroup struct { Title string `json:"title"` Fields []FormField `json:"fields"` } // FormField represents a single field in a form. type FormField struct { Key string `json:"key"` Type string `json:"type"` Label string `json:"label"` Unit string `json:"unit,omitempty"` Options []string `json:"options,omitempty"` } // ScheduleSlot defines when a tracker should be shown. // Supports both old format (Time string) and new format (Times []string). type ScheduleSlot struct { Days []string `json:"days"` Time string `json:"time,omitempty"` // Old format: single time Times []string `json:"times,omitempty"` // New format: multiple times } // EntryData represents a single piece of data extracted from user input. type EntryData struct { Value string `json:"value"` Data interface{} `json:"data"` Timestamp int64 `json:"timestamp,omitempty"` // Legacy: Unix timestamp Date string `json:"date,omitempty"` // New: ISO date YYYY-MM-DD } // ValidCategories is the list of recognized categories. var ValidCategories = map[string]bool{ "vital": true, "exercise": true, "medication": true, "supplement": true, "symptom": true, "note": true, "surgery": true, "hospitalization": true, "consultation": true, "diagnosis": true, "device": true, "therapy": true, "assessment": true, "birth": true, "imaging_finding": true, "eeg_finding": true, "provider": true, "question": true, "history": true, "family_history": true, "nutrition": true, "fertility": true, "out_of_domain": true, } // UnmarshalJSON handles both old array format and new single-object format for schedule. func (e *ExtractionResult) UnmarshalJSON(data []byte) error { // Define an alias to avoid recursion type Alias ExtractionResult aux := &struct { Schedule interface{} `json:"schedule"` *Alias }{ Alias: (*Alias)(e), } if err := json.Unmarshal(data, &aux); err != nil { return err } // Handle schedule field - can be array or single object if aux.Schedule != nil { switch v := aux.Schedule.(type) { case []interface{}: // Old format: array of schedule slots schedJSON, _ := json.Marshal(v) json.Unmarshal(schedJSON, &e.Schedule) case map[string]interface{}: // New format: single schedule object schedJSON, _ := json.Marshal(v) var slot ScheduleSlot if json.Unmarshal(schedJSON, &slot) == nil { e.Schedule = []ScheduleSlot{slot} } } } return nil }