- Add safety checks to Zig build - Add TUI with job management and narrative views - Add WebSocket support and export services - Add smart configuration defaults - Update API routes with security headers - Update SECURITY.md with comprehensive policy - Add Makefile security scanning targets
173 lines
5.7 KiB
Go
173 lines
5.7 KiB
Go
// Package model provides TUI data structures and state management
|
|
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/charmbracelet/bubbles/list"
|
|
"github.com/charmbracelet/bubbles/spinner"
|
|
"github.com/charmbracelet/bubbles/textinput"
|
|
"github.com/charmbracelet/bubbles/viewport"
|
|
"github.com/jfraeys/fetch_ml/internal/domain"
|
|
)
|
|
|
|
// Re-export domain types for TUI use
|
|
// Task represents a task in the TUI
|
|
type Task = domain.Task
|
|
|
|
// TrackingConfig specifies experiment tracking tools
|
|
type TrackingConfig = domain.TrackingConfig
|
|
|
|
// MLflowTrackingConfig controls MLflow integration
|
|
type MLflowTrackingConfig = domain.MLflowTrackingConfig
|
|
|
|
// TensorBoardTrackingConfig controls TensorBoard integration
|
|
type TensorBoardTrackingConfig = domain.TensorBoardTrackingConfig
|
|
|
|
// WandbTrackingConfig controls Weights & Biases integration
|
|
type WandbTrackingConfig = domain.WandbTrackingConfig
|
|
|
|
// ViewMode represents the current view mode in the TUI
|
|
type ViewMode int
|
|
|
|
// ViewMode constants represent different TUI views
|
|
const (
|
|
ViewModeJobs ViewMode = iota // Jobs view mode
|
|
ViewModeGPU // GPU status view mode
|
|
ViewModeQueue // Queue status view mode
|
|
ViewModeContainer // Container status view mode
|
|
ViewModeSettings // Settings view mode
|
|
ViewModeDatasets // Datasets view mode
|
|
ViewModeExperiments // Experiments view mode
|
|
ViewModeNarrative // Narrative/Outcome view mode
|
|
ViewModeTeam // Team collaboration view mode
|
|
ViewModeExperimentHistory // Experiment history view mode
|
|
ViewModeConfig // Config view mode
|
|
ViewModeLogs // Logs streaming view mode
|
|
)
|
|
|
|
// DatasetInfo represents dataset information in the TUI
|
|
type DatasetInfo struct {
|
|
Name string `json:"name"`
|
|
SizeBytes int64 `json:"size_bytes"`
|
|
Location string `json:"location"`
|
|
LastAccess time.Time `json:"last_access"`
|
|
}
|
|
|
|
// State holds the application state
|
|
type State struct {
|
|
Jobs []Job
|
|
QueuedTasks []*Task
|
|
Datasets []DatasetInfo
|
|
JobList list.Model
|
|
GpuView viewport.Model
|
|
ContainerView viewport.Model
|
|
QueueView viewport.Model
|
|
SettingsView viewport.Model
|
|
DatasetView viewport.Model
|
|
ExperimentsView viewport.Model
|
|
NarrativeView viewport.Model
|
|
TeamView viewport.Model
|
|
ExperimentHistoryView viewport.Model
|
|
ConfigView viewport.Model
|
|
LogsView viewport.Model
|
|
SelectedJob Job
|
|
Input textinput.Model
|
|
APIKeyInput textinput.Model
|
|
Status string
|
|
ErrorMsg string
|
|
InputMode bool
|
|
Width int
|
|
Height int
|
|
ShowHelp bool
|
|
Spinner spinner.Model
|
|
ActiveView ViewMode
|
|
LastRefresh time.Time
|
|
LastFrameTime time.Time
|
|
RefreshRate float64 // measured in ms
|
|
FrameCount int
|
|
LastGPUUpdate time.Time
|
|
IsLoading bool
|
|
JobStats map[JobStatus]int
|
|
APIKey string
|
|
SettingsIndex int
|
|
Keys KeyMap
|
|
}
|
|
|
|
// InitialState creates the initial application state
|
|
func InitialState(apiKey string) State {
|
|
items := []list.Item{}
|
|
delegate := NewJobListDelegate()
|
|
jobList := list.New(items, delegate, 0, 0)
|
|
jobList.Title = "ML Jobs & Queue"
|
|
jobList.SetShowStatusBar(true)
|
|
jobList.SetFilteringEnabled(true)
|
|
jobList.SetShowHelp(false)
|
|
jobList.Styles.Title = JobListTitleStyle()
|
|
|
|
input := textinput.New()
|
|
input.Placeholder = "Args: --epochs 100 --lr 0.001 --priority 5"
|
|
input.Width = 60
|
|
input.CharLimit = 200
|
|
|
|
apiKeyInput := textinput.New()
|
|
apiKeyInput.Placeholder = "Enter API key..."
|
|
apiKeyInput.Width = 40
|
|
apiKeyInput.CharLimit = 200
|
|
|
|
s := spinner.New()
|
|
s.Spinner = spinner.Dot
|
|
s.Style = SpinnerStyle()
|
|
|
|
return State{
|
|
JobList: jobList,
|
|
GpuView: viewport.New(0, 0),
|
|
ContainerView: viewport.New(0, 0),
|
|
QueueView: viewport.New(0, 0),
|
|
SettingsView: viewport.New(0, 0),
|
|
DatasetView: viewport.New(0, 0),
|
|
ExperimentsView: viewport.New(0, 0),
|
|
NarrativeView: viewport.New(0, 0),
|
|
TeamView: viewport.New(0, 0),
|
|
ExperimentHistoryView: viewport.New(0, 0),
|
|
ConfigView: viewport.New(0, 0),
|
|
LogsView: viewport.New(0, 0),
|
|
Input: input,
|
|
APIKeyInput: apiKeyInput,
|
|
Status: "Connected",
|
|
InputMode: false,
|
|
ShowHelp: false,
|
|
Spinner: s,
|
|
ActiveView: ViewModeJobs,
|
|
LastRefresh: time.Now(),
|
|
IsLoading: false,
|
|
JobStats: make(map[JobStatus]int),
|
|
APIKey: apiKey,
|
|
SettingsIndex: 0,
|
|
Keys: DefaultKeys(),
|
|
}
|
|
}
|
|
|
|
// LogMsg represents a log line from a job
|
|
type LogMsg struct {
|
|
JobName string `json:"job_name"`
|
|
Line string `json:"line"`
|
|
Time string `json:"time"`
|
|
}
|
|
|
|
// JobUpdateMsg represents a real-time job status update via WebSocket
|
|
type JobUpdateMsg struct {
|
|
JobName string `json:"job_name"`
|
|
Status string `json:"status"`
|
|
TaskID string `json:"task_id"`
|
|
Progress int `json:"progress"`
|
|
}
|
|
|
|
// GPUUpdateMsg represents a real-time GPU status update via WebSocket
|
|
type GPUUpdateMsg struct {
|
|
DeviceID int `json:"device_id"`
|
|
Utilization int `json:"utilization"`
|
|
MemoryUsed int64 `json:"memory_used"`
|
|
MemoryTotal int64 `json:"memory_total"`
|
|
Temperature int `json:"temperature"`
|
|
}
|