Take the catalogue's composition rules into the node-engine
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
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user