Files
mesh-delivery/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/toolchains.go
T
jschoubben 71a35a6376 MV1: move contracts and sdk under modules/, importers follow
The delivery repository's contracts and SDK live under modules/ as
mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths
renamed to match the folders (the TypeScript names already did), and
every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools
and mesh-sdk follows in the same group: a design as it should be, one
path per module, checked by the group's check building every importer.

Builds: design 47 G §427, §88

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:09:56 +01:00

83 lines
3.7 KiB
Go

package main
import (
"fmt"
"sort"
"strings"
"time"
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/buildstep"
stdio "git.novox.be/novox/mesh-sdk/go"
)
// heardState is the builder's state toolchains-heard as the tools bundle reads and deletes in it.
type heardState interface {
Keys() ([]string, error)
Get(key string) (*stdio.StateEntry, error)
Delete(key string) error
}
// toolchainsTools are builder_toolchains, which lists the toolchains the builder heard from the build seats, and
// builder_toolchains_drop, which deletes one key and writes it in the hand-act log (design 47 G §604, §546). The drop is
// of class act, with the default callers: the bus refuses another caller.
func toolchainsTools(st heardState, acts meshhandactsclient.Recorder, now func() time.Time) []stdio.Tool {
return []stdio.Tool{
{Name: buildrun.ToolchainsTool,
Description: "The toolchains the builder heard from the build seats' toolchain-reported, one key <node>.<language> each: its version, " +
"recipe, the digest of its toolchain program and when it was said. The builder agrees a language's version from these, and forgets a node's " +
"when the node-engine seat says the build module stopped there. Read-only.",
Input: map[string]any{"type": "object", "properties": map[string]any{}},
Run: func(map[string]any) (any, error) {
keys, err := st.Keys()
if err != nil {
return nil, err
}
sort.Strings(keys)
rows := []map[string]any{}
for _, k := range keys {
e, err := st.Get(k)
if err != nil || e == nil {
continue
}
row := map[string]any{"key": k}
if tc, err := buildstep.DecodeToolchain(e.Value); err != nil {
row["error"] = err.Error()
} else {
row["version"], row["recipe"], row["digest"], row["said"] = tc.Version, tc.Recipe, tc.Digest, tc.At
}
rows = append(rows, row)
}
return map[string]any{"toolchains": rows}, nil
}},
{Name: buildrun.ToolchainsDropTool,
Description: "Drop one node's toolchain of a language from what the builder heard, by hand: a build module that left a node and said nothing. " +
"The builder agrees without it; the node's build module says it again at its start and on each change. Written in the hand-act log (mesh-hand-acts).",
Input: map[string]any{"type": "object", "required": []string{"key", "why"}, "properties": map[string]any{
"key": map[string]any{"type": "string", "description": "<node>.<language>, as builder_toolchains lists it"},
"why": map[string]any{"type": "string", "description": "why, in plain words"}}},
Run: func(args map[string]any) (any, error) {
str := func(k string) string { s, _ := args[k].(string); return strings.TrimSpace(s) }
key, why := str("key"), str("why")
if _, _, err := buildstep.ParseToolchainKey(key); err != nil {
return nil, err
}
if why == "" {
return nil, fmt.Errorf("why is required")
}
if e, err := st.Get(key); err != nil || e == nil {
return nil, fmt.Errorf("%s holds no key %s", buildrun.ToolchainsHeardState, key)
}
if _, err := acts.Record(meshhandactsclient.Request{What: fmt.Sprintf("dropped the toolchain %s from what the builder heard", key),
Why: why, Cause: buildrun.ToolchainsDropTool, Verb: "toolchains-drop"}); err != nil {
return nil, fmt.Errorf("the hand act was not recorded through mesh-hand-acts, so nothing was dropped: %w", err)
}
if err := st.Delete(key); err != nil {
return nil, err
}
return map[string]any{"key": key, "dropped": true, "at": now().UTC()}, nil
}},
}
}