ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk carries no composition rule. The catalogue functions only the node-engine's composition reaches (Resolve, Resolution's Compose, Declaration, DataItems, LeftOut, Rules and the rest, the settings, placeholder and template refusals, the rendering helpers) are copied with their tests into internal/compose/resolution; a method of a mesh-sdk shape becomes a function taking it first. The composition calls its own copies, and the captured catalogue its tests read lives here now, shared by mesh-compose's tests. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
60 lines
2.1 KiB
Go
60 lines
2.1 KiB
Go
package resolution
|
|
|
|
import (
|
|
"maps"
|
|
"slices"
|
|
)
|
|
|
|
// schema is a JSON schema for an object of string properties, which is every argument the verbs
|
|
// above take. Kept small on purpose: a schema an agent cannot read is a tool it cannot call. The
|
|
// switches are the properties that are "true" or "false" and nothing else, said in the schema as an
|
|
// enum so a caller sees it and the verb can refuse any other word rather than read it as false.
|
|
//
|
|
// **The schema is the whole of what a verb takes** (novox/hq issue 244): an argument it does not
|
|
// name is refused when the verb is called, never passed over.
|
|
// withObject adds to a verb's input s the property name, an object of the string fields given, each required.
|
|
func withObject(s map[string]any, name, description string, fields map[string]string) map[string]any {
|
|
inner := schema(fields, slices.Sorted(maps.Keys(fields)))
|
|
inner["description"], inner["additionalProperties"] = description, false
|
|
s["properties"].(map[string]any)[name] = inner
|
|
return s
|
|
}
|
|
|
|
func schema(properties map[string]string, required []string, switches ...string) map[string]any {
|
|
isSwitch := map[string]bool{}
|
|
for _, s := range switches {
|
|
if _, declared := properties[s]; !declared {
|
|
panic("a switch that is not a property: " + s)
|
|
}
|
|
isSwitch[s] = true
|
|
}
|
|
props := map[string]any{}
|
|
for name, description := range properties {
|
|
p := map[string]any{"type": "string", "description": description}
|
|
if isSwitch[name] {
|
|
p["enum"] = []string{"true", "false"}
|
|
}
|
|
props[name] = p
|
|
}
|
|
out := map[string]any{"type": "object", "properties": props}
|
|
if len(required) > 0 {
|
|
out["required"] = required
|
|
}
|
|
return out
|
|
}
|
|
|
|
// listed makes the named properties of a schema lists of text: a caller gives them as a JSON array (or, as
|
|
// any argument, one text separated by commas).
|
|
func listed(in map[string]any, names ...string) map[string]any {
|
|
props, _ := in["properties"].(map[string]any)
|
|
for _, n := range names {
|
|
p, _ := props[n].(map[string]any)
|
|
if p == nil {
|
|
panic("a list that is not a property: " + n)
|
|
}
|
|
props[n] = map[string]any{"type": "array", "items": map[string]any{"type": "string"},
|
|
"description": p["description"]}
|
|
}
|
|
return in
|
|
}
|