package main import ( "context" "fmt" "strings" stdio "git.novox.be/novox/mesh-sdk/go" ) // Tools are the module's tools over MCP (novox/hq ADR 0211): the machine's power now, the code // modules contributed for each moment, the recent power history, running one moment on demand, and // the module's own check. func Tools(m *Machine, w *Watcher) []stdio.Tool { return []stdio.Tool{ { Name: "power_state", Description: "This machine's power now: since when it runs, mains or battery and the charge, the lid, " + "logind's power-key and lid settings in force, and what the watcher last saw: its delay lock, " + "the last sleep and wake, and events still waiting for the bus.", Run: func(map[string]any) (any, error) { return m.State(w), nil }, }, { Name: "power_hooks", Description: "The code every module contributed for each power moment (after boot, on mains, on battery, " + "before sleep, after waking, before shutdown), as placed on this machine, each piece with its module.", Run: func(map[string]any) (any, error) { return m.Hooks(), nil }, }, { Name: "power_history", Description: "The machine's recent power events from the journal: each boot, every sleep and wake, and " + "every moment's run with each module's outcome.", Input: map[string]any{ "boots": map[string]any{"type": "integer", "description": "how many boots back (default 3, at most 20)"}, }, Run: func(args map[string]any) (any, error) { n := 3 if v, ok := args["boots"].(float64); ok { n = int(v) } if n < 1 || n > 20 { return nil, fmt.Errorf("boots is 1 to 20") } return m.History(context.Background(), n) }, }, { Name: "power_run", Description: "Run one moment's contributed code now, as the machine would, to test it: each module's " + "piece on its own, bounded. `supply` runs on-mains or on-battery for the source the machine is on. " + "Answers the runner's lines. Needs sudo -n.", Input: map[string]any{ "type": "object", "properties": map[string]any{ "moment": map[string]any{"type": "string", "enum": append(append([]string(nil), Moments...), "supply"), "description": "the moment to run"}, }, "required": []string{"moment"}, }, Run: func(args map[string]any) (any, error) { moment, _ := args["moment"].(string) known := moment == "supply" for _, mo := range Moments { known = known || mo == moment } if !known { return nil, fmt.Errorf("no moment %q; the moments are %s and supply", moment, strings.Join(Moments, ", ")) } out, err := m.privileged(context.Background(), RunnerPath, moment, "--force") return map[string]any{"moment": moment, "said": strings.Split(strings.TrimSpace(out), "\n")}, err }, }, { Name: "power_check", Description: "Whether this machine's power handling is as the mesh declares it: the module's units enabled, " + "the runner and every moment's file in place, logind's power file the mesh's and the only one, no " + "hand-placed sleep hooks, the watcher's delay lock held and no events stuck before the bus.", Run: func(map[string]any) (any, error) { return m.Check(context.Background(), w), nil }, }, } }