@@ -36,17 +36,19 @@ type Model struct {
3636 cpuHistory []float64
3737 memHistory []float64
3838 diskHistory []float64
39+ gpuHistory []float64
3940}
4041
4142func New (cfg config.Config ) Model {
4243 return Model {
4344 cfg : cfg ,
44- client : ollama .NewClient (cfg .BaseURL ),
45+ client : ollama .NewClientWithTimeout (cfg .BaseURL , cfg . RequestTimeout ),
4546 width : 120 ,
4647 height : 40 ,
4748 cpuHistory : make ([]float64 , 0 , 40 ),
4849 memHistory : make ([]float64 , 0 , 40 ),
4950 diskHistory : make ([]float64 , 0 , 40 ),
51+ gpuHistory : make ([]float64 , 0 , 40 ),
5052 }
5153}
5254
@@ -97,6 +99,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
9799 m .cpuHistory = pushHistory (m .cpuHistory , msg .sample .Host .CPUPercent , 48 )
98100 m .memHistory = pushHistory (m .memHistory , msg .sample .Host .MemoryUsedPercent , 48 )
99101 m .diskHistory = pushHistory (m .diskHistory , msg .sample .Host .DiskUsedPercent , 48 )
102+ m .gpuHistory = pushHistory (m .gpuHistory , msg .sample .Host .GPU .UtilizationPct , 48 )
100103 case tickMsg :
101104 return m , tea .Batch (m .refreshCmd (), tickCmd (m .cfg .Interval ))
102105 }
@@ -197,6 +200,7 @@ func (m Model) renderOverview() string {
197200 cpuBar := util .PercentBar (s .Host .CPUPercent , 18 , "█" , "░" )
198201 memBar := util .PercentBar (s .Host .MemoryUsedPercent , 18 , "█" , "░" )
199202 diskBar := util .PercentBar (s .Host .DiskUsedPercent , 18 , "█" , "░" )
203+ gpuBar := util .PercentBar (s .Host .GPU .UtilizationPct , 18 , "█" , "░" )
200204
201205 lines := []string {
202206 tui .Title .Render ("Overview" ),
@@ -208,9 +212,11 @@ func (m Model) renderOverview() string {
208212 fmt .Sprintf ("%s %5.1f%% %s" , tui .MetricLabel .Render ("CPU" ), s .Host .CPUPercent , colorizePercent (s .Host .CPUPercent , cpuBar )),
209213 fmt .Sprintf ("%s %5.1f%% %s" , tui .MetricLabel .Render ("MEM" ), s .Host .MemoryUsedPercent , colorizePercent (s .Host .MemoryUsedPercent , memBar )),
210214 fmt .Sprintf ("%s %5.1f%% %s" , tui .MetricLabel .Render ("DSK" ), s .Host .DiskUsedPercent , colorizePercent (s .Host .DiskUsedPercent , diskBar )),
215+ fmt .Sprintf ("%s %5.1f%% %s" , tui .MetricLabel .Render ("GPU" ), s .Host .GPU .UtilizationPct , colorizePercent (s .Host .GPU .UtilizationPct , gpuBar )),
211216 "" ,
212217 fmt .Sprintf ("%s %.1f / %.1f GB" , tui .MetricLabel .Render ("Memory" ), s .Host .MemoryUsedGB , s .Host .MemoryTotalGB ),
213218 fmt .Sprintf ("%s %.1f / %.1f GB" , tui .MetricLabel .Render ("Disk" ), s .Host .DiskUsedGB , s .Host .DiskTotalGB ),
219+ fmt .Sprintf ("%s %.1fW @ %.0fMHz" , tui .MetricLabel .Render ("GPU Pwr" ), s .Host .GPU .PowerW , s .Host .GPU .FrequencyMHz ),
214220 fmt .Sprintf ("%s %.2f / %.2f" , tui .MetricLabel .Render ("Load" ), s .Host .Load1 , s .Host .Load5 ),
215221 fmt .Sprintf ("%s %d installed / %d running" , tui .MetricLabel .Render ("Models" ), len (s .Installed ), len (s .Running )),
216222 }
@@ -229,12 +235,14 @@ func (m Model) renderTelemetry() string {
229235 cpuSpark := util .Sparkline (m .cpuHistory , 32 )
230236 memSpark := util .Sparkline (m .memHistory , 32 )
231237 diskSpark := util .Sparkline (m .diskHistory , 32 )
238+ gpuSpark := util .Sparkline (m .gpuHistory , 32 )
232239
233240 lines := []string {
234241 tui .Title .Render ("Trends" ),
235242 fmt .Sprintf ("%s %s" , tui .MetricLabel .Render ("CPU" ), tui .Accent .Render (cpuSpark )),
236243 fmt .Sprintf ("%s %s" , tui .MetricLabel .Render ("MEM" ), tui .Accent .Render (memSpark )),
237244 fmt .Sprintf ("%s %s" , tui .MetricLabel .Render ("DSK" ), tui .Accent .Render (diskSpark )),
245+ fmt .Sprintf ("%s %s" , tui .MetricLabel .Render ("GPU" ), tui .Accent .Render (gpuSpark )),
238246 "" ,
239247 tui .Title .Render ("Telemetry" ),
240248 fmt .Sprintf ("%s %s" , tui .MetricLabel .Render ("Token/s" ), renderTokenRate (s )),
@@ -254,9 +262,9 @@ func (m Model) renderTelemetry() string {
254262 }
255263
256264 if s .Time .IsZero () {
257- lines = append (lines , "" , tui .Dim .Render ("İlk örnek bekleniyor ..." ))
265+ lines = append (lines , "" , tui .Dim .Render ("Waiting for first sample ..." ))
258266 } else if s .LogStats .RequestCount == 0 {
259- lines = append (lines , "" , tui .Dim .Render ("Log erişim kaydı bekleniyor ." ))
267+ lines = append (lines , "" , tui .Dim .Render ("Waiting for access log entries ." ))
260268 }
261269
262270 return tui .Box .Width (rightW ).Render (strings .Join (lines , "\n " ))
@@ -273,15 +281,15 @@ func (m Model) renderInsights() string {
273281 insights := make ([]string , 0 , 6 )
274282
275283 if s .Host .MemoryUsedPercent > 85 {
276- insights = append (insights , "• RAM kullanımı yüksek. Büyük model yüklemelerinde yavaşlama olabilir ." )
284+ insights = append (insights , "• RAM usage is high. Large model loads may slow down ." )
277285 } else if s .Host .MemoryUsedPercent > 70 {
278- insights = append (insights , "• RAM kullanımı orta-yüksek . Keep-alive süreleri gözden geçirilebilir ." )
286+ insights = append (insights , "• RAM usage is moderately high . Keep-alive settings may need review ." )
279287 } else {
280- insights = append (insights , "• RAM tarafı şu an rahat görünüyor ." )
288+ insights = append (insights , "• RAM usage is currently in a comfortable range ." )
281289 }
282290
283291 if s .Host .DiskUsedPercent > 80 {
284- insights = append (insights , "• Disk doluluğu kritik eşiğe yaklaşıyor. Eski modeller temizlenebilir ." )
292+ insights = append (insights , "• Disk usage is approaching a critical threshold. Old models may need cleanup ." )
285293 }
286294
287295 if len (s .Installed ) > 0 {
@@ -291,25 +299,25 @@ func (m Model) renderInsights() string {
291299 idx = i
292300 }
293301 }
294- insights = append (insights , fmt .Sprintf ("• En büyük model: %s (%s)" , s .Installed [idx ].Name , util .BytesToHuman (s .Installed [idx ].Size )))
302+ insights = append (insights , fmt .Sprintf ("• Largest installed model: %s (%s)" , s .Installed [idx ].Name , util .BytesToHuman (s .Installed [idx ].Size )))
295303 }
296304
297305 if len (s .Running ) > 0 {
298306 rm := s .Running [0 ]
299- insights = append (insights , fmt .Sprintf ("• Aktif örnek : %s, VRAM/RAM yükü yaklaşık %s" , rm .Name , util .BytesToHuman (rm .SizeVRAM )))
307+ insights = append (insights , fmt .Sprintf ("• Active runtime : %s, estimated VRAM/RAM load %s" , rm .Name , util .BytesToHuman (rm .SizeVRAM )))
300308 } else {
301- insights = append (insights , "• Şu an bellekte aktif model görünmüyor ." )
309+ insights = append (insights , "• No active in-memory model is visible right now ." )
302310 }
303311
304312 if s .LogStats .RequestCount > 0 {
305- insights = append (insights , fmt .Sprintf ("• Son %d log kaydında ortalama latency %s." , s .LogStats .RequestCount , renderLatency (s .LogStats .AvgLatency )))
313+ insights = append (insights , fmt .Sprintf ("• Average latency across the last %d log entries is %s." , s .LogStats .RequestCount , renderLatency (s .LogStats .AvgLatency )))
306314 if len (s .LogStats .TopEndpoints ) > 0 {
307- insights = append (insights , fmt .Sprintf ("• En yoğun endpoint: %s (%d istek )." , s .LogStats .TopEndpoints [0 ].Endpoint , s .LogStats .TopEndpoints [0 ].Count ))
315+ insights = append (insights , fmt .Sprintf ("• Busiest endpoint: %s (%d requests )." , s .LogStats .TopEndpoints [0 ].Endpoint , s .LogStats .TopEndpoints [0 ].Count ))
308316 }
309317 }
310318
311319 if m .filter != "" {
312- insights = append (insights , fmt .Sprintf ("• Filtre etkin : %q" , m .filter ))
320+ insights = append (insights , fmt .Sprintf ("• Active filter : %q" , m .filter ))
313321 }
314322
315323 return strings .Join (insights , "\n " )
@@ -325,7 +333,7 @@ func (m Model) renderRunning() string {
325333 running = filterRunning (running , m .filter )
326334
327335 if len (running ) == 0 {
328- lines = append (lines , tui .Dim .Render ("Aktif model yok veya filtre eşleşmedi ." ))
336+ lines = append (lines , tui .Dim .Render ("No active model found or the filter did not match ." ))
329337 return tui .Box .Width (leftW ).Render (strings .Join (lines , "\n " ))
330338 }
331339
@@ -359,7 +367,7 @@ func (m Model) renderInstalled() string {
359367 models = filterInstalled (models , m .filter )
360368
361369 if len (models ) == 0 {
362- lines = append (lines , tui .Dim .Render ("Yüklü model bulunamadı veya filtre eşleşmedi ." ))
370+ lines = append (lines , tui .Dim .Render ("No installed model found or the filter did not match ." ))
363371 return tui .Box .Width (rightW ).Render (strings .Join (lines , "\n " ))
364372 }
365373
@@ -394,7 +402,7 @@ func (m Model) renderLogPanel() string {
394402 case m .last .LogError != "" :
395403 lines = append (lines , tui .Warn .Render (m .last .LogError ))
396404 case len (m .last .LogLines ) == 0 :
397- lines = append (lines , tui .Dim .Render ("Log bulunamadı. OLLAMON_LOG_PATH ile özel yol verebilirsin ." ))
405+ lines = append (lines , tui .Dim .Render ("Log file not found. Use OLLAMON_LOG_PATH to provide a custom path ." ))
398406 default :
399407 logLines := m .last .LogLines
400408 if len (logLines ) > 10 {
0 commit comments