claude-code: read where it runs from the controller's JSON answer
nodesRunningMe looked for printed lines in what is a JSON list, so every register tool's "also on" hint and every nodes: "all" named no machine.
This commit is contained in:
@@ -163,20 +163,37 @@ func nodesRunningMe() ([]string, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var answer struct {
|
||||
Output string `json:"output"`
|
||||
return NodesRunning(raw, "claude-code"), nil
|
||||
}
|
||||
|
||||
// NodesRunning reads where a module runs from the controller's `modules` answer. The verb runs `module list
|
||||
// --json`, so the answer is a JSON list of {module, on}: the lines of the printed list it was once read as
|
||||
// never came, and every "also on" hint and every `nodes: "all"` named no machine. The printed form, `<module>
|
||||
// … on a, b`, is still read when that is what came.
|
||||
func NodesRunning(raw json.RawMessage, module string) []string {
|
||||
var listed []struct {
|
||||
Module string `json:"module"`
|
||||
On []string `json:"on"`
|
||||
}
|
||||
text := string(raw)
|
||||
if json.Unmarshal(raw, &answer) == nil && answer.Output != "" {
|
||||
text = answer.Output
|
||||
if json.Unmarshal(verbAnswer(raw), &listed) == nil {
|
||||
for _, m := range listed {
|
||||
if m.Module == module {
|
||||
return m.On
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
text := outputOf(raw)
|
||||
if text == "" {
|
||||
text = string(raw)
|
||||
}
|
||||
for _, line := range strings.Split(text, "\n") {
|
||||
if !strings.HasPrefix(line, "claude-code ") {
|
||||
if !strings.HasPrefix(line, module+" ") {
|
||||
continue
|
||||
}
|
||||
_, on, ok := strings.Cut(line, " on ")
|
||||
if !ok || strings.TrimSpace(on) == "nothing" {
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
var out []string
|
||||
for _, n := range strings.Split(on, ",") {
|
||||
@@ -184,9 +201,9 @@ func nodesRunningMe() ([]string, error) {
|
||||
out = append(out, n)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
return out
|
||||
}
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func fingerprintOfFile(path string) any {
|
||||
@@ -264,7 +281,7 @@ func tools(p Paths, servers ServerState, view *ServerView, config ConfigState, c
|
||||
return answer, err
|
||||
}},
|
||||
{Name: "claude_code_guard",
|
||||
Description: "The guard on the agent's shell on this machine (novox/hq ADR 0244): what it refuses — ssh to a mesh machine, writing /etc/hosts or /etc/resolv.conf, HOSTALIASES — the machines and the replaced commands it judges with, the \"instead of\" table rendered into the agent's instructions, and its record of what it refused and what the operator's override let through, newest last.",
|
||||
Description: "The guard on the agent's shell on this machine (novox/hq ADR 0245): what it refuses — ssh to a mesh machine, writing /etc/hosts or /etc/resolv.conf, HOSTALIASES — the machines and the replaced commands it judges with, the \"instead of\" table rendered into the agent's instructions, and its record of what it refused and what the operator's override let through, newest last.",
|
||||
Input: map[string]any{"last": map[string]any{"type": "integer", "description": "how many lines of the record (default 50)"}},
|
||||
Run: func(a map[string]any) (any, error) {
|
||||
last := 50
|
||||
@@ -370,7 +387,7 @@ func persist(what string, attempt func() error, done func(refusals int)) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// The guard on the agent's shell (novox/hq ADR 0244): this binary, run by the agent's hook.
|
||||
// The guard on the agent's shell (novox/hq ADR 0245): this binary, run by the agent's hook.
|
||||
if len(os.Args) == 3 && os.Args[1] == "guard" {
|
||||
os.Exit(runGuard(os.Args[2], os.Stdin, os.Stderr))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user