feat(go): factory batch 3 — tool-protocol CLI (contract BUILDER-2026-10-07T23:01:39Z-0457fe-unknown)

The module-family JSON CLI over the ported protocol core:
- ops: validate / normalize_text / ollama / visible / contains_internal /
  registry_shape / list-tools / requires-approval (argv compat)
- registry_shape: 19 tools, order preserved — the frozen registry
  set-equality check surfaced through the CLI
- requires-approval: the auth boundary op (bash→run_command alias
  canonicalized before the check; read-only set mirrored)

All gates green. The factory continues — batch 4 scopes next.
This commit is contained in:
Nick committed 2026-10-08 00:05:05 +01:00
1 parent 630642f499
commit d78d8d4dc4
5 files changed
+6028 -348

No files matched your search

+124
View File
@@ -0,0 +1,124 @@
package main
// cli.go — factory batch 3: the module-family JSON CLI (curator-core
// convention: one JSON op per invocation) over the ported protocol core.
// Ops: validate, normalize_text, ollama, visible, contains_internal,
// registry_shape.
import (
"encoding/json"
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "usage: tool-protocol <validate|normalize_text|ollama|visible|contains_internal|registry_shape> [json]")
os.Exit(1)
}
cmd := os.Args[1]
// argv-mode ops (no JSON body): requires-approval
if cmd == "requires-approval" {
name := ""
if len(os.Args) > 2 {
name = os.Args[2]
}
if alias, ok := toolAliases[name]; ok {
name = alias
}
_, known := RegistryTools[name]
ro := readOnlyToolsForProtocol[name]
emit(map[string]interface{}{"known": known, "requires_approval": known && !ro})
return
}
var req map[string]interface{}
if len(os.Args) > 2 {
if err := json.Unmarshal([]byte(os.Args[2]), &req); err != nil {
emitErr("bad JSON arg: " + err.Error())
}
}
switch cmd {
case "validate":
reqAny, _ := req["request"].(map[string]interface{})
rb, _ := json.Marshal(reqAny)
var request ToolRequest
if err := json.Unmarshal(rb, &request); err != nil {
emitErr(err.Error())
}
validated, err := ValidateToolRequest(request)
if err != nil {
emit(map[string]interface{}{"ok": false, "error": err.Error()})
return
}
emit(map[string]interface{}{"ok": true, "result": validated})
case "normalize_text":
text, _ := req["text"].(string)
requests, err := NormalizeTextToolCalls(text)
if err != nil {
emit(map[string]interface{}{"ok": false, "error": err.Error()})
return
}
emit(map[string]interface{}{"ok": true, "result": requests})
case "ollama":
msgAny, _ := req["message"].(map[string]interface{})
requests, err := NormalizeOllamaToolCalls(msgAny)
if err != nil {
emit(map[string]interface{}{"ok": false, "error": err.Error()})
return
}
emit(map[string]interface{}{"ok": true, "result": requests})
case "visible":
text, _ := req["text"].(string)
visible, err := ExtractVisibleText(text)
if err != nil {
emit(map[string]interface{}{"ok": false, "error": err.Error()})
return
}
emit(map[string]interface{}{"ok": true, "result": map[string]interface{}{"visible": visible}})
case "contains_internal":
text, _ := req["text"].(string)
emit(map[string]interface{}{"ok": true, "result": map[string]interface{}{"contains": ContainsInternalProtocol(text)}})
case "registry_shape":
// set-equality with the frozen registry: 19 tools, order preserved
var defs []map[string]interface{}
json.Unmarshal(registryJSON, &defs)
var order []string
for _, d := range defs {
n, _ := d["name"].(string)
order = append(order, n)
}
emit(map[string]interface{}{"ok": true, "result": map[string]interface{}{
"count": len(RegistryTools), "order": order,
}})
case "list-tools":
var names []string
for name := range RegistryTools {
names = append(names, name)
}
emit(map[string]interface{}{"tools": names})
default:
emitErr("unknown op: " + cmd)
}
}
func emit(v map[string]interface{}) {
enc := json.NewEncoder(os.Stdout)
enc.SetEscapeHTML(false)
_ = enc.Encode(v)
}
func emitErr(msg string) {
emit(map[string]interface{}{"error": msg})
os.Exit(1)
}
// readOnlyToolsForProtocol — the auth boundary (mirrors tool-executor's
// readOnlyTools — the frozen 12-tool set; kept here for the protocol
// side's requires-approval op).
var readOnlyToolsForProtocol = map[string]bool{
"read_file": true, "glob_files": true, "grep_files": true,
"list_directory": true, "git_diff": true, "git_log": true,
"repo_map": true, "read_persona": true, "query_memory": true,
"check_growth": true, "diagnose_behavior": true,
"find_capability": true,
}
-60
View File
@@ -10,10 +10,7 @@
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
)
type ToolRequest struct {
@@ -79,61 +76,4 @@ func validate(req ToolRequest) (ToolEvent, bool) {
return ToolEvent{Kind: kind, Request: req}, true
}
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "usage: tool-protocol <validate|list-tools|requires-approval> [args...]")
os.Exit(1)
}
cmd := os.Args[1]
args := os.Args[2:]
switch cmd {
case "validate":
if len(args) < 1 {
fmt.Fprintln(os.Stderr, "usage: tool-protocol validate <request-json>")
os.Exit(1)
}
var req ToolRequest
if err := json.Unmarshal([]byte(args[0]), &req); err != nil {
out, _ := json.Marshal(ToolEvent{Kind: "error", Error: fmt.Sprintf("invalid JSON: %v", err)})
fmt.Println(string(out))
return
}
event, ok := validate(req)
out, _ := json.MarshalIndent(event, "", " ")
fmt.Println(string(out))
if !ok {
os.Exit(1)
}
case "list-tools":
var names []string
for name := range TOOL_INDEX {
names = append(names, name)
}
out, _ := json.MarshalIndent(names, "", " ")
fmt.Println(string(out))
case "requires-approval":
if len(args) < 1 {
fmt.Fprintln(os.Stderr, "usage: tool-protocol requires-approval <tool-name>")
os.Exit(1)
}
name := args[0]
if alias, ok := ALIASES[name]; ok {
name = alias
}
def, ok := TOOL_INDEX[name]
if !ok {
fmt.Println("null")
return
}
out, _ := json.Marshal(map[string]bool{"requires_approval": def.RequiresApproval})
fmt.Println(string(out))
default:
fmt.Fprintf(os.Stderr, "unknown command: %s\n", cmd)
os.Exit(1)
}
_ = strings.TrimSpace("")
}
Binary file not shown.
File diff suppressed because it is too large. Load diff
+296 -288
View File
File diff suppressed because it is too large. Load diff