File size: 1,562 Bytes
857a91b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package api

import (
	"io/fs"
	"net/http"
	"os"
	"path/filepath"
	"syscall"
)

// dirSize sums the size of all regular files under dir (0 when missing).
func dirSize(dir string) int64 {
	var total int64
	_ = filepath.WalkDir(dir, func(_ string, d fs.DirEntry, err error) error {
		if err != nil || d.IsDir() {
			return nil
		}
		if info, err := d.Info(); err == nil {
			total += info.Size()
		}
		return nil
	})
	return total
}

func fileSize(path string) int64 {
	if info, err := os.Stat(path); err == nil {
		return info.Size()
	}
	return 0
}

// handleStorage reports disk usage for the runtime's data directory: per-area
// sizes, the database file, job count, and free space on the filesystem.
func (s *Server) handleStorage(w http.ResponseWriter, _ *http.Request) {
	l := s.manager.Layout()
	areas := map[string]int64{
		"models":   dirSize(l.HuggingFace()),
		"mcp":      dirSize(l.MCP()),
		"agents":   dirSize(l.Agents()),
		"jobs":     dirSize(l.Jobs()),
		"logs":     dirSize(l.Logs()),
		"database": fileSize(s.cfg.DBPath),
	}
	var total int64
	for _, v := range areas {
		total += v
	}

	jobsCount := 0
	if entries, err := os.ReadDir(l.Jobs()); err == nil {
		jobsCount = len(entries)
	}

	var freeBytes uint64
	var fsStat syscall.Statfs_t
	if err := syscall.Statfs(s.cfg.DataDir, &fsStat); err == nil {
		freeBytes = fsStat.Bavail * uint64(fsStat.Bsize)
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"data_dir":    s.cfg.DataDir,
		"areas":       areas,
		"total_bytes": total,
		"free_bytes":  freeBytes,
		"jobs_count":  jobsCount,
	})
}