catalogue's SeatReference, InRegistrySeat, Routed, Recorded, InArtifactStore and ArtifactSweepSeat leave mesh-sdk; each package gives the two registry seats' names from their contracts (or the build step's copies of them). Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
123 lines
4.3 KiB
Go
123 lines
4.3 KiB
Go
package main
|
|
|
|
// The seat mesh-artifact-sweep's verbs (novox/hq ADR 0571 clause 2; sweep.Seat), each a tool named
|
|
// `artifact-store.<verb>` as the runtime serves a seat's verb, answering as the controller's verb answered: {output,
|
|
// ok, answer}.
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
sweep "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshartifactsweep"
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
)
|
|
|
|
// verbAnswer is the controller's verbs' answer shape, which the builder and docker read (answerOf).
|
|
type verbAnswer struct {
|
|
Output string `json:"output"`
|
|
OK bool `json:"ok"`
|
|
Answer any `json:"answer"`
|
|
}
|
|
|
|
// SeatTools are the seat's verbs over h; s reads the store's listing for mirrors.
|
|
func SeatTools(h *Holder, s *Store) []stdio.Tool {
|
|
seat := sweep.Seat + "."
|
|
return []stdio.Tool{
|
|
{Name: seat + "artifacts", Description: "Every artifact the mesh made that the store holds: kept and why, eligible, " +
|
|
"or with collected those it no longer holds.",
|
|
Run: func(args map[string]any) (any, error) {
|
|
r, err := h.Artifacts(text(args, "repository"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if text(args, "collected") != "true" {
|
|
refs := r.References[:0:0]
|
|
for _, x := range r.References {
|
|
if x.State != "collected" {
|
|
refs = append(refs, x)
|
|
}
|
|
}
|
|
r.References = refs
|
|
}
|
|
return verbAnswer{Output: fmt.Sprintf("%d kept, %d eligible, %d collected\n", r.Counts["kept"],
|
|
r.Counts["eligible"], r.Counts["collected"]), OK: true, Answer: r}, nil
|
|
}},
|
|
{Name: seat + "held", Description: "Whether the store holds each reference given: held, gone or unknown with why.",
|
|
Run: func(args map[string]any) (any, error) {
|
|
a, err := h.Held(listOf(args["references"]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return verbAnswer{Output: fmt.Sprintf("the artifact store at %s holds %d of the %d reference(s) asked\n",
|
|
a.Store, len(a.Held), len(a.Held)+len(a.Gone)+len(a.Unknown)), OK: true, Answer: a}, nil
|
|
}},
|
|
{Name: seat + "collect", Description: "The sweep now: a dry run without confirm; with confirm and why, every kept " +
|
|
"archive held, then each eligible artifact let go of, each recorded in the hand-act log.",
|
|
Run: func(args map[string]any) (any, error) {
|
|
most, err := count(args, "most", MostPerSweep, 1, MostAtAll)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
a, err := h.Collect(text(args, "why"), text(args, "confirm") == "true", most)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return verbAnswer{Output: fmt.Sprintf("let go of %d, would let go of %d, %d left\n", len(a.LetGo),
|
|
len(a.WouldLetGo), a.Left), OK: true, Answer: a}, nil
|
|
}},
|
|
{Name: seat + "mirrors", Description: "The bases the mesh copied into its store, each kept (a kept build stood on " +
|
|
"it), eligible (only builds no longer kept stood on it) or unrecorded (no build the builder's log holds stood " +
|
|
"on it: never removed).",
|
|
Run: func(args map[string]any) (any, error) {
|
|
if text(args, "record") != "" {
|
|
return nil, fmt.Errorf("mirrors records nothing by hand on this seat: a copy is recorded by the builds the " +
|
|
"builder's log says stood on it (novox/hq ADR 0571 clause 1)")
|
|
}
|
|
m, err := h.MirrorsNow()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return verbAnswer{Output: fmt.Sprintf("%d copies\n", len(m.Copies)), OK: true, Answer: m}, nil
|
|
}},
|
|
{Name: seat + "images", Description: "Every container image one machine's wants and haves name.",
|
|
Run: func(args map[string]any) (any, error) {
|
|
node := text(args, "node")
|
|
if node == "" {
|
|
return nil, fmt.Errorf("images names the machine")
|
|
}
|
|
address := ""
|
|
if d, err := h.Door(); err == nil {
|
|
address = d.Address()
|
|
}
|
|
a, err := h.ImagesOf(node, address)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return verbAnswer{Output: fmt.Sprintf("%s: %d images\n", node, len(a.Images)), OK: true, Answer: a}, nil
|
|
}},
|
|
}
|
|
}
|
|
|
|
// listOf is a list argument: a list, or one text separated by commas.
|
|
func listOf(v any) []string {
|
|
var out []string
|
|
add := func(s string) {
|
|
for _, p := range strings.Split(s, ",") {
|
|
if p = strings.TrimSpace(p); p != "" && !contains(out, p) {
|
|
out = append(out, p)
|
|
}
|
|
}
|
|
}
|
|
switch x := v.(type) {
|
|
case string:
|
|
add(x)
|
|
case []any:
|
|
for _, e := range x {
|
|
if s, ok := e.(string); ok {
|
|
add(s)
|
|
}
|
|
}
|
|
}
|
|
return out
|
|
}
|