package model import ( "encoding/json" "fmt" "io" "os" "path/filepath" ) // ModelStore manages custom model files on disk. type ModelStore struct { baseDir string } func NewModelStore(baseDir string) *ModelStore { _ = os.MkdirAll(baseDir, 0755) return &ModelStore{baseDir: baseDir} } // SaveModel saves a .nef file for the given model ID. func (s *ModelStore) SaveModel(id string, file io.Reader) (string, error) { dir := filepath.Join(s.baseDir, id) if err := os.MkdirAll(dir, 0755); err != nil { return "", fmt.Errorf("failed to create model directory: %w", err) } nefPath := filepath.Join(dir, "model.nef") f, err := os.Create(nefPath) if err != nil { return "", fmt.Errorf("failed to create model file: %w", err) } defer f.Close() written, err := io.Copy(f, file) if err != nil { return "", fmt.Errorf("failed to write model file: %w", err) } fmt.Printf("[INFO] Saved model file: %s (%d bytes)\n", nefPath, written) return nefPath, nil } // SaveMetadata saves model metadata as JSON. func (s *ModelStore) SaveMetadata(id string, m Model) error { dir := filepath.Join(s.baseDir, id) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("failed to create model directory: %w", err) } metaPath := filepath.Join(dir, "metadata.json") data, err := json.MarshalIndent(m, "", " ") if err != nil { return fmt.Errorf("failed to marshal metadata: %w", err) } return os.WriteFile(metaPath, data, 0644) } // GetModelPath returns the .nef file path for a model. func (s *ModelStore) GetModelPath(id string) string { return filepath.Join(s.baseDir, id, "model.nef") } // DeleteModel removes a model's directory and all files. func (s *ModelStore) DeleteModel(id string) error { dir := filepath.Join(s.baseDir, id) return os.RemoveAll(dir) } // LoadCustomModels scans the store directory and returns all custom models. func (s *ModelStore) LoadCustomModels() ([]Model, error) { entries, err := os.ReadDir(s.baseDir) if err != nil { if os.IsNotExist(err) { return nil, nil } return nil, err } var models []Model for _, entry := range entries { if !entry.IsDir() { continue } metaPath := filepath.Join(s.baseDir, entry.Name(), "metadata.json") data, err := os.ReadFile(metaPath) if err != nil { continue } var m Model if err := json.Unmarshal(data, &m); err != nil { continue } m.IsCustom = true models = append(models, m) } return models, nil }