package console import ( "log" "strings" "github.com/novox/mesh-tools/node-tools/internal/approval" ) // verbApprovals is the mesh MCP server's tool that reads and steers what the gate asked on this machine (design 46 // 7-approval-mark §18). const verbApprovals = "mesh_approvals" // Approvals is the gate of this machine's tool runner, as mesh_approvals and mesh_describe read it. type Approvals interface { List() ([]approval.Listed, error) Read(id string) (approval.Whole, error) Applied() []approval.Marks Describe(module, seat, name string) (bool, string) Again(id string) error Cancel(id string) error // Fill is the state approvals' bytes against its cap, every machine's keys together. Fill() (bytes uint64, max int64, err error) } func approvalsTool() map[string]any { str := func(desc string) map[string]any { return map[string]any{"type": "string", "description": desc} } return map[string]any{"name": verbApprovals, "inputSchema": map[string]any{"type": "object", "properties": map[string]any{ "ask": str("an ask's id: its whole arguments and the act's digest"), "record": str("an ask's id: ask mesh-hand-acts.warranted again for its run, recorded in the hand-act log first"), "cancel": str("an ask's id: take that open ask back, recorded in the hand-act log first"), "why": str("why, for record and cancel, kept in the hand-act log"), }}, "description": "The calls that needed the operator's approval on this machine: with no argument, those asked in " + "the last day, newest first, with their state and fingerprint, the marks the tool runner applies (each module's " + "marked tools and verbs with their source and the catalog revision read) and its state's fill; `ask` reads one " + "whole, `record` asks its hand-act again, `cancel` takes an open ask back."} } // approvalsAnswer is mesh_approvals. func (s *Surface) approvalsAnswer(args map[string]any) map[string]any { if s.Approvals == nil { return failure("this tool runner has no approval gate") } str := func(k string) string { v, _ := args[k].(string); return strings.TrimSpace(v) } why := str("why") if why == "" { why = "asked by hand with no reason given" } act := func(id, what, cause string, do func(string) error) map[string]any { // A hand act, recorded through the seat mesh-hand-acts before it is done (§18); one that cannot be recorded is refused. log.Printf("[mesh-tools] hand act: %s %s ask %s: %s", s.who, what, id, why) if err := s.recordAct(map[string]any{"what": what + " ask " + id, "why": why, "cause": cause, "verb": verbApprovals}); err != nil { return failure("the hand act was not recorded through mesh-hand-acts, so nothing was done: " + err.Error()) } if err := do(id); err != nil { return failure(err.Error()) } return answerText(map[string]any{"done": what + " ask " + id, "recorded": "mesh-hand-acts.hand-act"}) } switch { case str("record") != "": return act(str("record"), "asked the hand-act of", "approval-record", s.Approvals.Again) case str("cancel") != "": return act(str("cancel"), "cancelled", "approval-cancel", s.Approvals.Cancel) case str("ask") != "": w, err := s.Approvals.Read(str("ask")) if err != nil { return failure(err.Error()) } return answerText(w) } asks, err := s.Approvals.List() out := map[string]any{"asks": asks, "marks": s.Approvals.Applied()} if err != nil { out["asks"], out["asks_why"] = []approval.Listed{}, "the state approvals cannot be read: "+err.Error() } if b, max, err := s.Approvals.Fill(); err != nil { out["fill_why"] = err.Error() } else { out["fill"] = map[string]any{"bytes": b, "max_bytes": max, "of": "every machine's keys together"} } return answerText(out) } // marked is what mesh_describe and a call that reached no one say of a marked tool or verb (§6, §18). func (s *Surface) marked(module, seat, name string) (bool, string) { if s.Approvals == nil { return false, "" } return s.Approvals.Describe(module, seat, name) } // markedTool is marked for a resolved address. func (s *Surface) markedTool(t target) (bool, string) { if t.Seat { return s.marked("", t.Tool.Module, t.Tool.Name) } return s.marked(t.Tool.Module, "", t.Tool.Name) }