Files
device_agent/manifest.go
T
2026-05-30 17:28:38 +02:00

60 lines
2.0 KiB
Go

package main
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
type Capability struct {
Name string `yaml:"name"`
BinariesAllowed []string `yaml:"binaries_allowed,omitempty"`
PathsAllowed []string `yaml:"paths_allowed,omitempty"`
RequiresApproval bool `yaml:"requires_approval"`
// shell.eval specific fields
Blocklist []string `yaml:"blocklist,omitempty"` // regex patterns hardcoded + extendible
AutoApprove []string `yaml:"auto_approve,omitempty"` // regex patterns pre-approved
ShellMode string `yaml:"shell_mode,omitempty"` // "bash"|"powershell"|"auto" (default auto)
MaxOutputBytes int `yaml:"max_output_bytes,omitempty"` // default 1MB
TimeoutSeconds int `yaml:"timeout_seconds,omitempty"` // default 60
// browser.* specific fields (CDP)
ChromeCDPHost string `yaml:"chrome_cdp_host,omitempty"` // default 127.0.0.1
ChromeCDPPort int `yaml:"chrome_cdp_port,omitempty"` // default 9223
ScreenshotDir string `yaml:"screenshot_dir,omitempty"` // dest dir for screenshots (browser.screenshot)
}
type Manifest struct {
DeviceID string `yaml:"device_id"`
Operator string `yaml:"operator"`
Capabilities []Capability `yaml:"capabilities"`
}
func LoadManifest(path string) (*Manifest, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read manifest %s: %w", path, err)
}
var mf Manifest
if err := yaml.Unmarshal(data, &mf); err != nil {
return nil, fmt.Errorf("parse manifest yaml: %w", err)
}
if mf.DeviceID == "" {
return nil, fmt.Errorf("manifest missing device_id")
}
if len(mf.Capabilities) == 0 {
return nil, fmt.Errorf("manifest has no capabilities")
}
return &mf, nil
}
// CapabilityByName devuelve el bloque del manifest para name, o nil si no esta.
func (m *Manifest) CapabilityByName(name string) *Capability {
for i := range m.Capabilities {
if m.Capabilities[i].Name == name {
return &m.Capabilities[i]
}
}
return nil
}