Files
Agent-System-Backend/internal/execenv/gc.go
T
weichenandCursor b85a1e1ca3 Add immutable layered Python environments for the sandbox.
Why: The sandbox hides the host home directory and has no network, so pip install --user cannot supply python-docx, and the service PATH resolved python3 to a linuxbrew path that does not exist inside the sandbox.
Evidence: SELF go test of execenv, tools, store, app, server, runmgr, config, and cmd/agent-system on this worktree. CI has not run.
Impact: Sessions inherit a read-only base layer. Extra packages are requested through python_env, auto-approved only from the allowlist, and mounted per conversation. Schema 35 adds the request and binding tables.
Refs: .task/feature-layered-python-env.md
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-15 13:52:48 +00:00

62 lines
1.3 KiB
Go

package execenv
import (
"os"
"path/filepath"
"time"
)
// GC 删除未被 current、绑定或锁引用、且早于 ttl 的层目录。ttl<=0 时用 7 天。
func (b *Broker) GC(ttl time.Duration) ([]string, error) {
if ttl <= 0 {
ttl = 7 * 24 * time.Hour
}
keep := map[string]bool{}
if id, err := b.Root.CurrentBase(); err != nil {
return nil, err
} else if id != "" {
keep[id] = true
}
if b.Store != nil {
binds, err := b.Store.ListExecEnvBindings()
if err != nil {
return nil, err
}
for _, bind := range binds {
if bind.BaseID != "" {
keep[bind.BaseID] = true
}
if bind.Isolated != "" {
keep[bind.Isolated] = true
}
for _, id := range bind.Extensions {
keep[id] = true
}
}
}
ents, err := os.ReadDir(b.Root.LayersDir())
if err != nil {
return nil, err
}
cut := time.Now().Add(-ttl)
var removed []string
for _, ent := range ents {
if !ent.IsDir() || keep[ent.Name()] {
continue
}
info, err := ent.Info()
if err != nil {
return removed, err
}
if info.ModTime().After(cut) {
continue
}
if err := os.RemoveAll(filepath.Join(b.Root.LayersDir(), ent.Name())); err != nil {
return removed, err
}
_ = os.Remove(filepath.Join(b.Root.LocksDir(), ent.Name()+".json"))
removed = append(removed, ent.Name())
}
return removed, nil
}