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
83 lines
3.7 KiB
Go
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
|
|
}},
|
|
}
|
|
}
|