| | |
| | | |
| | | // EngineService provides engine status and model management to the frontend. |
| | | type EngineService struct { |
| | | cfg *config.Config |
| | | app *application.App |
| | | initCallback func() |
| | | mu sync.RWMutex |
| | | status string |
| | | hardwareInfo string |
| | | lastError string |
| | | downloadMu sync.Mutex |
| | | downloadID string |
| | | downloadCancel context.CancelFunc |
| | | cfg *config.Config |
| | | app *application.App |
| | | initCallback func() |
| | | mu sync.RWMutex |
| | | status string |
| | | hardwareInfo string |
| | | lastError string |
| | | downloadMu sync.Mutex |
| | | downloadID string |
| | | downloadCancel context.CancelFunc |
| | | downloadCancelling bool |
| | | downloadProgress float64 |
| | | downloadDownloaded int64 |
| | | downloadTotal int64 |
| | | } |
| | | |
| | | func NewEngineService(cfg *config.Config) *EngineService { |
| | |
| | | defer finish() |
| | | |
| | | err = model.DownloadProfileWithContext(ctx, profile, profile.DownloadURLs, paths.ModelsRoot(), func(percent float64, downloaded, total int64) { |
| | | s.updateModelDownloadProgress(profile.ID, percent, downloaded, total) |
| | | if s.app != nil { |
| | | s.app.Event.Emit("model:download-progress", map[string]interface{}{ |
| | | "percent": percent, |
| | |
| | | s.downloadMu.Unlock() |
| | | return false |
| | | } |
| | | s.downloadCancelling = true |
| | | s.downloadCancel() |
| | | s.downloadMu.Unlock() |
| | | |
| | |
| | | }) |
| | | } |
| | | return true |
| | | } |
| | | |
| | | func (s *EngineService) GetModelDownloadStatus() map[string]interface{} { |
| | | s.downloadMu.Lock() |
| | | defer s.downloadMu.Unlock() |
| | | return s.modelDownloadStatusLocked() |
| | | } |
| | | |
| | | func (s *EngineService) modelStatusMap(profile model.ModelProfile, current modelselection.CurrentModel) map[string]interface{} { |
| | |
| | | defer finish() |
| | | |
| | | err = model.DownloadProfileWithContext(ctx, profile, []string{primaryURL, fallbackURL}, paths.ModelsRoot(), func(percent float64, downloaded, total int64) { |
| | | s.updateModelDownloadProgress(profile.ID, percent, downloaded, total) |
| | | if s.app != nil { |
| | | s.app.Event.Emit("model:download-progress", map[string]interface{}{ |
| | | "percent": percent, |
| | |
| | | defer finish() |
| | | |
| | | err = model.DownloadProfileWithContext(ctx, current.Profile, current.Profile.DownloadURLs, paths.ModelsRoot(), func(percent float64, downloaded, total int64) { |
| | | s.updateModelDownloadProgress(current.ModelID, percent, downloaded, total) |
| | | if s.app != nil { |
| | | s.app.Event.Emit("model:download-progress", map[string]interface{}{ |
| | | "percent": percent, |
| | |
| | | ctx, cancel := context.WithCancel(context.Background()) |
| | | s.downloadID = modelID |
| | | s.downloadCancel = cancel |
| | | s.downloadCancelling = false |
| | | s.downloadProgress = 0 |
| | | s.downloadDownloaded = 0 |
| | | s.downloadTotal = 0 |
| | | finish := func() { |
| | | emitFinished := false |
| | | s.downloadMu.Lock() |
| | | if s.downloadID == modelID { |
| | | s.downloadID = "" |
| | | s.downloadCancel = nil |
| | | s.downloadCancelling = false |
| | | s.downloadProgress = 0 |
| | | s.downloadDownloaded = 0 |
| | | s.downloadTotal = 0 |
| | | emitFinished = true |
| | | } |
| | | s.downloadMu.Unlock() |
| | | if emitFinished && s.app != nil { |
| | | s.app.Event.Emit("model:download-finished", map[string]interface{}{ |
| | | "modelID": modelID, |
| | | }) |
| | | } |
| | | } |
| | | return ctx, finish, nil |
| | | } |
| | | |
| | | func (s *EngineService) updateModelDownloadProgress(modelID string, percent float64, downloaded, total int64) { |
| | | s.downloadMu.Lock() |
| | | if s.downloadID == modelID && s.downloadCancel != nil { |
| | | s.downloadProgress = percent |
| | | s.downloadDownloaded = downloaded |
| | | s.downloadTotal = total |
| | | } |
| | | s.downloadMu.Unlock() |
| | | } |
| | | |
| | | func (s *EngineService) modelDownloadStatusLocked() map[string]interface{} { |
| | | return map[string]interface{}{ |
| | | "active": s.downloadCancel != nil, |
| | | "modelID": s.downloadID, |
| | | "cancelling": s.downloadCancelling, |
| | | "percent": s.downloadProgress, |
| | | "downloaded": s.downloadDownloaded, |
| | | "total": s.downloadTotal, |
| | | } |
| | | } |
| | | |
| | | func (s *EngineService) allowedModelProfile(modelID string) (model.ModelProfile, error) { |
| | | profile, err := model.GetModelProfile(modelID) |
| | | if err != nil { |