feat(0144c): launcher wiring + adapter al tool-use loop LLM

Schema DeviceMeshConfig en AgentConfig. Adapter ToolsForLLM convierte
ToolSpec → tools.Tool transparente al LLM existente. URL via env var
override. tools_allowed filter. agent-wsl-lucas blank import en launcher.

LLM ve los tools como cualquier otra herramienta. Effects runner ya
soporta ActionKindDeviceMesh como fallback. Build + tests verdes.
This commit is contained in:
2026-05-24 14:07:13 +02:00
parent 4c5bf95def
commit 61606d450d
6 changed files with 457 additions and 2 deletions
+81
View File
@@ -17,12 +17,93 @@ type AgentConfig struct {
Memory MemoryCfg `yaml:"memory"`
Skills SkillsCfg `yaml:"skills"`
// DeviceMesh holds the optional device-mesh block. When nil the agent has
// no device_mesh tools; when set and Enabled the runtime constructs a
// devicemesh.Client + ToolRegistry and registers the builtin tools (filtered
// by ToolsAllowed). See issue 0144 §6.1 + .claude/rules/cpp_apps.md.
DeviceMesh *DeviceMeshConfig `yaml:"device_mesh,omitempty"`
// ConfigDir is the directory containing the config file. Set by the loader
// at load time, not from YAML. Used to resolve relative paths like
// system_prompt_file correctly regardless of where the agent lives.
ConfigDir string `yaml:"-"`
}
// DeviceMeshConfig is the optional device-mesh block on the agent config.
// When DeviceMesh is non-nil and Enabled is true, the launcher builds a
// devicemesh.Client + ToolRegistry, registers builtin tools filtered by
// Mode (user|sudo), optionally narrows them via ToolsAllowed, and exposes
// each tool to the LLM tool-use loop via the standard tool registry.
type DeviceMeshConfig struct {
// Enabled gates the whole block. False keeps it inert even when present.
Enabled bool `yaml:"enabled"`
// Host identifies the target device for log/audit context. Matches
// device_id from the manifest (ex "home-wsl", "aurgi-pc").
Host string `yaml:"host"`
// DeviceID is an alias for Host. Templates use device_id; keep both for
// compatibility. When both are set Host wins.
DeviceID string `yaml:"device_id,omitempty"`
// Mode controls which subset of the builtin catalog gets registered.
// "user" → non-approval tools. "sudo" → approval-gated tools (shell.eval
// promoted to requires_approval). Empty defaults to "user".
Mode string `yaml:"mode"`
// DeviceAgentURL is the http://host:port URL of the remote device_agent.
// May be empty when URLEnv is set.
DeviceAgentURL string `yaml:"device_agent_url"`
// URLEnv allows the agent_url to be supplied at runtime via env var
// (ex "AGENT_HOME_WSL_DEVICE_MESH_URL"). When non-empty the runtime reads
// the env var; if both are set, the env var wins when non-empty. This
// keeps device URLs out of the YAML/git history.
URLEnv string `yaml:"device_agent_url_env,omitempty"`
// ManifestID is metadata for log/audit context. The device_agent enforces
// the actual manifest binding. Empty allowed.
ManifestID string `yaml:"manifest_id,omitempty"`
// ToolsAllowed is a whitelist applied AFTER RegisterBuiltins. Empty means
// "keep all tools the mode-filter accepted". Names that do not match any
// registered tool are logged and ignored.
ToolsAllowed []string `yaml:"tools_allowed,omitempty"`
// TimeoutSeconds overrides the per-call HTTP timeout. 0 → DefaultTimeout
// of the devicemesh client (30s).
TimeoutSeconds int `yaml:"timeout_seconds,omitempty"`
// ClientTimeoutS is an alias for TimeoutSeconds. Templates use
// client_timeout_s; we accept both. When both set, ClientTimeoutS wins
// when non-zero.
ClientTimeoutS int `yaml:"client_timeout_s,omitempty"`
}
// ResolvedHost returns Host if non-empty, otherwise DeviceID. Used by the
// runtime to log audit context without caring which key the YAML used.
func (d *DeviceMeshConfig) ResolvedHost() string {
if d == nil {
return ""
}
if d.Host != "" {
return d.Host
}
return d.DeviceID
}
// ResolvedTimeoutSeconds returns the first non-zero of TimeoutSeconds and
// ClientTimeoutS. 0 means "use devicemesh defaults".
func (d *DeviceMeshConfig) ResolvedTimeoutSeconds() int {
if d == nil {
return 0
}
if d.TimeoutSeconds > 0 {
return d.TimeoutSeconds
}
return d.ClientTimeoutS
}
// ── Identity ──────────────────────────────────────────────────────────────
type AgentMeta struct {